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