mirror of
https://github.com/frida/tinycc
synced 2024-12-24 22:16:49 +03:00
float update
This commit is contained in:
parent
5ee1584493
commit
2694c10547
101
i386-gen.c
101
i386-gen.c
@ -242,12 +242,13 @@ void store(r, ft, fc)
|
||||
/* XXX: incorrect if reg to reg */
|
||||
/* XXX: should not flush float stack */
|
||||
if (bt == VT_FLOAT) {
|
||||
o(0xd9); /* fstps */
|
||||
r = 3;
|
||||
o(0xd9); /* fsts */
|
||||
r = 2;
|
||||
} else if (bt == VT_DOUBLE) {
|
||||
o(0xdd); /* fstpl */
|
||||
r = 3;
|
||||
r = 2;
|
||||
} else if (bt == VT_LDOUBLE) {
|
||||
o(0xc0d9); /* fld %st(0) */
|
||||
o(0xdb); /* fstpt */
|
||||
r = 7;
|
||||
} else {
|
||||
@ -296,9 +297,7 @@ void gfunc_param(GFuncContext *c)
|
||||
vswap();
|
||||
vstore();
|
||||
c->args_size += size;
|
||||
} else if ((vtop->t & VT_BTYPE) == VT_LDOUBLE ||
|
||||
(vtop->t & VT_BTYPE) == VT_DOUBLE ||
|
||||
(vtop->t & VT_BTYPE) == VT_FLOAT) {
|
||||
} else if (is_float(vtop->t)) {
|
||||
gv(); /* only one float register */
|
||||
if ((vtop->t & VT_BTYPE) == VT_FLOAT)
|
||||
size = 4;
|
||||
@ -333,10 +332,10 @@ void gfunc_call(GFuncContext *c)
|
||||
/* constant case */
|
||||
/* forward reference */
|
||||
if (vtop->t & VT_FORWARD) {
|
||||
greloc((Sym *)vtop->c, ind + 1, RELOC_REL32);
|
||||
greloc(vtop->c.sym, ind + 1, RELOC_REL32);
|
||||
oad(0xe8, 0);
|
||||
} else {
|
||||
oad(0xe8, vtop->c - ind - 5);
|
||||
oad(0xe8, vtop->c.ul - ind - 5);
|
||||
}
|
||||
} else {
|
||||
/* otherwise, indirect call */
|
||||
@ -362,23 +361,23 @@ int gtst(int inv, int t)
|
||||
if (v == VT_CMP) {
|
||||
/* fast case : can jump directly since flags are set */
|
||||
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) {
|
||||
/* && or || optimization */
|
||||
if ((v & 1) == inv) {
|
||||
/* insert vtop->c jump list in t */
|
||||
p = &vtop->c;
|
||||
p = &vtop->c.i;
|
||||
while (*p != 0)
|
||||
p = (int *)*p;
|
||||
*p = t;
|
||||
t = vtop->c;
|
||||
t = vtop->c.i;
|
||||
} else {
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||
/* constant jmp optimization */
|
||||
if ((vtop->c != 0) != inv)
|
||||
if ((vtop->c.i != 0) != inv)
|
||||
t = gjmp(t);
|
||||
} else {
|
||||
/* XXX: floats */
|
||||
@ -472,6 +471,15 @@ void gen_opf(int op)
|
||||
{
|
||||
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 */
|
||||
if ((vtop[-1].t & VT_LVAL) &&
|
||||
(vtop[0].t & VT_LVAL)) {
|
||||
@ -481,7 +489,7 @@ void gen_opf(int op)
|
||||
}
|
||||
if (op >= TOK_EQ && op <= TOK_GT) {
|
||||
/* 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)
|
||||
o(0xc9d9); /* fxch %st(1) */
|
||||
o(0xe9da); /* fucompp */
|
||||
@ -502,7 +510,7 @@ void gen_opf(int op)
|
||||
}
|
||||
vtop--;
|
||||
vtop->t = (vtop->t & VT_TYPE) | VT_CMP;
|
||||
vtop->c = op;
|
||||
vtop->c.i = op;
|
||||
} else {
|
||||
/* swap the stack if needed so that t1 is the register and t2 is
|
||||
the memory reference */
|
||||
@ -532,7 +540,7 @@ void gen_opf(int op)
|
||||
break;
|
||||
}
|
||||
ft = vtop->t;
|
||||
fc = vtop->c;
|
||||
fc = vtop->c.ul;
|
||||
if ((ft & VT_BTYPE) == VT_DOUBLE)
|
||||
o(0xdc);
|
||||
else
|
||||
@ -551,10 +559,10 @@ void gen_opf(int op)
|
||||
}
|
||||
}
|
||||
|
||||
/* convert integers to floating point 't' type (float/double/long
|
||||
double) */
|
||||
void gen_cvtf(int t)
|
||||
/* convert integers to fp 't' type */
|
||||
void gen_cvt_itof(int t)
|
||||
{
|
||||
gv();
|
||||
if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) {
|
||||
/* unsigned int to float/double/long double */
|
||||
o(0x6a); /* push $0 */
|
||||
@ -568,8 +576,63 @@ void gen_cvtf(int t)
|
||||
o(0x2404db); /* fildl (%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 */
|
||||
/*************************************************************/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user