mirror of https://github.com/PrimeDecomp/prime.git
58 lines
1.1 KiB
C
58 lines
1.1 KiB
C
typedef struct {
|
|
char gpr;
|
|
char fpr;
|
|
char reserved[2];
|
|
char* input_arg_area;
|
|
char* reg_save_area;
|
|
} va_list[1];
|
|
|
|
typedef enum {
|
|
ARGPOINTER,
|
|
WORD,
|
|
DOUBLEWORD,
|
|
REAL,
|
|
} _va_arg_type;
|
|
|
|
#define ALIGN(addr, amount) (((unsigned int)(addr) + ((amount)-1)) & ~((amount)-1))
|
|
|
|
void* __va_arg(va_list ap, _va_arg_type type) {
|
|
char* addr;
|
|
char* curGprPtr = &(ap->gpr);
|
|
int curGpr = ap->gpr;
|
|
int max = 8;
|
|
int size = 4;
|
|
int inc = 1;
|
|
int even = 0;
|
|
int fprOffset = 0;
|
|
int regSize = 4;
|
|
|
|
if (type == 3) {
|
|
curGprPtr = &(ap->fpr);
|
|
curGpr = ap->fpr;
|
|
size = 8;
|
|
fprOffset = 8 * 4;
|
|
regSize = 8;
|
|
}
|
|
if (type == 2) {
|
|
size = 8;
|
|
max = max - 1;
|
|
if (curGpr & 1)
|
|
even = 1;
|
|
inc = 2;
|
|
}
|
|
if (curGpr < max) {
|
|
curGpr += even;
|
|
addr = ap->reg_save_area + fprOffset + (curGpr * regSize);
|
|
*curGprPtr = curGpr + inc;
|
|
} else {
|
|
*curGprPtr = 8;
|
|
addr = ap->input_arg_area;
|
|
addr = (char*)ALIGN(addr, size);
|
|
ap->input_arg_area = addr + size;
|
|
}
|
|
if (type == ARGPOINTER)
|
|
addr = *((char**)addr);
|
|
|
|
return addr;
|
|
}
|