}
hard:
- fatal("cgen_asop hard not implemented");
if(nr->ullman > nl->ullman) {
regalloc(&n2, nr->type, N);
cgen(nr, &n2);
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
{
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);
}
* 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
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
/*
* 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];
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);
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):
// 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):
// 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):
// 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):
// 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;
// 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;
// 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;
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);
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);