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
This commit is contained in:
committed by
grischka
parent
2c657f6608
commit
12265da6cd
116
arm-gen.c
116
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();
|
||||
|
||||
Reference in New Issue
Block a user