shl and shr and for tiny mode only
This commit is contained in:
parent
27f6e16bae
commit
881aa9077a
1 changed files with 63 additions and 60 deletions
115
tcc.c
115
tcc.c
|
@ -334,7 +334,7 @@ int gtst(inv, t)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the size (in bytes) of a given type */
|
/* return the size in bytes of a given type */
|
||||||
int type_size(t)
|
int type_size(t)
|
||||||
{
|
{
|
||||||
if ((t & VT_PTRMASK) > VT_PTRINC | (t & VT_TYPE) == VT_PTRINC)
|
if ((t & VT_PTRMASK) > VT_PTRINC | (t & VT_TYPE) == VT_PTRINC)
|
||||||
|
@ -361,16 +361,24 @@ void inc(a, c)
|
||||||
o(0x0189 | a); /* mov %eax/%edx, (%ecx) */
|
o(0x0189 | a); /* mov %eax/%edx, (%ecx) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* op is '-' or '+' (or 0) */
|
|
||||||
/* t is the type of the first operand */
|
|
||||||
/* XXX: handle ptr sub and 'int + ptr' case (only 'ptr + int' handled) */
|
/* XXX: handle ptr sub and 'int + ptr' case (only 'ptr + int' handled) */
|
||||||
void gen_op(op, t)
|
/* XXX: handle constant propagation (need to track live eax) */
|
||||||
|
void gen_op(op, l)
|
||||||
{
|
{
|
||||||
|
int t;
|
||||||
|
gv();
|
||||||
|
t = vt;
|
||||||
|
o(0x50); /* push %eax */
|
||||||
|
next();
|
||||||
|
if (l < 0)
|
||||||
|
expr();
|
||||||
|
else
|
||||||
|
sum(l);
|
||||||
gv();
|
gv();
|
||||||
o(0x59); /* pop %ecx */
|
o(0x59); /* pop %ecx */
|
||||||
if (op == '+' | op == '-') {
|
if (op == '+' | op == '-') {
|
||||||
/* XXX: incorrect for short (futur!) */
|
/* XXX: incorrect for short (futur!) */
|
||||||
if (type_size(t) != 1)
|
if (type_size(t) == 4)
|
||||||
o(0x02e0c1); /* shl $2, %eax */
|
o(0x02e0c1); /* shl $2, %eax */
|
||||||
if (op == '-')
|
if (op == '-')
|
||||||
o(0xd8f7); /* neg %eax */
|
o(0xd8f7); /* neg %eax */
|
||||||
|
@ -384,10 +392,13 @@ void gen_op(op, t)
|
||||||
o(0xc809);
|
o(0xc809);
|
||||||
else if (op == '*')
|
else if (op == '*')
|
||||||
o(0xc1af0f); /* imul %ecx, %eax */
|
o(0xc1af0f); /* imul %ecx, %eax */
|
||||||
|
#ifndef TINY
|
||||||
else if (op == TOK_SHL | op == TOK_SHR) {
|
else if (op == TOK_SHL | op == TOK_SHR) {
|
||||||
o(0xd391); /* xchg %ecx, %eax, shl/sar %cl, %eax */
|
o(0xd391); /* xchg %ecx, %eax, shl/sar %cl, %eax */
|
||||||
o(op);
|
o(op);
|
||||||
} else if (op == '/' | op == '%') {
|
}
|
||||||
|
#endif
|
||||||
|
else if (op == '/' | op == '%') {
|
||||||
o(0xd231); /* xor %edx, %edx */
|
o(0xd231); /* xor %edx, %edx */
|
||||||
o(0xf9f791); /* xchg %ecx, %eax, idiv %ecx, %eax */
|
o(0xf9f791); /* xchg %ecx, %eax, idiv %ecx, %eax */
|
||||||
if (op == '%')
|
if (op == '%')
|
||||||
|
@ -471,22 +482,33 @@ int typ(v,t)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read a number in base b */
|
||||||
|
int getn(c, b)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
n = 0;
|
||||||
|
while (isnum(c)) {
|
||||||
|
n = n * b + c - '0';
|
||||||
|
c = inp();
|
||||||
|
}
|
||||||
|
ungetc(c, file);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
int getq(n)
|
int getq(n)
|
||||||
{
|
{
|
||||||
int c;
|
|
||||||
if (n == '\\') {
|
if (n == '\\') {
|
||||||
n = inp();
|
n = inp();
|
||||||
if (n == 'n')
|
if (n == 'n')
|
||||||
n = '\n';
|
n = '\n';
|
||||||
else if (isnum(n)) {
|
#ifndef TINY
|
||||||
c = 0;
|
else if (n == 'r')
|
||||||
while (isnum(n)) {
|
n = '\r';
|
||||||
c = c * 8 + n - '0';
|
else if (n == 't')
|
||||||
n = inp();
|
n = '\t';
|
||||||
}
|
#endif
|
||||||
ungetc(n, file);
|
else if (isnum(n))
|
||||||
return c;
|
n = getn(n, 8);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
@ -497,12 +519,8 @@ void unary()
|
||||||
|
|
||||||
if (isnum(tok)) {
|
if (isnum(tok)) {
|
||||||
/* number */
|
/* number */
|
||||||
n = 0;
|
vset(VT_CONST, getn(tok, 10));
|
||||||
while (isnum(tok)) {
|
|
||||||
n = n * 10 + tok - '0';
|
|
||||||
next();
|
next();
|
||||||
}
|
|
||||||
vset(VT_CONST, n);
|
|
||||||
} else if (tok == '\'') {
|
} else if (tok == '\'') {
|
||||||
vset(VT_CONST, getq(inp()));
|
vset(VT_CONST, getq(inp()));
|
||||||
next(); /* skip char */
|
next(); /* skip char */
|
||||||
|
@ -545,8 +563,7 @@ void unary()
|
||||||
if (!(vt & VT_LVAL))
|
if (!(vt & VT_LVAL))
|
||||||
error("lvalue expected");
|
error("lvalue expected");
|
||||||
#endif
|
#endif
|
||||||
vt = vt & VT_LVALN;
|
vt = (vt & VT_LVALN) + VT_PTRINC;
|
||||||
vt = vt + VT_PTRINC;
|
|
||||||
} else
|
} else
|
||||||
#ifndef TINY
|
#ifndef TINY
|
||||||
if (t == '!') {
|
if (t == '!') {
|
||||||
|
@ -602,16 +619,9 @@ void unary()
|
||||||
if (!(vt & VT_PTRMASK))
|
if (!(vt & VT_PTRMASK))
|
||||||
error("pointer expected");
|
error("pointer expected");
|
||||||
#endif
|
#endif
|
||||||
gv();
|
gen_op('+', -1);
|
||||||
ft = vt;
|
|
||||||
fc = vc;
|
|
||||||
next();
|
|
||||||
o(0x50); /* push %eax */
|
|
||||||
expr();
|
|
||||||
gen_op('+', ft);
|
|
||||||
/* dereference pointer */
|
/* dereference pointer */
|
||||||
vt = (ft - VT_PTRINC) | VT_LVAL;
|
vt = (vt - VT_PTRINC) | VT_LVAL;
|
||||||
vc = fc;
|
|
||||||
skip(']');
|
skip(']');
|
||||||
} else
|
} else
|
||||||
if (tok == '(') {
|
if (tok == '(') {
|
||||||
|
@ -661,7 +671,7 @@ void unary()
|
||||||
}
|
}
|
||||||
if (t)
|
if (t)
|
||||||
oad(0xc481, t);
|
oad(0xc481, t);
|
||||||
/* return value is variable */
|
/* return value is variable, int */
|
||||||
vt = VT_VAR;
|
vt = VT_VAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -692,40 +702,33 @@ void uneq()
|
||||||
if (ft & VT_VAR) {
|
if (ft & VT_VAR) {
|
||||||
o(0x59); /* pop %ecx */
|
o(0x59); /* pop %ecx */
|
||||||
o(0x0189 - b); /* mov %eax/%al, (%ecx) */
|
o(0x0189 - b); /* mov %eax/%al, (%ecx) */
|
||||||
} else {
|
} else if (ft & VT_LOCAL)
|
||||||
if (ft & VT_LOCAL)
|
|
||||||
oad(0x8589 - b, fc); /* mov %eax/%al,xxx(%ebp) */
|
oad(0x8589 - b, fc); /* mov %eax/%al,xxx(%ebp) */
|
||||||
else
|
else
|
||||||
oad(0xa3 - b, fc); /* mov %eax/%al,xxx */
|
oad(0xa3 - b, fc); /* mov %eax/%al,xxx */
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sum(l)
|
void sum(l)
|
||||||
{
|
{
|
||||||
int op, t;
|
#ifndef TINY
|
||||||
|
int t;
|
||||||
|
#endif
|
||||||
if (l == 0)
|
if (l == 0)
|
||||||
uneq();
|
uneq();
|
||||||
else {
|
else {
|
||||||
l--;
|
sum(--l);
|
||||||
sum(l);
|
while ((l == 0 & (tok == '*' | tok == '/' | tok == '%')) |
|
||||||
while (1) {
|
(l == 1 & (tok == '+' | tok == '-')) |
|
||||||
op = tok;
|
#ifndef TINY
|
||||||
if ((l == 0 & op != '*' & op != '/' & op != '%') |
|
(l == 2 & (tok == TOK_SHL | tok == TOK_SHR)) |
|
||||||
(l == 1 & op != '+' & op != '-') |
|
#endif
|
||||||
(l == 2 & op != TOK_SHL & op != TOK_SHR) |
|
(l == 3 & (tok >= TOK_LT & tok <= TOK_GT)) |
|
||||||
(l == 3 & (op < TOK_LT | op > TOK_GT)) |
|
(l == 4 & (tok == TOK_EQ | tok == TOK_NE)) |
|
||||||
(l == 4 & op != TOK_EQ & op != TOK_NE) |
|
(l == 5 & tok == '&') |
|
||||||
(l == 5 & op != '&') |
|
(l == 6 & tok == '^') |
|
||||||
(l == 6 & op != '^') |
|
(l == 7 & tok == '|')) {
|
||||||
(l == 7 & op != '|'))
|
gen_op(tok, l);
|
||||||
break;
|
|
||||||
gv();
|
|
||||||
t = vt;
|
|
||||||
o(0x50); /* push %eax */
|
|
||||||
next();
|
|
||||||
sum(l);
|
|
||||||
gen_op(op, t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue