aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile25
-rw-r--r--lib/alloca-arm.S11
-rw-r--r--lib/armeabi.c468
-rw-r--r--lib/bcheck.c13
-rw-r--r--lib/libtcc1.c94
5 files changed, 572 insertions, 39 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 300fa46..e9e12f1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -6,7 +6,7 @@ TOP = ..
include $(TOP)/Makefile
VPATH = $(top_srcdir)/lib $(top_srcdir)/win32/lib
-ifndef TARGET
+ifndef TARGET # native library
ifdef CONFIG_WIN64
TARGET = x86_64-win32
else
@@ -24,6 +24,11 @@ ifndef TARGET
ifneq ($(TARGETOS),Darwin)
XCC = $(CC)
endif
+ else
+ ifeq ($(ARCH),arm)
+ TARGET = arm
+ XCC = $(CC)
+ endif
endif
endif
endif
@@ -41,20 +46,27 @@ 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
+ARM_O = libtcc1.o armeabi.o alloca-arm.o
WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
WIN64_O = $(X86_64_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)/,$(WIN32_O))
TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
XAR = $(DIR)/tiny_libmaker$(EXESUF)
+ PICFLAGS =
else
ifeq "$(TARGET)" "x86_64-win32"
OBJ = $(addprefix $(DIR)/,$(WIN64_O))
TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
XAR = $(DIR)/tiny_libmaker$(EXESUF)
+ PICFLAGS =
else
ifeq "$(TARGET)" "i386"
OBJ = $(addprefix $(DIR)/,$(I386_O))
@@ -66,13 +78,19 @@ ifeq "$(TARGET)" "x86_64"
TGT = -DTCC_TARGET_X86_64
XCC ?= $(TCC) -B$(TOP)
else
+ifeq "$(TARGET)" "arm"
+ OBJ = $(addprefix $(DIR)/,$(ARM_O))
+ TGT = -DTCC_TARGET_ARM
+ XCC ?= $(TCC) -B$(TOP)
+else
$(error libtcc1.a not supported on target '$(TARGET)')
endif
endif
endif
endif
+endif
-XFLAGS = $(CPPFLAGS) $(CFLAGS) $(TGT)
+XFLAGS = $(CPPFLAGS) $(CFLAGS) $(PICFLAGS) $(TGT)
ifeq ($(TARGETOS),Darwin)
XAR = $(DIR)/tiny_libmaker$(EXESUF)
@@ -100,6 +118,3 @@ $(DIR)/exists :
clean :
rm -rfv i386-win32 x86_64-win32 i386 x86_64
-
-Makefile: $(top_srcdir)/lib/Makefile
- cp $< $@
diff --git a/lib/alloca-arm.S b/lib/alloca-arm.S
new file mode 100644
index 0000000..9deae63
--- /dev/null
+++ b/lib/alloca-arm.S
@@ -0,0 +1,11 @@
+ .text
+ .align 2
+ .global alloca
+ .type alloca, %function
+alloca:
+ rsb sp, r0, sp
+ bic sp, sp, #7
+ mov r0, sp
+ mov pc, lr
+ .size alloca, .-alloca
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/armeabi.c b/lib/armeabi.c
new file mode 100644
index 0000000..ce5e232
--- /dev/null
+++ b/lib/armeabi.c
@@ -0,0 +1,468 @@
+#include <limits.h>
+
+/* We rely on the little endianness and EABI calling convention for this to
+ work */
+
+typedef struct double_unsigned_struct {
+ unsigned low;
+ unsigned high;
+} double_unsigned_struct;
+
+typedef struct unsigned_int_struct {
+ unsigned low;
+ int high;
+} unsigned_int_struct;
+
+#define REGS_RETURN(name, type) \
+ void name ## _return(type ret) {}
+
+
+/* Float helper functions */
+
+#define FLOAT_EXP_BITS 8
+#define FLOAT_FRAC_BITS 23
+
+#define DOUBLE_EXP_BITS 11
+#define DOUBLE_FRAC_BITS 52
+
+#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
+
+REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
+REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
+
+/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
+
+
+/* float to [unsigned] long long conversion */
+#define DEFINE__AEABI_F2XLZ(name, with_sign) \
+void __aeabi_ ## name(unsigned val) \
+{ \
+ int exp, high_shift, sign; \
+ double_unsigned_struct ret; \
+ \
+ /* compute sign */ \
+ sign = val >> 31; \
+ \
+ /* compute real exponent */ \
+ exp = val >> FLOAT_FRAC_BITS; \
+ exp &= (1 << FLOAT_EXP_BITS) - 1; \
+ exp -= ONE_EXP(FLOAT); \
+ \
+ /* undefined behavior if truncated value cannot be represented */ \
+ if (with_sign) { \
+ if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
+ return; \
+ } else { \
+ if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
+ return; \
+ } \
+ \
+ val &= (1 << FLOAT_FRAC_BITS) - 1; \
+ if (exp >= 32) { \
+ ret.high = 1 << (exp - 32); \
+ if (exp - 32 >= FLOAT_FRAC_BITS) { \
+ ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
+ ret.low = 0; \
+ } else { \
+ high_shift = FLOAT_FRAC_BITS - (exp - 32); \
+ ret.high |= val >> high_shift; \
+ ret.low = val << (32 - high_shift); \
+ } \
+ } else { \
+ ret.high = 0; \
+ ret.low = 1 << exp; \
+ if (exp > FLOAT_FRAC_BITS) \
+ ret.low |= val << (exp - FLOAT_FRAC_BITS); \
+ else \
+ ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
+ } \
+ \
+ /* encode negative integer using 2's complement */ \
+ if (with_sign && sign) { \
+ ret.low = ~ret.low; \
+ ret.high = ~ret.high; \
+ if (ret.low == UINT_MAX) { \
+ ret.low = 0; \
+ ret.high++; \
+ } else \
+ ret.low++; \
+ } \
+ \
+ double_unsigned_struct_return(ret); \
+}
+
+/* float to unsigned long long conversion */
+DEFINE__AEABI_F2XLZ(f2ulz, 0)
+
+/* float to long long conversion */
+DEFINE__AEABI_F2XLZ(f2lz, 1)
+
+/* double to [unsigned] long long conversion */
+#define DEFINE__AEABI_D2XLZ(name, with_sign) \
+void __aeabi_ ## name(double_unsigned_struct val) \
+{ \
+ int exp, high_shift, sign; \
+ double_unsigned_struct ret; \
+ \
+ /* compute sign */ \
+ sign = val.high >> 31; \
+ \
+ /* compute real exponent */ \
+ exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
+ exp &= (1 << DOUBLE_EXP_BITS) - 1; \
+ exp -= ONE_EXP(DOUBLE); \
+ \
+ /* undefined behavior if truncated value cannot be represented */ \
+ if (with_sign) { \
+ if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
+ return; \
+ } else { \
+ if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
+ return; \
+ } \
+ \
+ val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
+ if (exp >= 32) { \
+ ret.high = 1 << (exp - 32); \
+ if (exp >= DOUBLE_FRAC_BITS) { \
+ high_shift = exp - DOUBLE_FRAC_BITS; \
+ ret.high |= val.high << high_shift; \
+ ret.high |= val.low >> (32 - high_shift); \
+ ret.low = val.low << high_shift; \
+ } else { \
+ high_shift = DOUBLE_FRAC_BITS - exp; \
+ ret.high |= val.high >> high_shift; \
+ ret.low = val.high << (32 - high_shift); \
+ ret.low |= val.low >> high_shift; \
+ } \
+ } else { \
+ ret.high = 0; \
+ ret.low = 1 << exp; \
+ if (exp > DOUBLE_FRAC_BITS - 32) { \
+ high_shift = exp - DOUBLE_FRAC_BITS - 32; \
+ ret.low |= val.high << high_shift; \
+ ret.low |= val.low >> (32 - high_shift); \
+ } else \
+ ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
+ } \
+ \
+ /* encode negative integer using 2's complement */ \
+ if (with_sign && sign) { \
+ ret.low = ~ret.low; \
+ ret.high = ~ret.high; \
+ if (ret.low == UINT_MAX) { \
+ ret.low = 0; \
+ ret.high++; \
+ } else \
+ ret.low++; \
+ } \
+ \
+ double_unsigned_struct_return(ret); \
+}
+
+/* double to unsigned long long conversion */
+DEFINE__AEABI_D2XLZ(d2ulz, 0)
+
+/* double to long long conversion */
+DEFINE__AEABI_D2XLZ(d2lz, 1)
+
+/* long long to float conversion */
+#define DEFINE__AEABI_XL2F(name, with_sign) \
+unsigned __aeabi_ ## name(unsigned long long v) \
+{ \
+ int s /* shift */, flb /* first lost bit */, sign = 0; \
+ unsigned p = 0 /* power */, ret; \
+ double_unsigned_struct val; \
+ \
+ /* fraction in negative float is encoded in 1's complement */ \
+ if (with_sign && (v & (1ULL << 63))) { \
+ sign = 1; \
+ v = ~v + 1; \
+ } \
+ val.low = v; \
+ val.high = v >> 32; \
+ /* fill fraction bits */ \
+ for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
+ if (p) { \
+ ret = val.high & (p - 1); \
+ if (s < FLOAT_FRAC_BITS) { \
+ ret <<= FLOAT_FRAC_BITS - s; \
+ ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
+ flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
+ } else { \
+ flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
+ ret >>= s - FLOAT_FRAC_BITS; \
+ } \
+ s += 32; \
+ } else { \
+ for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
+ if (p) { \
+ ret = val.low & (p - 1); \
+ if (s <= FLOAT_FRAC_BITS) { \
+ ret <<= FLOAT_FRAC_BITS - s; \
+ flb = 0; \
+ } else { \
+ flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
+ ret >>= s - FLOAT_FRAC_BITS; \
+ } \
+ } else \
+ return 0; \
+ } \
+ if (flb) \
+ ret++; \
+ \
+ /* fill exponent bits */ \
+ ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
+ \
+ /* fill sign bit */ \
+ ret |= sign << 31; \
+ \
+ return ret; \
+}
+
+/* unsigned long long to float conversion */
+DEFINE__AEABI_XL2F(ul2f, 0)
+
+/* long long to float conversion */
+DEFINE__AEABI_XL2F(l2f, 1)
+
+/* long long to double conversion */
+#define __AEABI_XL2D(name, with_sign) \
+void __aeabi_ ## name(unsigned long long v) \
+{ \
+ int s /* shift */, high_shift, sign = 0; \
+ unsigned tmp, p = 0; \
+ double_unsigned_struct val, ret; \
+ \
+ /* fraction in negative float is encoded in 1's complement */ \
+ if (with_sign && (v & (1ULL << 63))) { \
+ sign = 1; \
+ v = ~v + 1; \
+ } \
+ val.low = v; \
+ val.high = v >> 32; \
+ \
+ /* fill fraction bits */ \
+ for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
+ if (p) { \
+ tmp = val.high & (p - 1); \
+ if (s < DOUBLE_FRAC_BITS - 32) { \
+ high_shift = DOUBLE_FRAC_BITS - 32 - s; \
+ ret.high = tmp << high_shift; \
+ ret.high |= val.low >> (32 - high_shift); \
+ ret.low = val.low << high_shift; \
+ } else { \
+ high_shift = s - (DOUBLE_FRAC_BITS - 32); \
+ ret.high = tmp >> high_shift; \
+ ret.low = tmp << (32 - high_shift); \
+ ret.low |= val.low >> high_shift; \
+ if ((val.low >> (high_shift - 1)) & 1) { \
+ if (ret.low == UINT_MAX) { \
+ ret.high++; \
+ ret.low = 0; \
+ } else \
+ ret.low++; \
+ } \
+ } \
+ s += 32; \
+ } else { \
+ for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
+ if (p) { \
+ tmp = val.low & (p - 1); \
+ if (s <= DOUBLE_FRAC_BITS - 32) { \
+ high_shift = DOUBLE_FRAC_BITS - 32 - s; \
+ ret.high = tmp << high_shift; \
+ ret.low = 0; \
+ } else { \
+ high_shift = s - (DOUBLE_FRAC_BITS - 32); \
+ ret.high = tmp >> high_shift; \
+ ret.low = tmp << (32 - high_shift); \
+ } \
+ } else { \
+ ret.high = ret.low = 0; \
+ double_unsigned_struct_return(ret); \
+ } \
+ } \
+ \
+ /* fill exponent bits */ \
+ ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
+ \
+ /* fill sign bit */ \
+ ret.high |= sign << 31; \
+ \
+ double_unsigned_struct_return(ret); \
+}
+
+/* unsigned long long to double conversion */
+__AEABI_XL2D(ul2d, 0)
+
+/* long long to double conversion */
+__AEABI_XL2D(l2d, 1)
+
+
+/* Long long helper functions */
+
+/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
+
+#define define_aeabi_xdivmod_signed_type(basetype, type) \
+typedef struct type { \
+ basetype quot; \
+ unsigned basetype rem; \
+} type
+
+#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
+typedef struct type { \
+ basetype quot; \
+ basetype rem; \
+} type
+
+#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
+static inline rettype aeabi_ ## name (type num, type den) \
+{ \
+ rettype ret; \
+ type quot = 0; \
+ \
+ /* Increase quotient while it is less than numerator */ \
+ while (num >= den) { \
+ type q = 1; \
+ \
+ /* Find closest power of two */ \
+ while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
+ q <<= 1; \
+ \
+ /* Compute difference between current quotient and numerator */ \
+ num -= q * den; \
+ quot += q; \
+ } \
+ ret.quot = quot; \
+ ret.rem = num; \
+ return ret; \
+}
+
+#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
+void __aeabi_ ## name(type numerator, type denominator) \
+{ \
+ unsigned type num, den; \
+ urettype uxdiv_ret; \
+ rettype ret; \
+ \
+ if (numerator >= 0) \
+ num = numerator; \
+ else \
+ num = 0 - numerator; \
+ if (denominator >= 0) \
+ den = denominator; \
+ else \
+ den = 0 - denominator; \
+ uxdiv_ret = aeabi_ ## uiname(num, den); \
+ /* signs differ */ \
+ if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
+ ret.quot = 0 - uxdiv_ret.quot; \
+ else \
+ ret.quot = uxdiv_ret.quot; \
+ if (numerator < 0) \
+ ret.rem = 0 - uxdiv_ret.rem; \
+ else \
+ ret.rem = uxdiv_ret.rem; \
+ \
+ rettype ## _return(ret); \
+}
+
+define_aeabi_xdivmod_signed_type(long long, lldiv_t);
+define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
+define_aeabi_xdivmod_signed_type(int, idiv_t);
+define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
+
+REGS_RETURN(lldiv_t, lldiv_t)
+REGS_RETURN(ulldiv_t, ulldiv_t)
+REGS_RETURN(idiv_t, idiv_t)
+REGS_RETURN(uidiv_t, uidiv_t)
+
+AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULONG)
+
+__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
+
+void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
+{
+ ulldiv_t_return(aeabi_uldivmod(num, den));
+}
+
+void __aeabi_llsl(double_unsigned_struct val, int shift)
+{
+ double_unsigned_struct ret;
+
+ if (shift >= 32) {
+ val.high = val.low;
+ val.low = 0;
+ shift -= 32;
+ }
+ if (shift > 0) {
+ ret.low = val.low << shift;
+ ret.high = (val.high << shift) | (val.low >> (32 - shift));
+ double_unsigned_struct_return(ret);
+ return;
+ }
+ double_unsigned_struct_return(val);
+}
+
+#define aeabi_lsr(val, shift, fill, type) \
+ type ## _struct ret; \
+ \
+ if (shift >= 32) { \
+ val.low = val.high; \
+ val.high = fill; \
+ shift -= 32; \
+ } \
+ if (shift > 0) { \
+ ret.high = val.high >> shift; \
+ ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
+ type ## _struct_return(ret); \
+ return; \
+ } \
+ type ## _struct_return(val);
+
+void __aeabi_llsr(double_unsigned_struct val, int shift)
+{
+ aeabi_lsr(val, shift, 0, double_unsigned);
+}
+
+void __aeabi_lasr(unsigned_int_struct val, int shift)
+{
+ aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
+}
+
+
+/* Integer division functions */
+
+AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
+
+int __aeabi_idiv(int numerator, int denominator)
+{
+ unsigned num, den;
+ uidiv_t ret;
+
+ if (numerator >= 0)
+ num = numerator;
+ else
+ num = 0 - numerator;
+ if (denominator >= 0)
+ den = denominator;
+ else
+ den = 0 - denominator;
+ ret = aeabi_uidivmod(num, den);
+ if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
+ ret.quot *= -1;
+ return ret.quot;
+}
+
+unsigned __aeabi_uidiv(unsigned num, unsigned den)
+{
+ return aeabi_uidivmod(num, den).quot;
+}
+
+__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
+
+void __aeabi_uidivmod(unsigned num, unsigned den)
+{
+ uidiv_t_return(aeabi_uidivmod(num, den));
+}
diff --git a/lib/bcheck.c b/lib/bcheck.c
index 064fb5d..8ac7d4e 100644
--- a/lib/bcheck.c
+++ b/lib/bcheck.c
@@ -22,7 +22,7 @@
#include <stdarg.h>
#include <string.h>
#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) \
- && !defined(__DragonFly__) && !defined(__OpenBSD__)
+ && !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
#include <malloc.h>
#endif
#if !defined(_WIN32)
@@ -41,7 +41,7 @@
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
|| defined(__DragonFly__) || defined(__dietlibc__) \
- || defined(__UCLIBC__) || defined(__OpenBSD__) \
+ || defined(__UCLIBC__) || defined(__OpenBSD__) || defined(__NetBSD__) \
|| defined(_WIN32) || defined(TCC_UCLIBC)
#warning Bound checking does not support malloc (etc.) in this environment.
#undef CONFIG_TCC_MALLOC_HOOKS
@@ -418,6 +418,13 @@ void __bound_init(void)
}
}
+void __bound_main_arg(void **p)
+{
+ void *start = p;
+ while (*p++);
+ __bound_new_region(start, (void *) p - start);
+}
+
void __bound_exit(void)
{
restore_malloc_hooks();
@@ -628,7 +635,7 @@ int __bound_delete_region(void *p)
}
/* return the size of the region starting at p, or EMPTY_SIZE if non
- existant region. */
+ existent region. */
static unsigned long get_region_size(void *p)
{
unsigned long addr = (unsigned long)p;
diff --git a/lib/libtcc1.c b/lib/libtcc1.c
index 53dbec4..284965e 100644
--- a/lib/libtcc1.c
+++ b/lib/libtcc1.c
@@ -28,6 +28,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
+#include <stdint.h>
+
#define W_TYPE_SIZE 32
#define BITS_PER_UNIT 8
@@ -107,10 +109,10 @@ union float_long {
};
/* XXX: we don't support several builtin supports for now */
-#ifndef __x86_64__
+#if !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM)
/* XXX: use gcc/tcc intrinsic ? */
-#if defined(__i386__)
+#if defined(TCC_TARGET_I386)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
: "=r" ((USItype) (sh)), \
@@ -478,13 +480,6 @@ long long __ashldi3(long long a, int b)
#endif
}
-#if defined(__i386__)
-/* FPU control word for rounding to nearest mode */
-unsigned short __tcc_fpu_control = 0x137f;
-/* FPU control word for round to zero mode for int conversion */
-unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
-#endif
-
#endif /* !__x86_64__ */
/* XXX: fix tcc's code generator to do this instead */
@@ -605,15 +600,38 @@ unsigned long long __fixunsxfdi (long double a1)
return 0;
}
-#if defined(__x86_64__) && !defined(_WIN64)
+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>
#else
/* Avoid including stdlib.h because it is not easily available when
cross compiling */
extern void *malloc(unsigned long long);
+void *memset(void *s, int c, size_t n);
extern void free(void*);
extern void abort(void);
#endif
@@ -622,8 +640,9 @@ enum __va_arg_type {
__va_gen_reg, __va_float_reg, __va_stack
};
+//This should be in sync with the declaration on our include/stdarg.h
/* GCC compatible definition of va_list. */
-struct __va_list_struct {
+typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
union {
@@ -631,19 +650,22 @@ struct __va_list_struct {
char *overflow_arg_area;
};
char *reg_save_area;
-};
+} __va_list_struct;
-void *__va_start(void *fp)
+#undef __va_start
+#undef __va_arg
+#undef __va_copy
+#undef __va_end
+
+void __va_start(__va_list_struct *ap, void *fp)
{
- struct __va_list_struct *ap =
- (struct __va_list_struct *)malloc(sizeof(struct __va_list_struct));
- *ap = *(struct __va_list_struct *)((char *)fp - 16);
+ 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;
- return ap;
}
-void *__va_arg(struct __va_list_struct *ap,
+void *__va_arg(__va_list_struct *ap,
enum __va_arg_type arg_type,
int size, int align)
{
@@ -669,7 +691,7 @@ void *__va_arg(struct __va_list_struct *ap,
case __va_stack:
use_overflow_area:
ap->overflow_arg_area += size;
- ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -(long long)align);
+ ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align);
return ap->overflow_arg_area - size;
default:
@@ -680,26 +702,36 @@ void *__va_arg(struct __va_list_struct *ap,
}
}
-void *__va_copy(struct __va_list_struct *src)
-{
- struct __va_list_struct *dest =
- (struct __va_list_struct *)malloc(sizeof(struct __va_list_struct));
- *dest = *src;
- return dest;
-}
+#endif /* __x86_64__ */
-void __va_end(struct __va_list_struct *ap)
+/* Flushing for tccrun */
+#if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_I386)
+
+void __clear_cache(char *beginning, char *end)
{
- free(ap);
}
-#endif /* __x86_64__ */
+#elif defined(TCC_TARGET_ARM)
-/* Flushing for tccrun */
-#if defined(__x86_64__) || defined(__i386__)
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdio.h>
void __clear_cache(char *beginning, char *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
}
#else