Hi,

I am trying to separate move immediates that require more than 16 bits
into two instructions that set the high and low 16 bits of a register
respectively.  Here is my define_expand:

(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(CONSTANT_P(operands[1])
            && (-0x8000 > INTVAL(operands[1]) || INTVAL(operands[1]) >
0x7FFF)){
      emit_move_insn(gen_rtx_SUBREG(HImode, operands[0], 0),
                     gen_rtx_TRUNCATE(HImode, operands[1]));
      emit_move_insn(gen_rtx_SUBREG(HImode, operands[0], 2),
                     gen_rtx_TRUNCATE(HImode, gen_rtx_LSHIFTRT(SImode,
 
operands[1],
                                                               16)));
      DONE;
    }
  }
)

and here are the patterns I intend to match:

(define_insn "movsi_subreg0"
  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
        (truncate:HI (match_operand:SI 1 "immediate_operand" "i")))]
  ""
  "%0.l = #LO(%1)"
)

(define_insn "movsi_subreg1"
  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
        (truncate:HI (lshiftrt:SI (match_operand:SI 1
"immediate_operand" "i")
                                  (const_int 16))))]
  ""
  "%0.h = #HI(%1)"
)

When I try to build, the cross compiler gives the following error:

./crtstuff.c: In function `__do_global_dtors_aux':
./crtstuff.c:261: internal compiler error: in expand_simple_unop, at
optabs.c:2291

Why does this not work?  I think the truncate expression is the problem.
Is this not the way to use truncate?

Thank you,
Charles J. Tabony

Reply via email to