shl and shr and for tiny mode only

tcc-xref
bellard 2001-10-28 01:15:41 +00:00
parent 27f6e16bae
commit 881aa9077a
1 changed files with 63 additions and 60 deletions

123
tcc.c
View File

@ -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)) { next();
n = n * 10 + tok - '0';
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);
} }
} }
} }