Hi,

I am working on a port for a processor that has 32 bit registers but can
only load 16 bit immediates.  I have tried several ways to split moves
with larger immediates into two RTL insns.  One is using a
define_expand:

-------------------------code-----------------------
(define_expand "movsi"
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (match_operand:SI 1 "general_operand" ""))]
  ""
  {
    if (GET_CODE(operands[0]) != REG) {
      operands[1] = force_reg(SImode, operands[1]);
    }
    else if(s17to32_const_int_operand(operands[1],
GET_MODE(operands[1]))){
      emit_move_insn(operands[0],
                     gen_rtx_HIGH(GET_MODE(operands[1]), operands[1]));
      emit_move_insn(operands[0],
                     gen_rtx_LO_SUM(GET_MODE(operands[1]),
                                    operands[0], operands[1]));
      DONE;
    }
  })
------------------------/code-----------------------

With the corresponding define_insns:

-------------------------code-----------------------
(define_insn "movsi_high"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (high:SI (match_operand:SI 1 "immediate_operand" "i")))]
  ""
  "%0.h = #HI(%1)")

(define_insn "movsi_lo_sum"
  [(set (match_operand:SI 0 "register_operand" "+r")
        (lo_sum:SI (match_dup 0)
                   (match_operand:SI 1 "immediate_operand" "i")))]
  ""
  "%0.l = #LO(%1)")
------------------------/code-----------------------

but using this method, I get the following error:

-------------------------error-----------------------
./libgcc2.c:470: error: unrecognizable insn:
(insn 100 99 86 0 ./libgcc2.c:464 (set (reg:SI 10 r10)
        (lo_sum (reg:SI 10 r10)
            (const_int 65536 [0x10000]))) -1 (nil)
    (nil))
./libgcc2.c:470: internal compiler error: in extract_insn, at
recog.c:2083
------------------------/error-----------------------

Why would that RTL not match my movsi_lo_sum define_insn?

I also tried using a define_split:

-------------------------code-----------------------
(define_split
  [(set (match_operand:SI 0 "register_operand" "")
        (match_operand:SI 1 "s17to32_const_int_operand" ""))]
  "reload_completed"
  [(set (match_dup 0)
        (high:SI (match_dup 1)))
   (set (match_dup 0)
        (lo_sum:SI (match_dup 0)
                (match_dup 1)))]
  "")
------------------------/code-----------------------

along with the same define_insns, but then I get the following error:

-------------------------error-----------------------
./crtstuff.c:288: error: insn does not satisfy its constraints:
(insn 103 12 11 0 (set (reg:SI 0 r0)
        (symbol_ref/u:SI ("*.LC0") [flags 0x2])) 18 {movsi_real} (nil)
    (nil))
./crtstuff.c:288: internal compiler error: in
reload_cse_simplify_operands, at postreload.c:378
------------------------/error-----------------------

In other words, that RTL never matches my define_split, even though I
placed it before the more general movsi define_insn and
s17to32_const_int_operand should return 1 for a symbol_ref.

Do you have any idea why either of these attempts do not work?  Which
method do you think is better?  In case you were wondering, here is the
code for s17to32_const_int_operand.  I modified the function
int_2word_operand from the frv port.

-------------------------code-----------------------
int s17to32_const_int_operand(rtx op, enum machine_mode mode
ATTRIBUTE_UNUSED)
{
  HOST_WIDE_INT value;
  REAL_VALUE_TYPE rv;
  long l;

  switch (GET_CODE (op))
    {
    default:
      break;

    case LABEL_REF:
    case SYMBOL_REF:
    case CONST:
      return 1;

    case CONST_INT:
      return ! IN_RANGE_P (INTVAL (op), -0x8000, 0x7FFF);

    case CONST_DOUBLE:
      if (GET_MODE (op) == SFmode)
        {
          REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
          REAL_VALUE_TO_TARGET_SINGLE (rv, l);
          value = l;
          return ! IN_RANGE_P (value, -0x8000, 0x7FFF);
        }
      else if (GET_MODE (op) == VOIDmode)
        {
          value = CONST_DOUBLE_LOW (op);
          return ! IN_RANGE_P (value, -0x8000, 0x7FFF);
        }
      break;
    }

  return 0;
}
------------------------/code-----------------------

Thank you,
Charles J. Tabony

Reply via email to