prime/src/Runtime/__va_arg.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;
}