This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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,


      


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]