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,