diff options
| author | Daniel Glöckner <daniel-gl@gmx.net> | 2008-09-05 21:07:46 +0200 |
|---|---|---|
| committer | grischka <grischka> | 2008-09-12 22:22:36 +0200 |
| commit | 12265da6cd24bd48ce6e40b60fac1dc62eeee156 (patch) | |
| tree | d181cedfa63eb65d06aa2ad3a78129a8ecc898f4 | |
| parent | 2c657f6608fd192e785d5b2eed2594007777842b (diff) | |
| download | tinycc-12265da6cd24bd48ce6e40b60fac1dc62eeee156.tar.gz tinycc-12265da6cd24bd48ce6e40b60fac1dc62eeee156.tar.bz2 | |
Runtime lib functions
Yesterday I felt the urge to change a few things in TinyCC.
This is the first and biggest change of all of them.
- use __aeabi_*divmod functions in ARM EABI to make binaries depend
solely on standardized library functions
- refactor ARM floating point <-> integer conversion a bit
- rename long long->float and shift library functions to correspond to
the names used by GCC
- compile more tokens conditionally to reduce the size of TinyCC
The intention is primarily to allow users of the ARM target to use
libgcc (which is usually available as a shared library) instead of
libtcc1 (which can't be compiled for ARM due to lack of an inline
assembler).
Changing the EABI target to use the divmod functions in theory allows
to use it without libtcc1 on any (not necessarily GCC based) ARM EABI
system.
Daniel
| -rw-r--r-- | arm-gen.c | 116 | ||||
| -rw-r--r-- | libtcc1.c | 12 | ||||
| -rw-r--r-- | tcc.c | 43 | ||||
| -rw-r--r-- | tcctok.h | 63 |
4 files changed, 140 insertions, 94 deletions
@@ -110,6 +110,13 @@ static int regmask(int r) { #define REG_LRET TREG_R1 /* second word return register (for long long) */ #define REG_FRET TREG_F0 /* float return register */ +#ifdef TCC_ARM_EABI +#define TOK___divdi3 TOK___aeabi_ldivmod +#define TOK___moddi3 TOK___aeabi_ldivmod +#define TOK___udivdi3 TOK___aeabi_uldivmod +#define TOK___umoddi3 TOK___aeabi_uldivmod +#endif + /* defined if function parameters must be evaluated in reverse order */ #define INVERT_FUNC_PARAMS @@ -119,6 +126,11 @@ static int regmask(int r) { #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) static CType float_type, double_type, func_float_type, func_double_type; +#define func_ldouble_type func_double_type +#else +#define func_float_type func_old_type +#define func_double_type func_old_type +#define func_ldouble_type func_old_type #endif /* pointer size, in bytes */ @@ -1083,6 +1095,7 @@ void gen_opi(int op) { int c, func = 0; unsigned long opc = 0,r,fr; + unsigned short retreg = REG_IRET; c=0; switch(op) { @@ -1151,11 +1164,21 @@ void gen_opi(int op) c=3; break; case '%': +#ifdef TCC_ARM_EABI + func=TOK___aeabi_idivmod; + retreg=REG_LRET; +#else func=TOK___modsi3; +#endif c=3; break; case TOK_UMOD: +#ifdef TCC_ARM_EABI + func=TOK___aeabi_uidivmod; + retreg=REG_LRET; +#else func=TOK___umodsi3; +#endif c=3; break; case TOK_UMULL: @@ -1230,7 +1253,7 @@ done: vrott(3); gfunc_call(2); vpushi(0); - vtop->r = REG_IRET; + vtop->r = retreg; break; default: error("gen_opi %i unimplemented!",op); @@ -1547,11 +1570,14 @@ void gen_opf(int op) /* convert integers to fp 't' type. Must handle 'int', 'unsigned int' and 'long long' cases. */ -void gen_cvt_itof(int t) +void gen_cvt_itof1(int t) { int r,r2,bt; bt=vtop->type.t & VT_BTYPE; if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) { +#ifndef TCC_ARM_VFP + unsigned int dsize=0; +#endif r=intr(gv(RC_INT)); #ifdef TCC_ARM_VFP r2=vfpr(vtop->r=get_reg(RC_FLOAT)); @@ -1562,10 +1588,12 @@ void gen_cvt_itof(int t) o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/ #else r2=fpr(vtop->r=get_reg(RC_FLOAT)); - o(0xEE000190|(r2<<16)|(r<<12)); + if((t & VT_BTYPE) != VT_FLOAT) + dsize=0x80; /* flts -> fltd */ + o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */ if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) { unsigned int off=0; - o(0xE3500000|(r<<12)); + o(0xE3500000|(r<<12)); /* cmp */ r=fpr(get_reg(RC_FLOAT)); if(last_itod_magic) { off=ind+8-last_itod_magic; @@ -1573,44 +1601,50 @@ void gen_cvt_itof(int t) if(off>255) off=0; } - o(0xBD1F8100|(r<<12)|off); + o(0xBD1F0100|(r<<12)|off); /* ldflts */ if(!off) { - o(0xEA000001); + o(0xEA000000); /* b */ last_itod_magic=ind; - o(0x41F00000); - o(0); + o(0x4F800000); /* 4294967296.0f */ } - o(0xBE000180|(r2<<16)|(r2<<12)|r); + o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */ } #endif return; } else if(bt == VT_LLONG) { int func; - CType *func_type = &func_old_type; -#ifdef TCC_ARM_VFP -#ifdef TCC_ARM_EABI - func_type = &func_double_type; -#endif + CType *func_type = 0; if((t & VT_BTYPE) == VT_FLOAT) { -#ifdef TCC_ARM_EABI func_type = &func_float_type; -#endif if(vtop->type.t & VT_UNSIGNED) - func=TOK___ulltof; + func=TOK___floatundisf; else - func=TOK___slltof; - } else + func=TOK___floatdisf; +#if LDOUBLE_SIZE != 8 + } else if((t & VT_BTYPE) == VT_LDOUBLE) { + func_type = &func_ldouble_type; + if(vtop->type.t & VT_UNSIGNED) + func=TOK___floatundixf; + else + func=TOK___floatdixf; + } else if((t & VT_BTYPE) == VT_DOUBLE) { +#else + } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) { #endif - if(vtop->type.t & VT_UNSIGNED) - func=TOK___ulltold; - else - func=TOK___slltold; - vpush_global_sym(func_type, func); - vswap(); - gfunc_call(1); - vpushi(0); - vtop->r=TREG_F0; - return; + func_type = &func_double_type; + if(vtop->type.t & VT_UNSIGNED) + func=TOK___floatundidf; + else + func=TOK___floatdidf; + } + if(func_type) { + vpush_global_sym(func_type, func); + vswap(); + gfunc_call(1); + vpushi(0); + vtop->r=TREG_F0; + return; + } } error("unimplemented gen_cvt_itof %x!",vtop->type.t); } @@ -1634,33 +1668,33 @@ void gen_cvt_ftoi(int t) if(u) { if(r2 == VT_FLOAT) func=TOK___fixunssfsi; - else if(r2 == VT_DOUBLE) - func=TOK___fixunsdfsi; +#if LDOUBLE_SIZE != 8 else if(r2 == VT_LDOUBLE) -#if LDOUBLE_SIZE == 8 - func=TOK___fixunsdfsi; -#else func=TOK___fixunsxfsi; + else if(r2 == VT_DOUBLE) +#else + else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE) #endif + func=TOK___fixunsdfsi; } else { r=fpr(gv(RC_FLOAT)); r2=intr(vtop->r=get_reg(RC_INT)); o(0xEE100170|(r2<<12)|r); - return; + return; } #endif } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1 if(r2 == VT_FLOAT) func=TOK___fixsfdi; - else if(r2 == VT_DOUBLE) - func=TOK___fixdfdi; +#if LDOUBLE_SIZE != 8 else if(r2 == VT_LDOUBLE) -#if LDOUBLE_SIZE == 8 - func=TOK___fixdfdi; -#else func=TOK___fixxfdi; + else if(r2 == VT_DOUBLE) +#else + else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE) #endif - } + func=TOK___fixdfdi; + } if(func) { vpush_global_sym(&func_old_type, func); vswap(); @@ -419,7 +419,7 @@ unsigned long long __umoddi3(unsigned long long u, unsigned long long v) } /* XXX: fix tcc's code generator to do this instead */ -long long __sardi3(long long a, int b) +long long __ashrdi3(long long a, int b) { #ifdef __TINYC__ DWunion u; @@ -438,7 +438,7 @@ long long __sardi3(long long a, int b) } /* XXX: fix tcc's code generator to do this instead */ -unsigned long long __shrdi3(unsigned long long a, int b) +unsigned long long __lshrdi3(unsigned long long a, int b) { #ifdef __TINYC__ DWunion u; @@ -457,7 +457,7 @@ unsigned long long __shrdi3(unsigned long long a, int b) } /* XXX: fix tcc's code generator to do this instead */ -long long __shldi3(long long a, int b) +long long __ashldi3(long long a, int b) { #ifdef __TINYC__ DWunion u; @@ -483,7 +483,7 @@ unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00; #endif /* XXX: fix tcc's code generator to do this instead */ -float __ulltof(unsigned long long a) +float __floatundisf(unsigned long long a) { DWunion uu; XFtype r; @@ -498,7 +498,7 @@ float __ulltof(unsigned long long a) } } -double __ulltod(unsigned long long a) +double __floatundidf(unsigned long long a) { DWunion uu; XFtype r; @@ -513,7 +513,7 @@ double __ulltod(unsigned long long a) } } -long double __ulltold(unsigned long long a) +long double __floatundixf(unsigned long long a) { DWunion uu; XFtype r; @@ -5261,6 +5261,8 @@ void gen_opl(int op) { int t, a, b, op1, c, i; int func; + unsigned short reg_iret = REG_IRET; + unsigned short reg_lret = REG_LRET; SValue tmp; switch(op) { @@ -5273,17 +5275,22 @@ void gen_opl(int op) goto gen_func; case '%': func = TOK___moddi3; - goto gen_func; + goto gen_mod_func; case TOK_UMOD: func = TOK___umoddi3; + gen_mod_func: +#ifdef TCC_ARM_EABI + reg_iret = TREG_R2; + reg_lret = TREG_R3; +#endif gen_func: /* call generic long long function */ vpush_global_sym(&func_old_type, func); vrott(3); gfunc_call(2); vpushi(0); - vtop->r = REG_IRET; - vtop->r2 = REG_LRET; + vtop->r = reg_iret; + vtop->r2 = reg_lret; break; case '^': case '&': @@ -5407,13 +5414,13 @@ void gen_opl(int op) /* XXX: should provide a faster fallback on x86 ? */ switch(op) { case TOK_SAR: - func = TOK___sardi3; + func = TOK___ashrdi3; goto gen_func; case TOK_SHR: - func = TOK___shrdi3; + func = TOK___lshrdi3; goto gen_func; case TOK_SHL: - func = TOK___shldi3; + func = TOK___ashldi3; goto gen_func; } } @@ -5878,6 +5885,7 @@ void gen_op(int op) } } +#ifndef TCC_TARGET_ARM /* generic itof for unsigned long long case */ void gen_cvt_itof1(int t) { @@ -5885,11 +5893,13 @@ void gen_cvt_itof1(int t) (VT_LLONG | VT_UNSIGNED)) { if (t == VT_FLOAT) - vpush_global_sym(&func_old_type, TOK___ulltof); - else if (t == VT_DOUBLE) - vpush_global_sym(&func_old_type, TOK___ulltod); + vpush_global_sym(&func_old_type, TOK___floatundisf); +#if LDOUBLE_SIZE != 8 + else if (t == VT_LDOUBLE) + vpush_global_sym(&func_old_type, TOK___floatundixf); +#endif else - vpush_global_sym(&func_old_type, TOK___ulltold); + vpush_global_sym(&func_old_type, TOK___floatundidf); vrott(2); gfunc_call(1); vpushi(0); @@ -5898,6 +5908,7 @@ void gen_cvt_itof1(int t) gen_cvt_itof(t); } } +#endif /* generic ftoi for unsigned long long case */ void gen_cvt_ftoi1(int t) @@ -5909,10 +5920,12 @@ void gen_cvt_ftoi1(int t) st = vtop->type.t & VT_BTYPE; if (st == VT_FLOAT) vpush_global_sym(&func_old_type, TOK___fixunssfdi); - else if (st == VT_DOUBLE) - vpush_global_sym(&func_old_type, TOK___fixunsdfdi); - else +#if LDOUBLE_SIZE != 8 + else if (st == VT_LDOUBLE) vpush_global_sym(&func_old_type, TOK___fixunsxfdi); +#endif + else + vpush_global_sym(&func_old_type, TOK___fixunsdfdi); vrott(2); gfunc_call(1); vpushi(0); @@ -6020,11 +6033,7 @@ static void gen_cast(CType *type) } } else { do_itof: -#if !defined(TCC_TARGET_ARM) gen_cvt_itof1(dbt); -#else - gen_cvt_itof(dbt); -#endif } } else if (sf) { /* convert fp to int */ @@ -126,41 +126,42 @@ DEF(TOK_memcpy4, "__aeabi_memcpy4") DEF(TOK_memcpy8, "__aeabi_memcpy8") DEF(TOK_memset, "__aeabi_memset") + DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod") + DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod") #else DEF(TOK_memcpy, "memcpy") DEF(TOK_memset, "memset") -#endif DEF(TOK___divdi3, "__divdi3") DEF(TOK___moddi3, "__moddi3") DEF(TOK___udivdi3, "__udivdi3") DEF(TOK___umoddi3, "__umoddi3") +#endif #if defined(TCC_TARGET_ARM) - DEF(TOK___modsi3, "__modsi3") - DEF(TOK___umodsi3, "__umodsi3") #ifdef TCC_ARM_EABI + DEF(TOK___aeabi_idivmod, "__aeabi_idivmod") + DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod") DEF(TOK___divsi3, "__aeabi_idiv") DEF(TOK___udivsi3, "__aeabi_uidiv") - DEF(TOK___sardi3, "__aeabi_lasr") - DEF(TOK___shrdi3, "__aeabi_llsr") - DEF(TOK___shldi3, "__aeabi_llsl") - DEF(TOK___slltof, "__aeabi_l2f") - DEF(TOK___slltold, "__aeabi_l2d") + DEF(TOK___floatdisf, "__aeabi_l2f") + DEF(TOK___floatdidf, "__aeabi_l2d") DEF(TOK___fixsfdi, "__aeabi_f2lz") DEF(TOK___fixdfdi, "__aeabi_d2lz") - DEF(TOK___fixxfdi, "__aeabi_d2lz") #else + DEF(TOK___modsi3, "__modsi3") + DEF(TOK___umodsi3, "__umodsi3") DEF(TOK___divsi3, "__divsi3") DEF(TOK___udivsi3, "__udivsi3") - DEF(TOK___sardi3, "__ashrdi3") - DEF(TOK___shrdi3, "__lshrdi3") - DEF(TOK___shldi3, "__ashldi3") - DEF(TOK___slltold, "__slltold") + DEF(TOK___floatdisf, "__floatdisf") + DEF(TOK___floatdidf, "__floatdidf") +#ifndef TCC_ARM_VFP + DEF(TOK___floatdixf, "__floatdixf") DEF(TOK___fixunssfsi, "__fixunssfsi") DEF(TOK___fixunsdfsi, "__fixunsdfsi") DEF(TOK___fixunsxfsi, "__fixunsxfsi") + DEF(TOK___fixxfdi, "__fixxfdi") +#endif DEF(TOK___fixsfdi, "__fixsfdi") DEF(TOK___fixdfdi, "__fixdfdi") - DEF(TOK___fixxfdi, "__fixxfdi") #endif #elif defined(TCC_TARGET_C67) DEF(TOK__divi, "_divi") @@ -169,33 +170,35 @@ DEF(TOK__divd, "_divd") DEF(TOK__remi, "_remi") DEF(TOK__remu, "_remu") - DEF(TOK___sardi3, "__sardi3") - DEF(TOK___shrdi3, "__shrdi3") - DEF(TOK___shldi3, "__shldi3") -#else - /* XXX: same names on i386 ? */ - DEF(TOK___sardi3, "__sardi3") - DEF(TOK___shrdi3, "__shrdi3") - DEF(TOK___shldi3, "__shldi3") #endif +#ifdef TCC_TARGET_I386 DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control") DEF(TOK___tcc_fpu_control, "__tcc_fpu_control") +#endif #ifdef TCC_ARM_EABI - DEF(TOK___ulltof, "__aeabi_ul2f") - DEF(TOK___ulltod, "__aeabi_ul2d") - DEF(TOK___ulltold, "__aeabi_ul2d") + DEF(TOK___ashrdi3, "__aeabi_lasr") + DEF(TOK___lshrdi3, "__aeabi_llsr") + DEF(TOK___ashldi3, "__aeabi_llsl") + DEF(TOK___floatundisf, "__aeabi_ul2f") + DEF(TOK___floatundidf, "__aeabi_ul2d") DEF(TOK___fixunssfdi, "__aeabi_f2ulz") DEF(TOK___fixunsdfdi, "__aeabi_d2ulz") - DEF(TOK___fixunsxfdi, "__aeabi_d2ulz") #else - DEF(TOK___ulltof, "__ulltof") - DEF(TOK___ulltod, "__ulltod") - DEF(TOK___ulltold, "__ulltold") + DEF(TOK___ashrdi3, "__ashrdi3") + DEF(TOK___lshrdi3, "__lshrdi3") + DEF(TOK___ashldi3, "__ashldi3") + DEF(TOK___floatundisf, "__floatundisf") + DEF(TOK___floatundidf, "__floatundidf") +#ifndef TCC_ARM_VFP + DEF(TOK___floatundixf, "__floatundixf") + DEF(TOK___fixunsxfdi, "__fixunsxfdi") +#endif DEF(TOK___fixunssfdi, "__fixunssfdi") DEF(TOK___fixunsdfdi, "__fixunsdfdi") - DEF(TOK___fixunsxfdi, "__fixunsxfdi") #endif +#ifdef TCC_TARGET_PE DEF(TOK___chkstk, "__chkstk") +#endif /* bound checking symbols */ #ifdef CONFIG_TCC_BCHECK |
