Thanks for the response Ian.  Doing the define_expand inserts the post
increment but GCC doesn't seem to notice the change in X.

I added this code:

----
(define_expand "movqi"
  [(set (match_operand:QI 0 "nonimmediate_operand")
        (match_operand:QI 1 "general_operand" ""))]
  ""
  {
    if (can_create_pseudo_p () && MEM_P (operands[1]))
      {
        rtx reg = copy_to_reg (XEXP (operands[1], 0));
        emit_insn (gen_movqi_mem (operands[0], reg));
        DONE;
      }
  }
)

; PENDING: The SI here is actually a P
(define_insn "movqi_mem"
  [(set (match_operand:QI 0 "register_operand" "=d")
        (mem:QI (post_inc:SI (match_operand:SI 1 "register_operand" "a"))))]
  ""
  "LOADACC, (%1+)\;STOREACC, %0"
)
----
The 'd' constraint is for data registers and the 'a' for address
registers, which is only the X register due to cache coherency
reasons.

When compiling this test case:
----
uint store5(volatile char* p)
{
  return *p + *p;
}
----
I get the following move2.i.139r.subreg:
---
(insn 3 5 4 2 move2.c:56 (set (reg/v/f:SI 30 [ p ])
        (reg:SI 5 R10 [ p ])) 6 {movsi} (nil))

(note 4 3 7 2 NOTE_INSN_FUNCTION_BEG)

(insn 7 4 8 2 move2.c:57 (set (reg:QI 31)
        (mem:QI (post_inc:SI (reg/v/f:SI 30 [ p ])) [0 S1 A8])) 0
{movqi_mem} (nil))

(insn 8 7 9 2 move2.c:57 (set (reg:SI 27 [ D.1191 ])
        (zero_extend:SI (reg:QI 31))) 24 {zero_extendqisi2} (nil))

(insn 9 8 10 2 move2.c:57 (set (reg:QI 32)
        (mem:QI (post_inc:SI (reg/v/f:SI 30 [ p ])) [0 S1 A8])) 0
{movqi_mem} (nil))

(insn 10 9 11 2 move2.c:57 (set (reg:SI 26 [ D.1193 ])
        (zero_extend:SI (reg:QI 32))) 24 {zero_extendqisi2} (nil))

(insn 11 10 12 2 move2.c:57 (set (reg:SI 33)
        (plus:SI (reg:SI 26 [ D.1193 ])
            (reg:SI 27 [ D.1191 ]))) 9 {addsi3} (nil))

(insn 12 11 16 2 move2.c:57 (set (reg:SI 28 [ <result> ])
        (reg:SI 33)) 6 {movsi} (nil))

(insn 16 12 22 2 move2.c:58 (set (reg/i:SI 5 R10)
        (reg:SI 28 [ <result> ])) 6 {movsi} (nil))

(insn 22 16 0 2 move2.c:58 (use (reg/i:SI 5 R10)) -1 (nil))
---
Instruction 3 copies incoming argument in R10 is copied into pseudo
30.  Pseudo 30 is then used at instruction 7 then instruction 9
without either being reloaded or corrected for the post increment.

-- Michael

2009/4/22 Ian Lance Taylor <i...@google.com>:
> Michael Hope <micha...@juju.net.nz> writes:
>
>> Hi there.  I'm looking at porting GCC to a new architecture which has
>> a quite small instruction set and I'm afraid I can't figure out how to
>> represent unintended side effects on instructions.
>>
>> My current problem is accessing memory.  Reading an aligned 32 bit
>> word is simple using LOADACC, (X).  Half words and bytes are harder as
>> the only instruction available is a load byte with post increment
>> 'LOADACC, (X+)'.
>
> Wow.
>
>> How can I tell GCC that loading a byte also increases the pointer
>> register?  My first version reserved one of the pointer registers and
>> threw away the modified value but this is inefficient.  I suspect that
>> some type of clobber or define_expand is required but I can't figure
>> it out.
>
> Well, you can use a define_expand to generate the move in the first
> place.  If can_create_pseudo_p() returns true, then you can call
> copy_to_reg (addr) to get the address into a register, and you can
> generate the post increment.
>
> (define_expand "movhi"
>  ...
>  if (can_create_pseudo_p () && MEM_P (operands[1]))
>    {
>      rtx reg = copy_to_reg (XEXP (operands[1], 0));
>      emit_insn (gen_movhi_insn (operands[0], reg));
>      DONE;
>    }
>  ...
> )
>
> (define_insn "movhi_insn"
>  [(set (match_operand:HI 0 ...)
>        (mem:HI (post_inc:P (match_operand:P 1 "register_operand" ...))))]
>  ...
> )
>
> The difficulties are going to come in reload.  Reload will want to load
> and store 16-bit values in order to spill registers.  You will need a
> scratch register to dothis, and that means that you need to implement
> TARGET_SECONDARY_RELOAD.  This is complicated:read the docs carefully
> and look at the existing examples.
>
> Ian
>

Reply via email to