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:
committed by
grischka
parent
0e239e2ba5
commit
9fe28b610e
28
tcc.c
28
tcc.c
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)\
|
||||||
|
|||||||
Reference in New Issue
Block a user