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
>

Reply via email to