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 <[email protected]>:
> Michael Hope <[email protected]> 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
>