x86-64: Make ABI for long double compatible with GCC.

- Now we use x87's stack top the long double return values.
- Add rc_fret and reg_fret, wrapper functions for RC_FRET and REG_FRET.
- Add a test case to check if strto* works OK.
This commit is contained in:
Shinichiro Hamaji
2009-04-14 01:12:29 +09:00
committed by grischka
parent 0e239e2ba5
commit 9fe28b610e
2 changed files with 31 additions and 3 deletions

28
tcc.c
View File

@ -5180,6 +5180,28 @@ void gv2(int rc1, int rc2)
} }
} }
/* wrapper around RC_FRET to return a register by type */
int rc_fret(int t)
{
#ifdef TCC_TARGET_X86_64
if (t == VT_LDOUBLE) {
return TREG_ST0;
}
#endif
return RC_FRET;
}
/* wrapper around REG_FRET to return a register by type */
int reg_fret(int t)
{
#ifdef TCC_TARGET_X86_64
if (t == VT_LDOUBLE) {
return TREG_ST0;
}
#endif
return REG_FRET;
}
/* expand long long on stack in two int registers */ /* expand long long on stack in two int registers */
void lexpand(void) void lexpand(void)
{ {
@ -6014,7 +6036,7 @@ void gen_cvt_itof1(int t)
vrott(2); vrott(2);
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
vtop->r = REG_FRET; vtop->r = reg_fret(t);
} else { } else {
gen_cvt_itof(t); gen_cvt_itof(t);
} }
@ -7942,7 +7964,7 @@ static void unary(void)
ret.type = s->type; ret.type = s->type;
/* return in register */ /* return in register */
if (is_float(ret.type.t)) { if (is_float(ret.type.t)) {
ret.r = REG_FRET; ret.r = reg_fret(ret.type.t);
} else { } else {
if ((ret.type.t & VT_BTYPE) == VT_LLONG) if ((ret.type.t & VT_BTYPE) == VT_LLONG)
ret.r2 = REG_LRET; ret.r2 = REG_LRET;
@ -8524,7 +8546,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
} }
#endif #endif
} else if (is_float(func_vt.t)) { } else if (is_float(func_vt.t)) {
gv(RC_FRET); gv(rc_fret(func_vt.t));
} else { } else {
gv(RC_IRET); gv(RC_IRET);
} }

View File

@ -1399,6 +1399,11 @@ void bitfield_test(void)
#define FLOAT_FMT "%.5f\n" #define FLOAT_FMT "%.5f\n"
#endif #endif
/* declare strto* functions as they are C99 */
double strtod(const char *nptr, char **endptr);
float strtof(const char *nptr, char **endptr);
long double strtold(const char *nptr, char **endptr);
#define FTEST(prefix, type, fmt)\ #define FTEST(prefix, type, fmt)\
void prefix ## cmp(type a, type b)\ void prefix ## cmp(type a, type b)\
{\ {\
@ -1455,6 +1460,7 @@ void prefix ## call(void)\
printf("float: " FLOAT_FMT, prefix ## retf(42.123456789));\ printf("float: " FLOAT_FMT, prefix ## retf(42.123456789));\
printf("double: %f\n", prefix ## retd(42.123456789));\ printf("double: %f\n", prefix ## retd(42.123456789));\
printf("long double: %Lf\n", prefix ## retld(42.123456789));\ printf("long double: %Lf\n", prefix ## retld(42.123456789));\
printf("strto%s: %f\n", #prefix, (double)strto ## prefix("1.2", NULL));\
}\ }\
\ \
void prefix ## test(void)\ void prefix ## test(void)\