Thanks for everybodys help. I've gotten things working so I thought I'd quickly write it up.
The architecture I'm working on is deliberatly simple. It has: * An accumulator * Fourteen general purpose registers R10 to R1E * X and Y cache registers each backed by non-coherent (!) caches * A stack backed by the S cache Memory can only be accessed by the X or Y registers. The cache-coherency problem means you can really only use X unless you can tell Y is far away - but that's a problem for another time. It also means you can't use the S stack as a data stack as you can't address it using X. The only addressing is 32 bit word indirect, 8 bit with pre-decrement, and 8 bit with post increment. I allocated R1E to the data stack and R1D to the frame pointer. The general purpose registers are in the DATA_REGS class while X and Y are in ADDR_REGS. Y is marked as fixed to prevent it being used. The implementation is: * Set BASE_REG_CLASS to ADDR_REGS * Set INDEX_REG_CLASS to NO_REGS to reject index addressing * Implement GO_IF_LEGITIMATE_ADDRESS so that it accepts (mem x) but rejects (mem (plus (reg const)) and the others You can't set BASE_REG_CLASS to NO_REGS as (mem x) is treated as (mem (plus (reg 0)) This works fine until you spill a variable. Spills generate offsets relative to the frame pointer. This is OK providing your frame pointer is a member of ADDR_REGS - mine isn't so the resulting fixup generates a offset address which kills the compiler. You can't pretend and put the FP in ADDR_REGS. A non-zero offset will correctly be rejected by GO_IF_LEGITIMATE_ADDRESS and loaded into X, but a zero offset will try to load from R1D. The solution here is to copy the mc68hc11 and use LEGITIMIZE_RELOAD_ADDRESS to recognise the offset and cause another reload. This code: if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == REG && GET_CODE(XEXP(x, 1)) == CONST_INT) { HOST_WIDE_INT value = INTVAL (XEXP (x, 1)); push_reload(x, NULL_RTX, px, NULL, ADDR_REGS, GET_MODE(x), VOIDmode, 0, 0, opnum, reload_type); return true; } does that. I tried TARGET_SECONDARY_RELOAD as well. Similar code to above would correclty generate the code on an 'in' reload but for some reason the code for the 'out' reload would never get inserted. -- Michael 2009/4/29 Michael Hope <micha...@juju.net.nz>: > HI there. I'm working on porting gcc to a new architecture which only > does indirect addressing - there is no indirect with displacement. > > The problem is with spill locations in GCC 4.4.0. The elimination > code correctly elimates the frame and args pointer and replaces it > with register X. The problem is that it then generates indirect with > offset loads to load spilt values. > > Normal usage such as: > > struct foo > { > int a; > int b; > } > > int bar(struct foo* p) > { > return p->b; > } > > is correctly split into load X with p, add four, and then de-references. > > The RTL is generated after the IRA stage. GCC aborts in post reload > with a 'instruction does not satisfy constraints' on: > (insn 183 181 75 3 mandelbrot.c:117 (set (reg:SI 6 R11) > (mem/c:SI (plus:SI (reg:SI 3 X) > (const_int -8 [0xfffffffffffffff8])) [0 %sfp+-8 S4 > A32])) -1 (nil)) > > The movsi it matches against is: > > (define_insn "movsi_insn" > [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,rm,rm,rm,C, rm") > (match_operand:SI 1 "general_operand" "r, m,I, i ,n, rm,C"))] > "" > "@ > LOADACC, %1\;STOREACC, %0 > LOADACC, %1\;STOREACC, %0 > LOADI, #%1\;STOREACC, %0 > LOADLONG, #%1\;STOREACC, %0 > LOADLONG, %1\;STOREACC, %0 > Foo > Bar" > ) > > I believe it fails on the constraints as the 'm' constraint misses as > go_if_legitimate_address only supports (mem (reg)) and not (mem (plus > (reg...))) > > I don't think I had this problem when working against 4.3.3 but I'm not sure. > > Could someone point me in the right direction please? Is it > appropriate to ask such questions on this list? > > -- Michael >