summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile139
-rw-r--r--lib/alloca-arm.S8
-rw-r--r--lib/alloca86-bt.S2
-rw-r--r--lib/alloca86.S6
-rw-r--r--lib/alloca86_64-bt.S6
-rw-r--r--lib/alloca86_64.S12
-rw-r--r--lib/armeabi.c12
-rw-r--r--lib/armflush.c58
-rw-r--r--lib/bcheck.c24
-rw-r--r--lib/lib-arm64.c12
-rw-r--r--lib/libtcc1.c144
-rw-r--r--lib/va_list.c65
12 files changed, 243 insertions, 245 deletions
diff --git a/lib/Makefile b/lib/Makefile
index e61437e..0c1ec54 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,108 +5,69 @@
TOP = ..
include $(TOP)/Makefile
VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib
+T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
+X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
+BIN = $(TOP)/$(X)libtcc1.a
-ifndef TARGET
- # we're building the native libtcc1.a
- ifdef CONFIG_WIN32
- ifeq ($(ARCH),x86-64)
- TARGET = x86_64-win32
- else
- TARGET = i386-win32
- endif
- # using tcc
- else ifeq ($(ARCH),i386)
- TARGET = i386
- XCC = $(CC) # using gcc
- else ifeq ($(ARCH),x86-64)
- TARGET = x86_64
- XCC = $(CC) # using gcc
- else ifeq ($(ARCH),arm)
- TARGET = arm
- XCC = $(CC) # using gcc
- else ifeq ($(ARCH),arm64)
- TARGET = arm64
- endif
- BCHECK_O = bcheck.o
-endif
-
-DIR = $(TARGET)
+XTCC ?= $(TOP)/$(X)tcc$(EXESUF)
+XCC = $(XTCC)
+XAR = $(XTCC) -ar
+XFLAGS-unx = -B$(TOPSRC)
+XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include
+XFLAGS = $(XFLAGS$(XCFG))
+XCFG = $(or $(findstring -win,$T),-unx)
-native : ../libtcc1.a
-cross : $(DIR)/libtcc1.a
+# in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes
+arm-libtcc1-usegcc ?= no
-native : TCC = $(TOP)/tcc$(EXESUF)
-cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
-
-I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
-X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BCHECK_O)
-ARM_O = libtcc1.o armeabi.o alloca-arm.o
-ARM64_O = lib-arm64.o
-WIN32_O = crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
-
-# build TCC runtime library to contain PIC code, so it can be linked
-# into shared libraries
-PICFLAGS = -fPIC
-
-ifeq "$(TARGET)" "i386-win32"
- OBJ = $(addprefix $(DIR)/,$(I386_O) $(WIN32_O))
- TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
- XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
- XAR = $(DIR)/tiny_libmaker$(EXESUF)
- XFLAGS = $(TGT)
-else ifeq "$(TARGET)" "x86_64-win32"
- OBJ = $(addprefix $(DIR)/,$(X86_64_O) $(WIN32_O))
- TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
- XCC = $(TCC) -B$(TOPSRC)/win32 -I$(TOPSRC)/include
- XAR = $(DIR)/tiny_libmaker$(EXESUF)
- XFLAGS = $(TGT)
-else ifeq "$(TARGET)" "i386"
- OBJ = $(addprefix $(DIR)/,$(I386_O))
- TGT = -DTCC_TARGET_I386
- XCC ?= $(TCC) -B$(TOPSRC)
-else ifeq "$(TARGET)" "x86_64"
- OBJ = $(addprefix $(DIR)/,$(X86_64_O))
- TGT = -DTCC_TARGET_X86_64
- XCC ?= $(TCC) -B$(TOPSRC)
-else ifeq "$(TARGET)" "arm"
- OBJ = $(addprefix $(DIR)/,$(ARM_O))
- TGT = -DTCC_TARGET_ARM
- XCC ?= $(TCC) -B$(TOPSRC)
-else ifeq "$(TARGET)" "arm64"
- OBJ = $(addprefix $(DIR)/,$(ARM64_O))
- TGT = -DTCC_TARGET_ARM64
- XCC ?= $(TCC) -B$(TOPSRC)
-else
- $(error libtcc1.a not supported on target '$(TARGET)')
+ifeq "$($(T)-libtcc1-usegcc)" "yes"
+ XCC = $(CC)
+ XAR = $(AR)
+ XFLAGS = $(CFLAGS) -fPIC
endif
-XFLAGS ?= $(CFLAGS) $(PICFLAGS) $(TGT)
+# only for native compiler
+$(X)BCHECK_O = bcheck.o
-ifeq ($(TARGETOS),Darwin)
- XAR = $(DIR)/tiny_libmaker$(EXESUF)
- XFLAGS += -D_ANSI_SOURCE
+ifeq ($(CONFIG_musl)$(CONFIG_uClibc),yes)
BCHECK_O =
endif
-ifdef XAR
-AR = $(XAR)
+ifdef CONFIG_OSX
+ XFLAGS += -D_ANSI_SOURCE
endif
-$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR)
- $(AR) rcs $@ $(OBJ)
-$(DIR)/%.o : %.c
- $(XCC) -c $< -o $@ $(XFLAGS)
-$(DIR)/%.o : %.S
+I386_O = libtcc1.o alloca86.o alloca86-bt.o
+X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o
+ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o
+ARM64_O = lib-arm64.o
+WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
+
+OBJ-i386 = $(I386_O) $(BCHECK_O)
+OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O)
+OBJ-x86_64-osx = $(X86_64_O) va_list.o
+OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O)
+OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O)
+OBJ-arm64 = $(ARM64_O)
+OBJ-arm = $(ARM_O)
+OBJ-arm-fpa = $(ARM_O)
+OBJ-arm-fpa-ld = $(ARM_O)
+OBJ-arm-vfp = $(ARM_O)
+OBJ-arm-eabi = $(ARM_O)
+OBJ-arm-eabihf = $(ARM_O)
+OBJ-arm-wince = $(ARM_O) $(WIN_O)
+
+$(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T))
+ $(XAR) rcs $@ $^
+
+$(X)%.o : %.c
$(XCC) -c $< -o $@ $(XFLAGS)
-# windows : utilities
-$(DIR)/tiny_%$(EXESUF) : $(TOPSRC)/win32/tools/tiny_%.c
- $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(TGT)
-$(OBJ) $(XAR) : $(DIR)/exists
+$(X)%.o : %.S
+ $(XCC) -c $< -o $@ $(XFLAGS)
-%/exists :
- mkdir -p $(DIR)
- @echo $@ > $@
+$(X)crt1w.o : crt1.c
+$(X)wincrt1w.o : wincrt1.c
clean :
- rm -rf i386-win32 x86_64-win32 i386 x86_64 arm arm64
+ rm -f *.a *.o $(BIN)
diff --git a/lib/alloca-arm.S b/lib/alloca-arm.S
index 9deae63..68556e3 100644
--- a/lib/alloca-arm.S
+++ b/lib/alloca-arm.S
@@ -3,9 +3,15 @@
.global alloca
.type alloca, %function
alloca:
+#ifdef __TINYC__
+ .int 0xe060d00d
+ .int 0xe3cdd007
+ .int 0xe1a0000d
+ .int 0xe1a0f00e
+#else
rsb sp, r0, sp
bic sp, sp, #7
mov r0, sp
mov pc, lr
+#endif
.size alloca, .-alloca
- .section .note.GNU-stack,"",%progbits
diff --git a/lib/alloca86-bt.S b/lib/alloca86-bt.S
index 5215505..4f95cf1 100644
--- a/lib/alloca86-bt.S
+++ b/lib/alloca86-bt.S
@@ -11,7 +11,7 @@ __bound_alloca:
and $-4,%eax
jz p6
-#ifdef TCC_TARGET_PE
+#ifdef _WIN32
p4:
cmp $4096,%eax
jbe p5
diff --git a/lib/alloca86.S b/lib/alloca86.S
index a17e07f..bb7a2c2 100644
--- a/lib/alloca86.S
+++ b/lib/alloca86.S
@@ -10,7 +10,7 @@ alloca:
and $-4,%eax
jz p3
-#ifdef TCC_TARGET_PE
+#ifdef _WIN32
p1:
cmp $4096,%eax
jbe p2
@@ -28,8 +28,4 @@ p3:
push %edx
ret
-/* mark stack as nonexecutable */
-#if defined __ELF__ && defined __linux__
- .section .note.GNU-stack,"",@progbits
-#endif
/* ---------------------------------------------- */
diff --git a/lib/alloca86_64-bt.S b/lib/alloca86_64-bt.S
index 1f196bb..4cbad90 100644
--- a/lib/alloca86_64-bt.S
+++ b/lib/alloca86_64-bt.S
@@ -4,7 +4,7 @@
.globl __bound_alloca
__bound_alloca:
-#ifdef TCC_TARGET_PE
+#ifdef _WIN32
# bound checking is not implemented
pop %rdx
mov %rcx,%rax
@@ -53,8 +53,4 @@ p3:
ret
#endif
-/* mark stack as nonexecutable */
-#if defined __ELF__ && defined __linux__
- .section .note.GNU-stack,"",@progbits
-#endif
/* ---------------------------------------------- */
diff --git a/lib/alloca86_64.S b/lib/alloca86_64.S
index 4a74104..ae3c97d 100644
--- a/lib/alloca86_64.S
+++ b/lib/alloca86_64.S
@@ -5,7 +5,7 @@
alloca:
pop %rdx
-#ifdef TCC_TARGET_PE
+#ifdef _WIN32
mov %rcx,%rax
#else
mov %rdi,%rax
@@ -14,7 +14,7 @@ alloca:
and $-16,%rax
jz p3
-#ifdef TCC_TARGET_PE
+#ifdef _WIN32
p1:
cmp $4096,%rax
jbe p2
@@ -27,16 +27,8 @@ p2:
sub %rax,%rsp
mov %rsp,%rax
-#ifdef TCC_TARGET_PE
- add $32,%rax
-#endif
-
p3:
push %rdx
ret
-/* mark stack as nonexecutable */
-#if defined __ELF__ && defined __linux__
- .section .note.GNU-stack,"",@progbits
-#endif
/* ---------------------------------------------- */
diff --git a/lib/armeabi.c b/lib/armeabi.c
index b12d164..a59640d 100644
--- a/lib/armeabi.c
+++ b/lib/armeabi.c
@@ -19,7 +19,19 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
+#ifdef __TINYC__
+#define INT_MIN (-2147483647 - 1)
+#define INT_MAX 2147483647
+#define UINT_MAX 0xffffffff
+#define LONG_MIN (-2147483647L - 1)
+#define LONG_MAX 2147483647L
+#define ULONG_MAX 0xffffffffUL
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-9223372036854775807LL - 1)
+#define ULLONG_MAX 0xffffffffffffffffULL
+#else
#include <limits.h>
+#endif
/* We rely on the little endianness and EABI calling convention for this to
work */
diff --git a/lib/armflush.c b/lib/armflush.c
new file mode 100644
index 0000000..eae3260
--- /dev/null
+++ b/lib/armflush.c
@@ -0,0 +1,58 @@
+/* armflush.c - flush the instruction cache
+
+ __clear_cache is used in tccrun.c, It is a built-in
+ intrinsic with gcc. However tcc in order to compile
+ itself needs this function */
+
+#ifdef __TINYC__
+
+/* syscall wrapper */
+unsigned syscall(unsigned syscall_nr, ...);
+
+/* arm-tcc supports only fake asm currently */
+__asm__(
+ ".global syscall\n"
+ "syscall:\n"
+ ".int 0xe92d4080\n" // push {r7, lr}
+ ".int 0xe1a07000\n" // mov r7, r0
+ ".int 0xe1a00001\n" // mov r0, r1
+ ".int 0xe1a01002\n" // mov r1, r2
+ ".int 0xe1a02003\n" // mov r2, r3
+ ".int 0xef000000\n" // svc 0x00000000
+ ".int 0xe8bd8080\n" // pop {r7, pc}
+ );
+
+/* from unistd.h: */
+#if defined(__thumb__) || defined(__ARM_EABI__)
+# define __NR_SYSCALL_BASE 0x0
+#else
+# define __NR_SYSCALL_BASE 0x900000
+#endif
+#define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000)
+#define __ARM_NR_cacheflush (__ARM_NR_BASE+2)
+
+#else
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdio.h>
+
+#endif
+
+/* Flushing for tccrun */
+void __clear_cache(void *beginning, void *end)
+{
+/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
+ * However, there is no ARM asm parser in tcc so we use it for now */
+#if 1
+ syscall(__ARM_NR_cacheflush, beginning, end, 0);
+#else
+ __asm__ ("push {r7}\n\t"
+ "mov r7, #0xf0002\n\t"
+ "mov r2, #0\n\t"
+ "swi 0\n\t"
+ "pop {r7}\n\t"
+ "ret");
+#endif
+}
diff --git a/lib/bcheck.c b/lib/bcheck.c
index d3b9955..90f0ad2 100644
--- a/lib/bcheck.c
+++ b/lib/bcheck.c
@@ -21,10 +21,15 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
-#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) \
- && !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
+
+#if !defined(__FreeBSD__) \
+ && !defined(__FreeBSD_kernel__) \
+ && !defined(__DragonFly__) \
+ && !defined(__OpenBSD__) \
+ && !defined(__NetBSD__)
#include <malloc.h>
#endif
+
#if !defined(_WIN32)
#include <unistd.h>
#endif
@@ -45,11 +50,14 @@
#define CONFIG_TCC_MALLOC_HOOKS
#define HAVE_MEMALIGN
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
- || defined(__DragonFly__) || defined(__dietlibc__) \
- || defined(__UCLIBC__) || defined(__OpenBSD__) || defined(__NetBSD__) \
- || defined(_WIN32) || defined(TCC_UCLIBC)
-#warning Bound checking does not support malloc (etc.) in this environment.
+#if defined(__FreeBSD__) \
+ || defined(__FreeBSD_kernel__) \
+ || defined(__DragonFly__) \
+ || defined(__OpenBSD__) \
+ || defined(__NetBSD__) \
+ || defined(__dietlibc__) \
+ || defined(_WIN32)
+//#warning Bound checking does not support malloc (etc.) in this environment.
#undef CONFIG_TCC_MALLOC_HOOKS
#undef HAVE_MEMALIGN
#endif
@@ -236,7 +244,7 @@ BOUND_PTR_INDIR(16)
#if defined(__GNUC__) && (__GNUC__ >= 6)
/*
- * At least gcc 6.2 complains when __builtin_frame_address is used whith
+ * At least gcc 6.2 complains when __builtin_frame_address is used with
* nonzero argument.
*/
#pragma GCC diagnostic push
diff --git a/lib/lib-arm64.c b/lib/lib-arm64.c
index 42d5936..b8fd9e8 100644
--- a/lib/lib-arm64.c
+++ b/lib/lib-arm64.c
@@ -9,8 +9,20 @@
* without any warranty.
*/
+#ifdef __TINYC__
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned uint32_t;
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+void *memcpy(void*,void*,__SIZE_TYPE__);
+#else
#include <stdint.h>
#include <string.h>
+#endif
void __clear_cache(void *beg, void *end)
{
diff --git a/lib/libtcc1.c b/lib/libtcc1.c
index c3ff7fe..0e46618 100644
--- a/lib/libtcc1.c
+++ b/lib/libtcc1.c
@@ -107,10 +107,10 @@ union float_long {
};
/* XXX: we don't support several builtin supports for now */
-#if !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM)
+#if !defined __x86_64__ && !defined __arm__
/* XXX: use gcc/tcc intrinsic ? */
-#if defined(TCC_TARGET_I386)
+#if defined __i386__
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
: "=r" ((USItype) (sh)), \
@@ -478,18 +478,6 @@ long long __ashldi3(long long a, int b)
#endif
}
-long long __tcc_cvt_ftol(long double x)
-{
- unsigned c0, c1;
- long long ret;
- __asm__ __volatile__ ("fnstcw %0" : "=m" (c0));
- c1 = c0 | 0x0C00;
- __asm__ __volatile__ ("fldcw %0" : : "m" (c1));
- __asm__ __volatile__ ("fistpll %0" : "=m" (ret));
- __asm__ __volatile__ ("fldcw %0" : : "m" (c0));
- return ret;
-}
-
#endif /* !__x86_64__ */
/* XXX: fix tcc's code generator to do this instead */
@@ -562,6 +550,13 @@ unsigned long long __fixunssfdi (float a1)
return 0;
}
+long long __fixsfdi (float a1)
+{
+ long long ret; int s;
+ ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1);
+ return s ? ret : -ret;
+}
+
unsigned long long __fixunsdfdi (double a1)
{
register union double_long dl1;
@@ -587,6 +582,14 @@ unsigned long long __fixunsdfdi (double a1)
return 0;
}
+long long __fixdfdi (double a1)
+{
+ long long ret; int s;
+ ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1);
+ return s ? ret : -ret;
+}
+
+#ifndef __arm__
unsigned long long __fixunsxfdi (long double a1)
{
register union ldouble_long dl1;
@@ -610,121 +613,10 @@ unsigned long long __fixunsxfdi (long double a1)
return 0;
}
-long long __fixsfdi (float a1)
-{
- long long ret; int s;
- ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1);
- return s ? ret : -ret;
-}
-
-long long __fixdfdi (double a1)
-{
- long long ret; int s;
- ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1);
- return s ? ret : -ret;
-}
-
long long __fixxfdi (long double a1)
{
long long ret; int s;
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
return s ? ret : -ret;
}
-
-#if defined(TCC_TARGET_X86_64) && !defined(_WIN64)
-
-#ifndef __TINYC__
-# include <stdlib.h>
-# include <stdio.h>
-# include <string.h>
-# undef __va_start
-# undef __va_arg
-# undef __va_copy
-# undef __va_end
-#else
-/* Avoid include files, they may not be available when cross compiling */
-extern void *memset(void *s, int c, __SIZE_TYPE__ n);
-extern void abort(void);
-#endif
-
-/* This should be in sync with our include/stdarg.h */
-enum __va_arg_type {
- __va_gen_reg, __va_float_reg, __va_stack
-};
-
-/* GCC compatible definition of va_list. */
-typedef struct {
- unsigned int gp_offset;
- unsigned int fp_offset;
- union {
- unsigned int overflow_offset;
- char *overflow_arg_area;
- };
- char *reg_save_area;
-} __va_list_struct;
-
-void __va_start(__va_list_struct *ap, void *fp)
-{
- memset(ap, 0, sizeof(__va_list_struct));
- *ap = *(__va_list_struct *)((char *)fp - 16);
- ap->overflow_arg_area = (char *)fp + ap->overflow_offset;
- ap->reg_save_area = (char *)fp - 176 - 16;
-}
-
-void *__va_arg(__va_list_struct *ap,
- enum __va_arg_type arg_type,
- int size, int align)
-{
- size = (size + 7) & ~7;
- align = (align + 7) & ~7;
- switch (arg_type) {
- case __va_gen_reg:
- if (ap->gp_offset + size <= 48) {
- ap->gp_offset += size;
- return ap->reg_save_area + ap->gp_offset - size;
- }
- goto use_overflow_area;
-
- case __va_float_reg:
- if (ap->fp_offset < 128 + 48) {
- ap->fp_offset += 16;
- return ap->reg_save_area + ap->fp_offset - 16;
- }
- size = 8;
- goto use_overflow_area;
-
- case __va_stack:
- use_overflow_area:
- ap->overflow_arg_area += size;
- ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align);
- return ap->overflow_arg_area - size;
-
- default: /* should never happen */
- abort();
- }
-}
-#endif /* __x86_64__ */
-
-#ifdef TCC_TARGET_ARM
-#define _GNU_SOURCE
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <stdio.h>
-
-/* Flushing for tccrun */
-void __clear_cache(void *beginning, void *end)
-{
-/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
- * However, there is no ARM asm parser in tcc so we use it for now */
-#if 1
- syscall(__ARM_NR_cacheflush, beginning, end, 0);
-#else
- __asm__ ("push {r7}\n\t"
- "mov r7, #0xf0002\n\t"
- "mov r2, #0\n\t"
- "swi 0\n\t"
- "pop {r7}\n\t"
- "ret");
-#endif
-}
-#endif /* arm */
+#endif /* !ARM */
diff --git a/lib/va_list.c b/lib/va_list.c
new file mode 100644
index 0000000..8749f46
--- /dev/null
+++ b/lib/va_list.c
@@ -0,0 +1,65 @@
+/* va_list.c - tinycc support for va_list on X86_64 */
+
+#if defined __x86_64__
+
+/* Avoid include files, they may not be available when cross compiling */
+extern void *memset(void *s, int c, __SIZE_TYPE__ n);
+extern void abort(void);
+
+/* This should be in sync with our include/stdarg.h */
+enum __va_arg_type {
+ __va_gen_reg, __va_float_reg, __va_stack
+};
+
+/* GCC compatible definition of va_list. */
+typedef struct {
+ unsigned int gp_offset;
+ unsigned int fp_offset;
+ union {
+ unsigned int overflow_offset;
+ char *overflow_arg_area;
+ };
+ char *reg_save_area;
+} __va_list_struct;
+
+void __va_start(__va_list_struct *ap, void *fp)
+{
+ memset(ap, 0, sizeof(__va_list_struct));
+ *ap = *(__va_list_struct *)((char *)fp - 16);
+ ap->overflow_arg_area = (char *)fp + ap->overflow_offset;
+ ap->reg_save_area = (char *)fp - 176 - 16;
+}
+
+void *__va_arg(__va_list_struct *ap,
+ enum __va_arg_type arg_type,
+ int size, int align)
+{
+ size = (size + 7) & ~7;
+ align = (align + 7) & ~7;
+ switch (arg_type) {
+ case __va_gen_reg:
+ if (ap->gp_offset + size <= 48) {
+ ap->gp_offset += size;
+ return ap->reg_save_area + ap->gp_offset - size;
+ }
+ goto use_overflow_area;
+
+ case __va_float_reg:
+ if (ap->fp_offset < 128 + 48) {
+ ap->fp_offset += 16;
+ return ap->reg_save_area + ap->fp_offset - 16;
+ }
+ size = 8;
+ goto use_overflow_area;
+
+ case __va_stack:
+ use_overflow_area:
+ ap->overflow_arg_area += size;
+ ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align);
+ return ap->overflow_arg_area - size;
+
+ default: /* should never happen */
+ abort();
+ }
+}
+#endif