diff --git a/arm-gen.c b/arm-gen.c index e3a5629..67a6f85 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -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(); diff --git a/libtcc1.c b/libtcc1.c index 11393e3..892baba 100644 --- a/libtcc1.c +++ b/libtcc1.c @@ -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; diff --git a/tcc.c b/tcc.c index 9855a13..aa34658 100644 --- a/tcc.c +++ b/tcc.c @@ -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 */ diff --git a/tcctok.h b/tcctok.h index e019476..d717024 100644 --- a/tcctok.h +++ b/tcctok.h @@ -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___fixunssfdi, "__fixunssfdi") - DEF(TOK___fixunsdfdi, "__fixunsdfdi") + 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") +#endif +#ifdef TCC_TARGET_PE DEF(TOK___chkstk, "__chkstk") +#endif /* bound checking symbols */ #ifdef CONFIG_TCC_BCHECK