aboutsummaryrefslogtreecommitdiff
path: root/i386-gen.c
diff options
context:
space:
mode:
authorbellard <bellard>2001-12-16 17:58:32 +0000
committerbellard <bellard>2001-12-16 17:58:32 +0000
commitfbc51a39f96f36462185118033e6f9479c7d08a0 (patch)
tree5e4db86a00fbc4bbfef0d8d1df353ee125cb56af /i386-gen.c
parentfa5161061e58352d357fbb2bbfbbaae2b7d0462e (diff)
downloadtinycc-fbc51a39f96f36462185118033e6f9479c7d08a0.tar.gz
tinycc-fbc51a39f96f36462185118033e6f9479c7d08a0.tar.bz2
new value stack system to handle the futur types (long long and floats)
Diffstat (limited to 'i386-gen.c')
-rw-r--r--i386-gen.c114
1 files changed, 60 insertions, 54 deletions
diff --git a/i386-gen.c b/i386-gen.c
index 40f1c2d..163180b 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -276,13 +276,14 @@ void gfunc_start(GFuncContext *c)
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)
{
- int size, align, ft, fc, r;
+ int size, align, r;
- if ((vt & (VT_BTYPE | VT_LVAL)) == (VT_STRUCT | VT_LVAL)) {
- size = type_size(vt, &align);
+ if ((vtop->t & (VT_BTYPE | VT_LVAL)) == (VT_STRUCT | VT_LVAL)) {
+ size = type_size(vtop->t, &align);
/* align to stack align size */
size = (size + 3) & ~3;
/* allocate the necessary size on stack */
@@ -291,21 +292,17 @@ void gfunc_param(GFuncContext *c)
r = get_reg(REG_CLASS_INT);
o(0x89); /* mov %esp, r */
o(0xe0 + r);
- ft = vt;
- fc = vc;
vset(VT_INT | r, 0);
- vpush();
- vt = ft;
- vc = fc;
+ vswap();
vstore();
c->args_size += size;
- } else if ((vt & VT_BTYPE) == VT_LDOUBLE ||
- (vt & VT_BTYPE) == VT_DOUBLE ||
- (vt & VT_BTYPE) == VT_FLOAT) {
+ } else if ((vtop->t & VT_BTYPE) == VT_LDOUBLE ||
+ (vtop->t & VT_BTYPE) == VT_DOUBLE ||
+ (vtop->t & VT_BTYPE) == VT_FLOAT) {
gv(); /* only one float register */
- if ((vt & VT_BTYPE) == VT_FLOAT)
+ if ((vtop->t & VT_BTYPE) == VT_FLOAT)
size = 4;
- else if ((vt & VT_BTYPE) == VT_DOUBLE)
+ else if ((vtop->t & VT_BTYPE) == VT_DOUBLE)
size = 8;
else
size = 12;
@@ -324,21 +321,22 @@ void gfunc_param(GFuncContext *c)
o(0x50 + r); /* push r */
c->args_size += 4;
}
+ vtop--;
}
-/* generate function call with address in (vt, vc) and free function
- context */
+/* generate function call with address in (vtop->t, vtop->c) and free function
+ context. Stack entry is popped */
void gfunc_call(GFuncContext *c)
{
int r;
- if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
+ if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
/* constant case */
/* forward reference */
- if (vt & VT_FORWARD) {
- greloc((Sym *)vc, ind + 1, RELOC_REL32);
+ if (vtop->t & VT_FORWARD) {
+ greloc((Sym *)vtop->c, ind + 1, RELOC_REL32);
oad(0xe8, 0);
} else {
- oad(0xe8, vc - ind - 5);
+ oad(0xe8, vtop->c - ind - 5);
}
} else {
/* otherwise, indirect call */
@@ -348,6 +346,7 @@ void gfunc_call(GFuncContext *c)
}
if (c->args_size)
oad(0xc481, c->args_size); /* add $xxx, %esp */
+ vtop--;
}
int gjmp(int t)
@@ -355,31 +354,31 @@ int gjmp(int 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 v, *p;
- v = vt & VT_VALMASK;
+ v = vtop->t & VT_VALMASK;
if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */
g(0x0f);
- t = psym((vc - 16) ^ inv, t);
+ t = psym((vtop->c - 16) ^ inv, t);
} else if (v == VT_JMP || v == VT_JMPI) {
/* && or || optimization */
if ((v & 1) == inv) {
- /* insert vc jump list in t */
- p = &vc;
+ /* insert vtop->c jump list in t */
+ p = &vtop->c;
while (*p != 0)
p = (int *)*p;
*p = t;
- t = vc;
+ t = vtop->c;
} else {
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 */
- if ((vc != 0) != inv)
+ if ((vtop->c != 0) != inv)
t = gjmp(t);
} else {
/* XXX: floats */
@@ -389,14 +388,21 @@ int gtst(int inv, int t)
g(0x0f);
t = psym(0x85 ^ inv, t);
}
+ vtop--;
return t;
}
-/* generate an integer binary operation 'v = r op fr' instruction and
- modifies (vt,vc) if needed */
-void gen_opi(int op, int r, int fr)
+/* generate an integer binary operation */
+void gen_opi(int op)
{
- int t;
+ int t, r, fr;
+
+ vswap();
+ r = gv();
+ vswap();
+ fr = gv();
+ vtop--;
+
if (op == '+') {
o(0x01);
o(0xc0 + r + fr * 8);
@@ -433,7 +439,7 @@ void gen_opi(int op, int r, int fr)
o(0xe8 + r);
else
o(0xf8 + r);
- vt = (vt & VT_TYPE) | r;
+ vtop->t = (vtop->t & VT_TYPE) | r;
} else if (op == '/' | op == TOK_UDIV | op == TOK_PDIV |
op == '%' | op == TOK_UMOD) {
save_reg(2); /* save edx */
@@ -450,33 +456,32 @@ void gen_opi(int op, int r, int fr)
r = 2;
else
r = 0;
- vt = (vt & VT_TYPE) | r;
+ vtop->t = (vtop->t & VT_TYPE) | r;
} else {
+ vtop--;
o(0x39);
o(0xc0 + r + fr * 8); /* cmp fr, r */
vset(VT_CMP, op);
}
}
-/* generate a floating point operation 'v = t1 op t2' instruction and
- modifies (vt,vc) if needed */
-/* NOTE: floats can only be lvalues */
+/* generate a floating point operation 'v = t1 op t2' instruction. The
+ two operands are guaranted to have the same floating point type */
+/* NOTE: currently floats can only be lvalues */
void gen_opf(int op)
{
int a, ft, fc, swapped, r;
/* must put at least one value in the floating point register */
- if ((vstack_ptr[-4] & VT_LVAL) &&
- (vstack_ptr[-2] & VT_LVAL)) {
+ if ((vtop[-1].t & VT_LVAL) &&
+ (vtop[0].t & VT_LVAL)) {
vswap();
- vpop(&vt, &vc);
gv();
- vpush();
vswap();
}
if (op >= TOK_EQ && op <= TOK_GT) {
/* 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)
o(0xc9d9); /* fxch %st(1) */
o(0xe9da); /* fucompp */
@@ -495,13 +500,14 @@ void gen_opf(int op)
o(0x45c4f6); /* test $0x45, %ah */
op = TOK_EQ;
}
- vstack_ptr[-4] = (vstack_ptr[-4] & VT_TYPE) | VT_CMP;
- vstack_ptr[-3] = op;
+ vtop--;
+ vtop->t = (vtop->t & VT_TYPE) | VT_CMP;
+ vtop->c = op;
} else {
/* swap the stack if needed so that t1 is the register and t2 is
the memory reference */
swapped = 0;
- if (vstack_ptr[-4] & VT_LVAL) {
+ if (vtop[-1].t & VT_LVAL) {
vswap();
swapped = 1;
}
@@ -525,8 +531,8 @@ void gen_opf(int op)
a += 8;
break;
}
- ft = vstack_ptr[-2];
- fc = vstack_ptr[-1];
+ ft = vtop->t;
+ fc = vtop->c;
if ((ft & VT_BTYPE) == VT_DOUBLE)
o(0xdc);
else
@@ -541,24 +547,24 @@ void gen_opf(int op)
} else {
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)
{
- 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 */
o(0x6a); /* push $0 */
g(0x00);
- o(0x50 + (vt & VT_VALMASK)); /* push r */
+ o(0x50 + (vtop->t & VT_VALMASK)); /* push r */
o(0x242cdf); /* fildll (%esp) */
o(0x08c483); /* add $8, %esp */
} else {
/* 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(0x04c483); /* add $4, %esp */
}