move patterns, emit_move_insn
Georg-Johann Lay
avr@gjlay.de
Tue Mar 3 12:53:00 GMT 2009
Florent DEFAY schrieb:
> Thank you for your help.
>
> Regarding your advice, I tried this implementation:
>
> ___________________________________________________
> ;; movhi
> (define_expand "movhi"
> [(set (match_operand:HI 0 "nonimmediate_operand" "")
> (match_operand:HI 1 "general_operand" "")
> )]
> ""
> ""
> )
>
> (define_insn "movhi1"
> [(set (match_operand:HI 0 "register_operand" "=r,r,m,r")
> (match_operand:HI 1 "general_operand" "r,m,r,i")
> )]
> ""
> "@
> movew\t%1,%0
> movew\t%1,%0
> movew\t%1,%0
> movew\t%1,%0"
> )
> ____________________________________________________
>
> But I get this error then:
>
> e.c:7: error: unrecognizable insn:
> (insn 7 6 8 3 e.c:4 (set (mem/c/i:HI (reg/f:HI 14) [0 i+0 S2 A16])
> (const_int 3 [0x3])) -1 (nil))
The expander may and will produce such patterns, but no insn matches
because predicate 0 "register_operand" of movhi1 is too tight. Try wider
predicate like "nonimmediate_operand"
> I think GCC has to put immediate into memory. The arch can't do that
> directly. GCC should put the immediate in register and then register
> to memory.
Reload will do that. Emit two moves in the expander like this:
(define_expand "movhi"
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
"
{
/* One of the ops has to be in a register. */
if (!register_operand(operand0, HImode)
&& !(register_operand(operand1, HImode))
{
operands[1] = copy_to_mode_reg(HImode, operand1);
}
}")
Georg-Johann
More information about the Gcc-help
mailing list