new value stack system to handle the futur types (long long and floats)

This commit is contained in:
bellard 2001-12-16 17:58:32 +00:00
parent fa5161061e
commit fbc51a39f9
2 changed files with 296 additions and 299 deletions

View File

@ -276,13 +276,14 @@ void gfunc_start(GFuncContext *c)
c->args_size = 0; c->args_size = 0;
} }
/* push function parameter which is in (vt, vc) */ /* push function parameter which is in (vtop->t, vtop->c). Stack entry
is then popped. */
void gfunc_param(GFuncContext *c) void gfunc_param(GFuncContext *c)
{ {
int size, align, ft, fc, r; int size, align, r;
if ((vt & (VT_BTYPE | VT_LVAL)) == (VT_STRUCT | VT_LVAL)) { if ((vtop->t & (VT_BTYPE | VT_LVAL)) == (VT_STRUCT | VT_LVAL)) {
size = type_size(vt, &align); size = type_size(vtop->t, &align);
/* align to stack align size */ /* align to stack align size */
size = (size + 3) & ~3; size = (size + 3) & ~3;
/* allocate the necessary size on stack */ /* allocate the necessary size on stack */
@ -291,21 +292,17 @@ void gfunc_param(GFuncContext *c)
r = get_reg(REG_CLASS_INT); r = get_reg(REG_CLASS_INT);
o(0x89); /* mov %esp, r */ o(0x89); /* mov %esp, r */
o(0xe0 + r); o(0xe0 + r);
ft = vt;
fc = vc;
vset(VT_INT | r, 0); vset(VT_INT | r, 0);
vpush(); vswap();
vt = ft;
vc = fc;
vstore(); vstore();
c->args_size += size; c->args_size += size;
} else if ((vt & VT_BTYPE) == VT_LDOUBLE || } else if ((vtop->t & VT_BTYPE) == VT_LDOUBLE ||
(vt & VT_BTYPE) == VT_DOUBLE || (vtop->t & VT_BTYPE) == VT_DOUBLE ||
(vt & VT_BTYPE) == VT_FLOAT) { (vtop->t & VT_BTYPE) == VT_FLOAT) {
gv(); /* only one float register */ gv(); /* only one float register */
if ((vt & VT_BTYPE) == VT_FLOAT) if ((vtop->t & VT_BTYPE) == VT_FLOAT)
size = 4; size = 4;
else if ((vt & VT_BTYPE) == VT_DOUBLE) else if ((vtop->t & VT_BTYPE) == VT_DOUBLE)
size = 8; size = 8;
else else
size = 12; size = 12;
@ -324,21 +321,22 @@ void gfunc_param(GFuncContext *c)
o(0x50 + r); /* push r */ o(0x50 + r); /* push r */
c->args_size += 4; c->args_size += 4;
} }
vtop--;
} }
/* generate function call with address in (vt, vc) and free function /* generate function call with address in (vtop->t, vtop->c) and free function
context */ context. Stack entry is popped */
void gfunc_call(GFuncContext *c) void gfunc_call(GFuncContext *c)
{ {
int r; int r;
if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST) { if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
/* constant case */ /* constant case */
/* forward reference */ /* forward reference */
if (vt & VT_FORWARD) { if (vtop->t & VT_FORWARD) {
greloc((Sym *)vc, ind + 1, RELOC_REL32); greloc((Sym *)vtop->c, ind + 1, RELOC_REL32);
oad(0xe8, 0); oad(0xe8, 0);
} else { } else {
oad(0xe8, vc - ind - 5); oad(0xe8, vtop->c - ind - 5);
} }
} else { } else {
/* otherwise, indirect call */ /* otherwise, indirect call */
@ -348,6 +346,7 @@ void gfunc_call(GFuncContext *c)
} }
if (c->args_size) if (c->args_size)
oad(0xc481, c->args_size); /* add $xxx, %esp */ oad(0xc481, c->args_size); /* add $xxx, %esp */
vtop--;
} }
int gjmp(int t) int gjmp(int t)
@ -355,31 +354,31 @@ int gjmp(int t)
return psym(0xe9, t); return psym(0xe9, t);
} }
/* generate a test. set 'inv' to invert test */ /* generate a test. set 'inv' to invert test. Stack entry is popped */
int gtst(int inv, int t) int gtst(int inv, int t)
{ {
int v, *p; int v, *p;
v = vt & VT_VALMASK; v = vtop->t & VT_VALMASK;
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((vc - 16) ^ inv, t); t = psym((vtop->c - 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 vc jump list in t */ /* insert vtop->c jump list in t */
p = &vc; p = &vtop->c;
while (*p != 0) while (*p != 0)
p = (int *)*p; p = (int *)*p;
*p = t; *p = t;
t = vc; t = vtop->c;
} else { } else {
t = gjmp(t); t = gjmp(t);
gsym(vc); gsym(vtop->c);
} }
} else if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST) { } else if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
/* constant jmp optimization */ /* constant jmp optimization */
if ((vc != 0) != inv) if ((vtop->c != 0) != inv)
t = gjmp(t); t = gjmp(t);
} else { } else {
/* XXX: floats */ /* XXX: floats */
@ -389,14 +388,21 @@ int gtst(int inv, int t)
g(0x0f); g(0x0f);
t = psym(0x85 ^ inv, t); t = psym(0x85 ^ inv, t);
} }
vtop--;
return t; return t;
} }
/* generate an integer binary operation 'v = r op fr' instruction and /* generate an integer binary operation */
modifies (vt,vc) if needed */ void gen_opi(int op)
void gen_opi(int op, int r, int fr)
{ {
int t; int t, r, fr;
vswap();
r = gv();
vswap();
fr = gv();
vtop--;
if (op == '+') { if (op == '+') {
o(0x01); o(0x01);
o(0xc0 + r + fr * 8); o(0xc0 + r + fr * 8);
@ -433,7 +439,7 @@ void gen_opi(int op, int r, int fr)
o(0xe8 + r); o(0xe8 + r);
else else
o(0xf8 + r); o(0xf8 + r);
vt = (vt & VT_TYPE) | r; vtop->t = (vtop->t & VT_TYPE) | r;
} else if (op == '/' | op == TOK_UDIV | op == TOK_PDIV | } else if (op == '/' | op == TOK_UDIV | op == TOK_PDIV |
op == '%' | op == TOK_UMOD) { op == '%' | op == TOK_UMOD) {
save_reg(2); /* save edx */ save_reg(2); /* save edx */
@ -450,33 +456,32 @@ void gen_opi(int op, int r, int fr)
r = 2; r = 2;
else else
r = 0; r = 0;
vt = (vt & VT_TYPE) | r; vtop->t = (vtop->t & VT_TYPE) | r;
} else { } else {
vtop--;
o(0x39); o(0x39);
o(0xc0 + r + fr * 8); /* cmp fr, r */ o(0xc0 + r + fr * 8); /* cmp fr, r */
vset(VT_CMP, op); vset(VT_CMP, op);
} }
} }
/* generate a floating point operation 'v = t1 op t2' instruction and /* generate a floating point operation 'v = t1 op t2' instruction. The
modifies (vt,vc) if needed */ two operands are guaranted to have the same floating point type */
/* NOTE: floats can only be lvalues */ /* NOTE: currently floats can only be lvalues */
void gen_opf(int op) void gen_opf(int op)
{ {
int a, ft, fc, swapped, r; int a, ft, fc, swapped, r;
/* must put at least one value in the floating point register */ /* must put at least one value in the floating point register */
if ((vstack_ptr[-4] & VT_LVAL) && if ((vtop[-1].t & VT_LVAL) &&
(vstack_ptr[-2] & VT_LVAL)) { (vtop[0].t & VT_LVAL)) {
vswap(); vswap();
vpop(&vt, &vc);
gv(); gv();
vpush();
vswap(); vswap();
} }
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, vstack_ptr[-2], vstack_ptr[-1]); load(REG_ST0, vtop->t, vtop->c);
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 */
@ -495,13 +500,14 @@ void gen_opf(int op)
o(0x45c4f6); /* test $0x45, %ah */ o(0x45c4f6); /* test $0x45, %ah */
op = TOK_EQ; op = TOK_EQ;
} }
vstack_ptr[-4] = (vstack_ptr[-4] & VT_TYPE) | VT_CMP; vtop--;
vstack_ptr[-3] = op; vtop->t = (vtop->t & VT_TYPE) | VT_CMP;
vtop->c = 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 */
swapped = 0; swapped = 0;
if (vstack_ptr[-4] & VT_LVAL) { if (vtop[-1].t & VT_LVAL) {
vswap(); vswap();
swapped = 1; swapped = 1;
} }
@ -525,8 +531,8 @@ void gen_opf(int op)
a += 8; a += 8;
break; break;
} }
ft = vstack_ptr[-2]; ft = vtop->t;
fc = vstack_ptr[-1]; fc = vtop->c;
if ((ft & VT_BTYPE) == VT_DOUBLE) if ((ft & VT_BTYPE) == VT_DOUBLE)
o(0xdc); o(0xdc);
else else
@ -541,24 +547,24 @@ void gen_opf(int op)
} else { } else {
g(0x00 + a + r); g(0x00 + a + r);
} }
vtop--;
} }
vstack_ptr -= 2;
vpop(&vt, &vc);
} }
/* convert integers to floating point (float or double) */ /* convert integers to floating point 't' type (float/double/long
double) */
void gen_cvtf(int t) void gen_cvtf(int t)
{ {
if ((vt & (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 */
g(0x00); g(0x00);
o(0x50 + (vt & VT_VALMASK)); /* push r */ o(0x50 + (vtop->t & VT_VALMASK)); /* push r */
o(0x242cdf); /* fildll (%esp) */ o(0x242cdf); /* fildll (%esp) */
o(0x08c483); /* add $8, %esp */ o(0x08c483); /* add $8, %esp */
} else { } else {
/* int to float/double/long double */ /* int to float/double/long double */
o(0x50 + (vt & VT_VALMASK)); /* push r */ o(0x50 + (vtop->t & VT_VALMASK)); /* push r */
o(0x2404db); /* fildl (%esp) */ o(0x2404db); /* fildl (%esp) */
o(0x04c483); /* add $4, %esp */ o(0x04c483); /* add $4, %esp */
} }

481
tcc.c

File diff suppressed because it is too large Load Diff