diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2023-02-02 17:29:19 -0400 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2023-02-03 13:27:06 -0400 |
commit | f2eabdb6257c09cf2890dac5e9737912728542af (patch) | |
tree | 3b46f6787185d65605651a0f48776dc9779ce648 /src/Runtime/__va_arg.c | |
parent | eef1dd840b7cecac28c2e6b0574707b90a37d4e7 (diff) |
global: Add rest of Dolphin SDK proper, add MSL, and MetroTRK
Finally, it links properly.
Diffstat (limited to 'src/Runtime/__va_arg.c')
-rw-r--r-- | src/Runtime/__va_arg.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/Runtime/__va_arg.c b/src/Runtime/__va_arg.c new file mode 100644 index 0000000..fd0e182 --- /dev/null +++ b/src/Runtime/__va_arg.c @@ -0,0 +1,57 @@ +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; +} |