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 >