summaryrefslogtreecommitdiff
path: root/src/PowerPC_EABI_Support/Runtime/Src/__va_arg.c
blob: b2f5fc5b807301a90d799a9e99240630226a8d86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "__va_arg.h"

#undef __va_arg

void* __va_arg(va_list v_list, int type) {
	char* addr;
	char* reg      = &(v_list->gpr);
	s32 g_reg      = v_list->gpr;
	s32 maxsize    = 8;
	s32 size       = 4;
	s32 increment  = 1;
	s32 even       = 0;
	s32 fpr_offset = 0;
	s32 regsize    = 4;

	if (type == 3) {
		reg        = &(v_list->fpr);
		g_reg      = v_list->fpr;
		size       = 8;
		fpr_offset = 32;
		regsize    = 8;
	}
	if (type == 2) {
		size = 8;
		maxsize--;
		if (g_reg & 1)
			even = 1;
		increment = 2;
	}
	if (g_reg < maxsize) {
		g_reg += even;
		addr = v_list->reg_save_area + fpr_offset + (g_reg * regsize);
		*reg = g_reg + increment;
	} else {
		*reg                    = 8;
		addr                    = v_list->input_arg_area;
		addr                    = (char*)(((u32)(addr) + ((size)-1)) & ~((size)-1));
		v_list->input_arg_area = addr + size;
	}
	if (type == 0)
		addr = *((char**)addr);

	return addr;
}