more work on adding in pieces. fixed my bad assumptions about

signed and unsigned integer conversions.

R=rsc
APPROVED=rsc
DELTA=398  (40 added, 230 deleted, 128 changed)
OCL=33546
CL=33569
This commit is contained in:
Kai Backman 2009-08-19 20:17:09 -07:00
parent 40b0786374
commit 8811896597
5 changed files with 160 additions and 350 deletions

View File

@ -201,6 +201,8 @@ cgen(Node *n, Node *res)
// asymmetric binary
case OSUB:
case OLSH:
case ORSH:
a = optoas(n->op, nl->type);
goto abop;
@ -294,17 +296,8 @@ cgen(Node *n, Node *res)
case OMOD:
case ODIV:
if(isfloat[n->type->etype]) {
a = optoas(n->op, nl->type);
goto abop;
}
cgen_div(n->op, nl, nr, res);
break;
case OLSH:
case ORSH:
cgen_shift(n->op, nl, nr, res);
break;
a = optoas(n->op, nl->type);
goto abop;
}
goto ret;
@ -343,14 +336,6 @@ abop: // asymmetric binary
regfree(&n2);
goto ret;
uop: // unary
regalloc(&n1, nl->type, res);
cgen(nl, &n1);
gins(a, N, &n1);
gmove(&n1, res);
regfree(&n1);
goto ret;
ret:
;
}

View File

@ -76,9 +76,6 @@ void cgen_callmeth(Node*, int);
void cgen_callinter(Node*, Node*, int);
void cgen_proc(Node*, int);
void cgen_callret(Node*, Node*);
void cgen_div(int, Node*, Node*, Node*);
void cgen_bmul(int, Node*, Node*, Node*);
void cgen_shift(int, Node*, Node*, Node*);
void cgen_dcl(Node*);
int needconvert(Type*, Type*);
void genconv(Type*, Type*);

View File

@ -392,7 +392,6 @@ cgen_asop(Node *n)
}
hard:
fatal("cgen_asop hard not implemented");
if(nr->ullman > nl->ullman) {
regalloc(&n2, nr->type, N);
cgen(nr, &n2);
@ -432,200 +431,52 @@ samereg(Node *a, Node *b)
return 1;
}
/*
* generate division according to op, one of:
* res = nl / nr
* res = nl % nr
*/
// TODO(kaib): rip out and just insert into cgen
void
cgen_div(int op, Node *nl, Node *nr, Node *res)
{
Node nod, nod1;
Prog* p;
Addr ta;
if(res == Z) {
// TODO(kaib): add back warning for null
// nullwarn(l, r);
return;
}
if(nl->ullman >= nr->ullman) {
regalloc(&nod, nl->type, res);
cgen(nl, &nod);
regalloc(&nod1, nr->type, Z);
cgen(nr, &nod1);
gins(optoas(op, nod1.type), &nod1, &nod);
} else {
regalloc(&nod, nr->type, res);
cgen(nr, &nod);
regalloc(&nod1, nl->type, Z);
cgen(nl, &nod1);
p = gins(optoas(op, nod.type), &nod, &nod);
naddr(&nod1, &ta);
p->reg = ta.reg;
}
gins(optoas(OAS, nod.type), &nod, res);
regfree(&nod);
regfree(&nod1);
}
/*
* generate shift according to op, one of:
* res = nl << nr
* res = nl >> nr
*/
// TODO(kaib): rip out and replace with simple isntruction
void
cgen_shift(int op, Node *nl, Node *nr, Node *res)
{
fatal("cgen_shift not implemented");
// Node n1, n2, n3;
// int a;
// Prog *p1;
// a = optoas(op, nl->type);
// if(nr->op == OLITERAL) {
// regalloc(&n1, nl->type, res);
// cgen(nl, &n1);
// if(mpgetfix(nr->val.u.xval) >= nl->type->width*8) {
// // large shift gets 2 shifts by width
// nodconst(&n3, types[TUINT32], nl->type->width*8-1);
// gins(a, &n3, &n1);
// gins(a, &n3, &n1);
// } else
// gins(a, nr, &n1);
// gmove(&n1, res);
// regfree(&n1);
// goto ret;
// }
// nodreg(&n1, types[TUINT32], D_CX);
// regalloc(&n1, nr->type, &n1); // to hold the shift type in CX
// regalloc(&n3, types[TUINT64], &n1); // to clear high bits of CX
// regalloc(&n2, nl->type, res);
// if(nl->ullman >= nr->ullman) {
// cgen(nl, &n2);
// cgen(nr, &n1);
// gmove(&n1, &n3);
// } else {
// cgen(nr, &n1);
// gmove(&n1, &n3);
// cgen(nl, &n2);
// }
// regfree(&n3);
// // test and fix up large shifts
// nodconst(&n3, types[TUINT64], nl->type->width*8);
// gins(optoas(OCMP, types[TUINT64]), &n1, &n3);
// p1 = gbranch(optoas(OLT, types[TUINT64]), T);
// if(op == ORSH && issigned[nl->type->etype]) {
// nodconst(&n3, types[TUINT32], nl->type->width*8-1);
// gins(a, &n3, &n2);
// } else {
// nodconst(&n3, nl->type, 0);
// gmove(&n3, &n2);
// }
// patch(p1, pc);
// gins(a, &n1, &n2);
// gmove(&n2, res);
// regfree(&n1);
// regfree(&n2);
//ret:
// ;
}
/*
* generate byte multiply:
* res = nl * nr
* no byte multiply instruction so have to do
* 16-bit multiply and take bottom half.
*/
// TODO(kaib): figure out if we can replace this normal multiply
void
cgen_bmul(int op, Node *nl, Node *nr, Node *res)
{
fatal("cgen_bmul not implemented");
// Node n1b, n2b, n1w, n2w;
// Type *t;
// int a;
// if(nl->ullman >= nr->ullman) {
// regalloc(&n1b, nl->type, res);
// cgen(nl, &n1b);
// regalloc(&n2b, nr->type, N);
// cgen(nr, &n2b);
// } else {
// regalloc(&n2b, nr->type, N);
// cgen(nr, &n2b);
// regalloc(&n1b, nl->type, res);
// cgen(nl, &n1b);
// }
// // copy from byte to short registers
// t = types[TUINT16];
// if(issigned[nl->type->etype])
// t = types[TINT16];
// regalloc(&n2w, t, &n2b);
// cgen(&n2b, &n2w);
// regalloc(&n1w, t, &n1b);
// cgen(&n1b, &n1w);
// a = optoas(op, t);
// gins(a, &n2w, &n1w);
// cgen(&n1w, &n1b);
// cgen(&n1b, res);
// regfree(&n1w);
// regfree(&n2w);
// regfree(&n1b);
// regfree(&n2b);
}
void
clearfat(Node *nl)
{
fatal("clearfat not implemented");
// uint32 w, c, q;
// Node n1;
uint32 w, c, q;
Node dst, nc, nz;
Prog *p;
// /* clear a fat object */
// if(debug['g'])
// dump("\nclearfat", nl);
/* clear a fat object */
if(debug['g'])
dump("\nclearfat", nl);
// w = nl->type->width;
// c = w % 8; // bytes
// q = w / 8; // quads
w = nl->type->width;
c = w % 4; // bytes
q = w / 4; // quads
// gconreg(AMOVQ, 0, D_AX);
// nodreg(&n1, types[tptr], D_DI);
// agen(nl, &n1);
regalloc(&dst, types[tptr], N);
agen(nl, &dst);
nodconst(&nc, types[TUINT32], 0);
regalloc(&nz, types[TUINT32], 0);
cgen(&nc, &nz);
// if(q >= 4) {
if(q >= 4) {
fatal("clearfat q >=4 not implemented");
// gconreg(AMOVQ, q, D_CX);
// gins(AREP, N, N); // repeat
// gins(ASTOSQ, N, N); // STOQ AL,*(DI)+
// } else
// while(q > 0) {
// gins(ASTOSQ, N, N); // STOQ AL,*(DI)+
// q--;
// }
} else
while(q > 0) {
p = gins(AMOVW, &nz, &dst);
p->to.type = D_OREG;
p->to.offset = 4;
p->scond |= C_PBIT;
//print("1. %P\n", p);
q--;
}
// if(c >= 4) {
// gconreg(AMOVQ, c, D_CX);
// gins(AREP, N, N); // repeat
// gins(ASTOSB, N, N); // STOB AL,*(DI)+
// } else
// while(c > 0) {
// gins(ASTOSB, N, N); // STOB AL,*(DI)+
// c--;
// }
while(c > 0) {
gins(AMOVBU, &nz, &dst);
p->to.type = D_OREG;
p->to.offset = 1;
p->scond |= C_PBIT;
//print("2. %P\n", p);
c--;
}
regfree(&dst);
regfree(&nz);
}
int

View File

@ -596,7 +596,7 @@ out:
p->reg = 7;
p->to.offset2 = 0;
p->to.reg = NREG;
print("1. %P\n", p);
//print("1. %P\n", p);
o = 0;
for(c=d-1; c>=0; c--) {
@ -613,7 +613,7 @@ print("1. %P\n", p);
p->from.offset = o;
p->to.type = D_REG;
p->to.reg = REGARG;
print("2. %P\n", p);
//print("2. %P\n", p);
o = 0;
}
if(o != 0) {
@ -625,7 +625,7 @@ print("2. %P\n", p);
p->from.offset = o;
p->to.type = D_REG;
p->to.reg = REGARG;
print("3. %P\n", p);
//print("3. %P\n", p);
}
f = dotlist[0].field;
@ -638,7 +638,7 @@ print("3. %P\n", p);
p->to.reg = NREG;
p->to.name = D_EXTERN;
p->to.sym = methodsym(method->sym, ptrto(f->type));
print("4. %P\n", p);
//print("4. %P\n", p);
pc->as = ARET; // overwrite AEND
}

View File

@ -393,8 +393,8 @@ gconreg(int as, vlong c, int reg)
{
Node n1, n2;
nodconst(&n1, types[TINT64], c);
nodreg(&n2, types[TINT64], reg);
nodconst(&n1, types[TINT32], c);
nodreg(&n2, types[TINT32], reg);
gins(as, &n1, &n2);
}
@ -489,18 +489,21 @@ gmove(Node *f, Node *t)
* integer copy and truncate
*/
case CASE(TINT8, TINT8): // same size
case CASE(TINT8, TUINT8):
case CASE(TUINT8, TINT8):
case CASE(TUINT8, TUINT8):
case CASE(TINT16, TINT8): // truncate
case CASE(TUINT16, TINT8):
case CASE(TINT32, TINT8):
case CASE(TUINT32, TINT8):
a = AMOVB;
break;
case CASE(TINT8, TUINT8):
case CASE(TUINT8, TUINT8):
case CASE(TINT16, TUINT8):
case CASE(TUINT16, TUINT8):
case CASE(TINT32, TUINT8):
case CASE(TUINT32, TUINT8):
a = AMOVB;
a = AMOVBU;
break;
case CASE(TINT64, TINT8): // truncate low word
@ -516,14 +519,17 @@ gmove(Node *f, Node *t)
return;
case CASE(TINT16, TINT16): // same size
case CASE(TINT16, TUINT16):
case CASE(TUINT16, TINT16):
case CASE(TUINT16, TUINT16):
case CASE(TINT32, TINT16): // truncate
case CASE(TUINT32, TINT16):
a = AMOVH;
break;
case CASE(TINT16, TUINT16):
case CASE(TUINT16, TUINT16):
case CASE(TINT32, TUINT16):
case CASE(TUINT32, TUINT16):
a = AMOVH;
a = AMOVHU;
break;
case CASE(TINT64, TINT16): // truncate low word
@ -582,45 +588,41 @@ gmove(Node *f, Node *t)
/*
* integer up-conversions
*/
// case CASE(TINT8, TINT16): // sign extend int8
// case CASE(TINT8, TUINT16):
// a = AMOVBWSX;
// goto rdst;
// case CASE(TINT8, TINT32):
// case CASE(TINT8, TUINT32):
// a = AMOVBLSX;
// goto rdst;
case CASE(TINT8, TINT16): // sign extend int8
case CASE(TINT8, TUINT16):
case CASE(TINT8, TINT32):
case CASE(TINT8, TUINT32):
a = AMOVB;
goto rdst;
// case CASE(TINT8, TINT64): // convert via int32
// case CASE(TINT8, TUINT64):
// cvt = types[TINT32];
// goto hard;
// case CASE(TUINT8, TINT16): // zero extend uint8
// case CASE(TUINT8, TUINT16):
// a = AMOVBWZX;
// goto rdst;
// case CASE(TUINT8, TINT32):
// case CASE(TUINT8, TUINT32):
// a = AMOVBLZX;
// goto rdst;
case CASE(TUINT8, TINT16): // zero extend uint8
case CASE(TUINT8, TUINT16):
case CASE(TUINT8, TINT32):
case CASE(TUINT8, TUINT32):
a = AMOVBU;
goto rdst;
// case CASE(TUINT8, TINT64): // convert via uint32
// case CASE(TUINT8, TUINT64):
// cvt = types[TUINT32];
// goto hard;
// case CASE(TINT16, TINT32): // sign extend int16
// case CASE(TINT16, TUINT32):
// a = AMOVWLSX;
// goto rdst;
case CASE(TINT16, TINT32): // sign extend int16
case CASE(TINT16, TUINT32):
a = AMOVH;
goto rdst;
// case CASE(TINT16, TINT64): // convert via int32
// case CASE(TINT16, TUINT64):
// cvt = types[TINT32];
// goto hard;
// case CASE(TUINT16, TINT32): // zero extend uint16
// case CASE(TUINT16, TUINT32):
// a = AMOVWLZX;
// goto rdst;
case CASE(TUINT16, TINT32): // zero extend uint16
case CASE(TUINT16, TUINT32):
a = AMOVHU;
goto rdst;
// case CASE(TUINT16, TINT64): // convert via uint32
// case CASE(TUINT16, TUINT64):
// cvt = types[TUINT32];
@ -728,7 +730,9 @@ gmove(Node *f, Node *t)
gins(a, f, t);
return;
//rdst:
rdst:
// TODO(kaib): we almost always require a register dest anyway, this can probably be
// removed.
// requires register destination
regalloc(&r1, t->type, t);
gins(a, f, &r1);
@ -1221,21 +1225,15 @@ optoas(int op, Type *t)
a = ASUBD;
break;
// case CASE(OAND, TINT8):
// case CASE(OAND, TUINT8):
// a = AANDB;
// break;
// case CASE(OAND, TINT16):
// case CASE(OAND, TUINT16):
// a = AANDW;
// break;
// case CASE(OAND, TINT32):
// case CASE(OAND, TUINT32):
// case CASE(OAND, TPTR32):
// a = AANDL;
// break;
case CASE(OAND, TINT8):
case CASE(OAND, TUINT8):
case CASE(OAND, TINT16):
case CASE(OAND, TUINT16):
case CASE(OAND, TINT32):
case CASE(OAND, TUINT32):
case CASE(OAND, TPTR32):
a = AAND;
break;
// case CASE(OAND, TINT64):
// case CASE(OAND, TUINT64):
@ -1243,21 +1241,15 @@ optoas(int op, Type *t)
// a = AANDQ;
// break;
// case CASE(OOR, TINT8):
// case CASE(OOR, TUINT8):
// a = AORB;
// break;
// case CASE(OOR, TINT16):
// case CASE(OOR, TUINT16):
// a = AORW;
// break;
// case CASE(OOR, TINT32):
// case CASE(OOR, TUINT32):
// case CASE(OOR, TPTR32):
// a = AORL;
// break;
case CASE(OOR, TINT8):
case CASE(OOR, TUINT8):
case CASE(OOR, TINT16):
case CASE(OOR, TUINT16):
case CASE(OOR, TINT32):
case CASE(OOR, TUINT32):
case CASE(OOR, TPTR32):
a = AORR;
break;
// case CASE(OOR, TINT64):
// case CASE(OOR, TUINT64):
@ -1265,21 +1257,15 @@ optoas(int op, Type *t)
// a = AORQ;
// break;
// case CASE(OXOR, TINT8):
// case CASE(OXOR, TUINT8):
// a = AXORB;
// break;
// case CASE(OXOR, TINT16):
// case CASE(OXOR, TUINT16):
// a = AXORW;
// break;
// case CASE(OXOR, TINT32):
// case CASE(OXOR, TUINT32):
// case CASE(OXOR, TPTR32):
// a = AXORL;
// break;
case CASE(OXOR, TINT8):
case CASE(OXOR, TUINT8):
case CASE(OXOR, TINT16):
case CASE(OXOR, TUINT16):
case CASE(OXOR, TINT32):
case CASE(OXOR, TUINT32):
case CASE(OXOR, TPTR32):
a = AEOR;
break;
// case CASE(OXOR, TINT64):
// case CASE(OXOR, TUINT64):
@ -1287,21 +1273,15 @@ optoas(int op, Type *t)
// a = AXORQ;
// break;
// case CASE(OLSH, TINT8):
// case CASE(OLSH, TUINT8):
// a = ASHLB;
// break;
// case CASE(OLSH, TINT16):
// case CASE(OLSH, TUINT16):
// a = ASHLW;
// break;
// case CASE(OLSH, TINT32):
// case CASE(OLSH, TUINT32):
// case CASE(OLSH, TPTR32):
// a = ASHLL;
// break;
case CASE(OLSH, TINT8):
case CASE(OLSH, TUINT8):
case CASE(OLSH, TINT16):
case CASE(OLSH, TUINT16):
case CASE(OLSH, TINT32):
case CASE(OLSH, TUINT32):
case CASE(OLSH, TPTR32):
a = ASLL;
break;
// case CASE(OLSH, TINT64):
// case CASE(OLSH, TUINT64):
@ -1309,47 +1289,38 @@ optoas(int op, Type *t)
// a = ASHLQ;
// break;
// case CASE(ORSH, TUINT8):
// a = ASHRB;
// break;
// case CASE(ORSH, TUINT16):
// a = ASHRW;
// break;
// case CASE(ORSH, TUINT32):
// case CASE(ORSH, TPTR32):
// a = ASHRL;
// break;
case CASE(ORSH, TUINT8):
case CASE(ORSH, TUINT16):
case CASE(ORSH, TUINT32):
case CASE(ORSH, TPTR32):
a = ASRL;
break;
// case CASE(ORSH, TUINT64):
// case CASE(ORSH, TPTR64):
// a = ASHRQ;
// break;
// case CASE(ORSH, TINT8):
// a = ASARB;
// break;
// case CASE(ORSH, TINT16):
// a = ASARW;
// break;
// case CASE(ORSH, TINT32):
// a = ASARL;
// break;
case CASE(ORSH, TINT8):
case CASE(ORSH, TINT16):
case CASE(ORSH, TINT32):
a = ASRA;
break;
// case CASE(ORSH, TINT64):
// a = ASARQ;
// break;
case CASE(OMUL, TINT8):
case CASE(OMUL, TUINT8):
case CASE(OMUL, TINT16):
case CASE(OMUL, TUINT16):
case CASE(OMUL, TINT32):
case CASE(OMUL, TUINT32):
case CASE(OMUL, TPTR32):
a = AMULU;
break;
case CASE(OMUL, TINT8):
case CASE(OMUL, TINT16):
case CASE(OMUL, TINT32):
a = AMUL;
break;
@ -1359,31 +1330,37 @@ optoas(int op, Type *t)
// a = AIMULQ;
// break;
// case CASE(OMUL, TFLOAT32):
// a = AMULSS;
// break;
case CASE(OMUL, TFLOAT32):
a = AMULF;
break;
// case CASE(OMUL, TFLOAT64):
// a = AMULSD;
// break;
case CASE(OMUL, TFLOAT64):
a = AMULD;
break;
case CASE(ODIV, TINT8):
case CASE(ODIV, TUINT8):
case CASE(ODIV, TINT16):
case CASE(ODIV, TUINT16):
case CASE(ODIV, TINT32):
case CASE(ODIV, TUINT32):
case CASE(ODIV, TPTR32):
a = ADIVU;
break;
case CASE(ODIV, TINT8):
case CASE(ODIV, TINT16):
case CASE(ODIV, TINT32):
a = ADIV;
break;
case CASE(OMOD, TINT8):
case CASE(OMOD, TUINT8):
case CASE(OMOD, TINT16):
case CASE(OMOD, TUINT16):
case CASE(OMOD, TINT32):
case CASE(OMOD, TUINT32):
case CASE(OMOD, TPTR32):
a = AMODU;
break;
case CASE(OMOD, TINT8):
case CASE(OMOD, TINT16):
case CASE(OMOD, TINT32):
a = AMOD;
break;
@ -1411,13 +1388,13 @@ optoas(int op, Type *t)
// a = ACQO;
// break;
// case CASE(ODIV, TFLOAT32):
// a = ADIVSS;
// break;
case CASE(ODIV, TFLOAT32):
a = ADIVF;
break;
// case CASE(ODIV, TFLOAT64):
// a = ADIVSD;
// break;
case CASE(ODIV, TFLOAT64):
a = ADIVD;
break;
}
return a;
@ -1621,9 +1598,9 @@ oindex:
n2.type = types[tptr];
n2.xoffset = Array_nel;
} else {
nodconst(&n2, types[TUINT64], l->type->bound);
nodconst(&n2, types[TUINT32], l->type->bound);
if(o & OPtrto)
nodconst(&n2, types[TUINT64], l->type->type->bound);
nodconst(&n2, types[TUINT32], l->type->type->bound);
}
gins(optoas(OCMP, types[TUINT32]), reg1, &n2);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
@ -1666,7 +1643,7 @@ oindex_const:
n1.op = OINDREG;
n1.type = types[tptr];
n1.xoffset = Array_nel;
nodconst(&n2, types[TUINT64], v);
nodconst(&n2, types[TUINT32], v);
gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
ginscall(throwindex, 0);