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