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,


      

Reply via email to