float update

tcc-xref
bellard 2001-12-17 21:56:48 +00:00
parent 5ee1584493
commit 2694c10547
2 changed files with 568 additions and 232 deletions

View File

@ -242,12 +242,13 @@ void store(r, ft, fc)
/* XXX: incorrect if reg to reg */ /* XXX: incorrect if reg to reg */
/* XXX: should not flush float stack */ /* XXX: should not flush float stack */
if (bt == VT_FLOAT) { if (bt == VT_FLOAT) {
o(0xd9); /* fstps */ o(0xd9); /* fsts */
r = 3; r = 2;
} else if (bt == VT_DOUBLE) { } else if (bt == VT_DOUBLE) {
o(0xdd); /* fstpl */ o(0xdd); /* fstpl */
r = 3; r = 2;
} else if (bt == VT_LDOUBLE) { } else if (bt == VT_LDOUBLE) {
o(0xc0d9); /* fld %st(0) */
o(0xdb); /* fstpt */ o(0xdb); /* fstpt */
r = 7; r = 7;
} else { } else {
@ -296,9 +297,7 @@ void gfunc_param(GFuncContext *c)
vswap(); vswap();
vstore(); vstore();
c->args_size += size; c->args_size += size;
} else if ((vtop->t & VT_BTYPE) == VT_LDOUBLE || } else if (is_float(vtop->t)) {
(vtop->t & VT_BTYPE) == VT_DOUBLE ||
(vtop->t & VT_BTYPE) == VT_FLOAT) {
gv(); /* only one float register */ gv(); /* only one float register */
if ((vtop->t & VT_BTYPE) == VT_FLOAT) if ((vtop->t & VT_BTYPE) == VT_FLOAT)
size = 4; size = 4;
@ -333,10 +332,10 @@ void gfunc_call(GFuncContext *c)
/* constant case */ /* constant case */
/* forward reference */ /* forward reference */
if (vtop->t & VT_FORWARD) { if (vtop->t & VT_FORWARD) {
greloc((Sym *)vtop->c, ind + 1, RELOC_REL32); greloc(vtop->c.sym, ind + 1, RELOC_REL32);
oad(0xe8, 0); oad(0xe8, 0);
} else { } else {
oad(0xe8, vtop->c - ind - 5); oad(0xe8, vtop->c.ul - ind - 5);
} }
} else { } else {
/* otherwise, indirect call */ /* otherwise, indirect call */
@ -362,23 +361,23 @@ int gtst(int inv, int t)
if (v == VT_CMP) { if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */ /* fast case : can jump directly since flags are set */
g(0x0f); g(0x0f);
t = psym((vtop->c - 16) ^ inv, t); t = psym((vtop->c.i - 16) ^ inv, t);
} else if (v == VT_JMP || v == VT_JMPI) { } else if (v == VT_JMP || v == VT_JMPI) {
/* && or || optimization */ /* && or || optimization */
if ((v & 1) == inv) { if ((v & 1) == inv) {
/* insert vtop->c jump list in t */ /* insert vtop->c jump list in t */
p = &vtop->c; p = &vtop->c.i;
while (*p != 0) while (*p != 0)
p = (int *)*p; p = (int *)*p;
*p = t; *p = t;
t = vtop->c; t = vtop->c.i;
} else { } else {
t = gjmp(t); t = gjmp(t);
gsym(vtop->c); gsym(vtop->c.i);
} }
} else if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) { } else if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
/* constant jmp optimization */ /* constant jmp optimization */
if ((vtop->c != 0) != inv) if ((vtop->c.i != 0) != inv)
t = gjmp(t); t = gjmp(t);
} else { } else {
/* XXX: floats */ /* XXX: floats */
@ -472,6 +471,15 @@ void gen_opf(int op)
{ {
int a, ft, fc, swapped, r; int a, ft, fc, swapped, r;
/* convert constants to memory references */
if ((vtop[-1].t & (VT_CONST | VT_LVAL)) == VT_CONST) {
vswap();
gv();
vswap();
}
if ((vtop[0].t & (VT_CONST | VT_LVAL)) == VT_CONST)
gv();
/* must put at least one value in the floating point register */ /* must put at least one value in the floating point register */
if ((vtop[-1].t & VT_LVAL) && if ((vtop[-1].t & VT_LVAL) &&
(vtop[0].t & VT_LVAL)) { (vtop[0].t & VT_LVAL)) {
@ -481,7 +489,7 @@ void gen_opf(int op)
} }
if (op >= TOK_EQ && op <= TOK_GT) { if (op >= TOK_EQ && op <= TOK_GT) {
/* load on stack second operand */ /* load on stack second operand */
load(REG_ST0, vtop->t, vtop->c); load(REG_ST0, vtop->t, vtop->c.ul);
if (op == TOK_GE || op == TOK_GT) if (op == TOK_GE || op == TOK_GT)
o(0xc9d9); /* fxch %st(1) */ o(0xc9d9); /* fxch %st(1) */
o(0xe9da); /* fucompp */ o(0xe9da); /* fucompp */
@ -502,7 +510,7 @@ void gen_opf(int op)
} }
vtop--; vtop--;
vtop->t = (vtop->t & VT_TYPE) | VT_CMP; vtop->t = (vtop->t & VT_TYPE) | VT_CMP;
vtop->c = op; vtop->c.i = op;
} else { } else {
/* swap the stack if needed so that t1 is the register and t2 is /* swap the stack if needed so that t1 is the register and t2 is
the memory reference */ the memory reference */
@ -532,7 +540,7 @@ void gen_opf(int op)
break; break;
} }
ft = vtop->t; ft = vtop->t;
fc = vtop->c; fc = vtop->c.ul;
if ((ft & VT_BTYPE) == VT_DOUBLE) if ((ft & VT_BTYPE) == VT_DOUBLE)
o(0xdc); o(0xdc);
else else
@ -551,10 +559,10 @@ void gen_opf(int op)
} }
} }
/* convert integers to floating point 't' type (float/double/long /* convert integers to fp 't' type */
double) */ void gen_cvt_itof(int t)
void gen_cvtf(int t)
{ {
gv();
if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) { if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) {
/* unsigned int to float/double/long double */ /* unsigned int to float/double/long double */
o(0x6a); /* push $0 */ o(0x6a); /* push $0 */
@ -568,8 +576,63 @@ void gen_cvtf(int t)
o(0x2404db); /* fildl (%esp) */ o(0x2404db); /* fildl (%esp) */
o(0x04c483); /* add $4, %esp */ o(0x04c483); /* add $4, %esp */
} }
vtop->t = t | REG_ST0;
} }
/* FPU control word for rounding to nearest mode */
/* XXX: should move that into tcc lib support code ! */
static unsigned short __tcc_fpu_control = 0x137f;
/* FPU control word for round to zero mode for int convertion */
static unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
/* convert fp to int 't' type */
/* XXX: handle long long case */
void gen_cvt_ftoi(int t)
{
int r, size;
gv();
if (t == VT_INT | VT_UNSIGNED &&
t == VT_LLONG | VT_UNSIGNED &&
t == VT_LLONG)
size = 8;
else
size = 4;
r = get_reg(REG_CLASS_INT);
oad(0x2dd9, (int)&__tcc_int_fpu_control); /* ldcw xxx */
oad(0xec81, size); /* sub $xxx, %esp */
if (size == 4)
o(0x1cdb); /* fistpl */
else
o(0x3cdb); /* fistpll */
o(0x24);
oad(0x2dd9, (int)&__tcc_fpu_control); /* ldcw xxx */
o(0x58 + r); /* pop r */
if (size == 8)
o(0x04c483); /* add $4, %esp */
vtop->t = t | r;
}
/* convert from one floating point type to another */
void gen_cvt_ftof(int t)
{
/* all we have to do on i386 is to put the float in a register */
gv();
}
/* pop stack value */
void vpop(void)
{
/* for x86, we need to pop the FP stack */
if ((vtop->t & VT_VALMASK) == REG_ST0) {
o(0xd9dd); /* fstp %st(1) */
}
vtop--;
}
/* end of X86 code generator */ /* end of X86 code generator */
/*************************************************************/ /*************************************************************/

699
tcc.c

File diff suppressed because it is too large Load Diff