Avoiding REG+OFF memory accesses
Sorry for such trivial question, but is there any macro that can be used to avoig GCC to generate REG+OFF memory accesses? So basically to force GCC to break: (mem (plus (reg const_int))) into (set regtmp (plus (reg const_int))) (set (mem regtmp) reg) This w/out writing custom RTL. Can you please Cc me, since I am not subscribed. Thank you. James
Re: Avoiding REG+OFF memory accesses
Ian suggestion worked perfectly, thanks. Can you tell me the macro/function name to look up to work out the secondary reload you're mentioning? - Original Message From: Michael Meissner To: Ian Lance Taylor Cc: Iceman ; g...@gnu.org Sent: Friday, May 8, 2009 11:47:43 AM Subject: Re: Avoiding REG+OFF memory accesses On Wed, May 06, 2009 at 05:01:33PM -0700, Ian Lance Taylor wrote: > Iceman writes: > > > Sorry for such trivial question, but is there any macro that can be used to > > avoig GCC to generate > > REG+OFF memory accesses? > > So basically to force GCC to break: > > > > (mem (plus (reg const_int))) > > > > into > > > > (set regtmp (plus (reg const_int))) > > (set (mem regtmp) reg) > > > > This w/out writing custom RTL. > > Assuming this is a private port, this should happen more or less > automatically if GO_IF_LEGITIMATE_ADDRESS rejects register plus offset > addressing. > > If that is not what you are looking for, I think you need to provide > some more context. And you may also need to provide secondary reload support as well to convert spill addresses into just REG addresses. -- Michael Meissner, IBM 4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA meiss...@linux.vnet.ibm.com
Re: Avoiding REG+OFF memory accesses
Perfect, thank you! - Original Message From: Michael Meissner To: Iceman Cc: Michael Meissner ; Ian Lance Taylor ; g...@gnu.org Sent: Friday, May 8, 2009 3:45:20 PM Subject: Re: Avoiding REG+OFF memory accesses On Fri, May 08, 2009 at 02:05:18PM -0700, Iceman wrote: > > Ian suggestion worked perfectly, thanks. Can you tell me the macro/function > name to look up > to work out the secondary reload you're mentioning? Look up TARGET_SECONDARY_RELOAD in the documentation. Basically it is a hook that is called and the backend can say it needs extra scratch registers for a move, or whether it needs to load a value into another register class. -- Michael Meissner, IBM 4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA meiss...@linux.vnet.ibm.com
varargs target handling
Hi! I'm porting GCC to a software VM with 32 32bit registers, and 32 64bit registers. The 64bit registers are used for DI, SF and DF mode. Pointers and QI, HI and SI modes are handled with 32bit registers. The first 8 32bit parameters of functions are passed into the first 8 32bit registers (g0..7) and the first 8 64bit function parameters are passed in the first 8 64bit registers (d0..7). Everything works fine, but now I've to figure out how to handle varargs functions. Before adding the 64bit registers, I simply had a bit set in the cumulative args, to signal a vararg function, and I was dumping g0..7 in the prologue, that looked like: str.l g0, SP[4] str.l g1, SP[8] str.l g2, SP[12] str.l g3, SP[16] str.l g4, SP[20] str.l g5, SP[24] str.l g6, SP[28] str.l g7, SP[32] push SP mov SP, FP This was working fine, and the code generated by GCC for the _builtin_* va_arg macros were OK. Now having the 64bit registers passed in registers (before they were pushed) confuses me a little WRT the implementation. My idea was to increase REG_PARM_STACK_SPACE to add the space for 8 64bit registers, and dump d0..7 into this area. So instead of (8 * 4) it'd become (8 * 4 + 8 * 8). Then I was thinking in creating a va_list (via xxx_build_builtin_va_list()) like: struct va_list { void *gptr; // Pointer to the first byte after the register dump area void *rptr;// Pointer to the first byte of the 32bit dump area int rcount; // Byte count left for 32bit pulls void *xptr; // Pointer to the first byte of the 64bit dump area int xcount; // Byte count left for 64bit pulls }; In xxx_va_start() I'd initialize va_list like: first_arg = SP + 4; // Skip IP v->gptr = first_arg + 8 * 4 + 8 * 8; v->rptr = first_arg; v->rcount = 8 * 4; v->xptr = v->rptr + 8 * 4; v->xcount = 8 * 8; The in the arg function I'd implement a logic like: if (TYPE_SIZE <= 4) { if (v->rcount > 0) { arg = *(int *) v->rptr; v->rptr += 4; v->rcount -= 4; } else { arg = *(int *) v->gptr; v->gptr += 4; } return arg; } if (v->xcount > 0) { arg = *(long long *) v->xptr; v->xptr += 8; v->xcount -= 8; } else { arg = *(long long *) v->gptr; v->gptr += 8; } return arg; Question. Am I doing it wrong? If yes, what are my best options to tackle this problem? If not, how can I implement the logic above in practical terms? Thank you,