diff options
| author | forsyth <forsyth@vitanuova.com> | 2010-04-27 12:51:13 +0100 |
|---|---|---|
| committer | forsyth <forsyth@vitanuova.com> | 2010-04-27 12:51:13 +0100 |
| commit | d67b7dad77bb8aa973dad1f7c3ab0c309b114278 (patch) | |
| tree | 6794120fb327d6de19cf05eed53f80d877781a3e /utils/qc | |
| parent | 09da2e137d5eb0c940df35d989e4c31ec0654fc4 (diff) | |
20100427-1251
Diffstat (limited to 'utils/qc')
| -rw-r--r-- | utils/qc/cgen.c | 520 | ||||
| -rw-r--r-- | utils/qc/enam.c | 83 | ||||
| -rw-r--r-- | utils/qc/gc.h | 16 | ||||
| -rw-r--r-- | utils/qc/list.c | 2 | ||||
| -rw-r--r-- | utils/qc/machcap.c | 16 | ||||
| -rw-r--r-- | utils/qc/mkfile | 21 | ||||
| -rw-r--r-- | utils/qc/peep.c | 87 | ||||
| -rw-r--r-- | utils/qc/q.out.h | 89 | ||||
| -rw-r--r-- | utils/qc/reg.c | 1 | ||||
| -rw-r--r-- | utils/qc/sgen.c | 407 | ||||
| -rw-r--r-- | utils/qc/swt.c | 231 | ||||
| -rw-r--r-- | utils/qc/txt.c | 554 |
12 files changed, 1324 insertions, 703 deletions
diff --git a/utils/qc/cgen.c b/utils/qc/cgen.c index 8323466c..d26704de 100644 --- a/utils/qc/cgen.c +++ b/utils/qc/cgen.c @@ -1,5 +1,10 @@ #include "gc.h" +static void cmpv(Node*, int, Node*); +static void testv(Node*, int); +static void cgen64(Node*, Node*); +static int isvconstable(int, vlong); + void cgen(Node *n, Node *nn) { @@ -15,10 +20,18 @@ cgen(Node *n, Node *nn) } if(n == Z || n->type == T) return; - if(typesuv[n->type->etype]) { + if(typesu[n->type->etype]) { sugen(n, nn, n->type->width); return; } + if(typev[n->type->etype]) { + switch(n->op) { + case OCONST: + case OFUNC: + cgen64(n, nn); + return; + } + } l = n->left; r = n->right; o = n->op; @@ -44,13 +57,17 @@ cgen(Node *n, Node *nn) if(r != Z && r->complex >= FNX) switch(o) { default: - regret(&nod, r); - cgen(r, &nod); - - regsalloc(&nod1, r); - gopcode(OAS, &nod, Z, &nod1); + if(!typev[r->type->etype]) { + regret(&nod, r); + cgen(r, &nod); + regsalloc(&nod1, r); + gmove(&nod, &nod1); + regfree(&nod); + } else { + regsalloc(&nod1, r); + cgen(r, &nod1); + } - regfree(&nod); nod = *n; nod.right = &nod1; cgen(&nod, nn); @@ -70,6 +87,19 @@ cgen(Node *n, Node *nn) diag(n, "unknown op in cgen: %O", o); break; + case ONEG: + case OCOM: + if(nn == Z) { + nullwarn(l, Z); + break; + } + regalloc(&nod, l, nn); + cgen(l, &nod); + gopcode(o, &nod, Z, &nod); + gmove(&nod, nn); + regfree(&nod); + break; + case OAS: if(l->op == OBIT) goto bitas; @@ -132,8 +162,11 @@ cgen(Node *n, Node *nn) case OXOR: if(nn != Z) if(r->op == OCONST && r->vconst == -1){ - cgen(l, nn); - gopcode(OCOM, nn, Z, nn); + regalloc(&nod, l, nn); + cgen(l, &nod); + gopcode(OCOM, &nod, Z, &nod); + gmove(&nod, nn); + regfree(&nod); break; } @@ -147,15 +180,14 @@ cgen(Node *n, Node *nn) /* * immediate operands */ - if(nn != Z) - if(r->op == OCONST) - if(!typefd[n->type->etype]) { - cgen(l, nn); - if(r->vconst == 0) - if(o != OAND) - break; - if(nn != Z) - gopcode(o, r, Z, nn); + if(nn != Z && r->op == OCONST && !typefd[n->type->etype] && + (!typev[n->type->etype] || isvconstable(o, r->vconst))) { + regalloc(&nod, l, nn); + cgen(l, &nod); + if(o == OAND || r->vconst != 0) + gopcode(o, r, Z, &nod); + gmove(&nod, nn); + regfree(&nod); break; } @@ -169,7 +201,7 @@ cgen(Node *n, Node *nn) nullwarn(l, r); break; } - if(o == OMUL || o == OLMUL) { + if((o == OMUL || o == OLMUL) && !typev[n->type->etype]) { if(mulcon(n, nn)) break; if(debug['M']) @@ -178,19 +210,23 @@ cgen(Node *n, Node *nn) if(l->complex >= r->complex) { regalloc(&nod, l, nn); cgen(l, &nod); - regalloc(&nod1, r, Z); + if(o != OMUL || typev[n->type->etype] || !sconst(r)) { + regalloc(&nod1, r, Z); + cgen(r, &nod1); + gopcode(o, &nod1, Z, &nod); + regfree(&nod1); + } else + gopcode(o, r, Z, &nod); + } else { + regalloc(&nod1, r, nn); cgen(r, &nod1); + regalloc(&nod, l, Z); + cgen(l, &nod); gopcode(o, &nod1, Z, &nod); - } else { - regalloc(&nod, r, nn); - cgen(r, &nod); - regalloc(&nod1, l, Z); - cgen(l, &nod1); - gopcode(o, &nod, &nod1, &nod); + regfree(&nod1); } gopcode(OAS, &nod, Z, nn); regfree(&nod); - regfree(&nod1); break; case OASLSHR: @@ -203,14 +239,13 @@ cgen(Node *n, Node *nn) case OASOR: if(l->op == OBIT) goto asbitop; - if(r->op == OCONST) - if(!typefd[r->type->etype]) - if(!typefd[n->type->etype]) { + if(r->op == OCONST && !typefd[r->type->etype] && !typefd[n->type->etype] && + (!typev[n->type->etype] || isvconstable(o, r->vconst))) { if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; - regalloc(&nod, r, nn); + regalloc(&nod, l, nn); gopcode(OAS, &nod2, Z, &nod); gopcode(o, r, Z, &nod); gopcode(OAS, &nod, Z, &nod2); @@ -234,20 +269,22 @@ cgen(Node *n, Node *nn) reglcgen(&nod2, l, Z); else nod2 = *l; - regalloc(&nod, n, nn); + regalloc(&nod, r, Z); cgen(r, &nod); } else { - regalloc(&nod, n, nn); + regalloc(&nod, r, Z); cgen(r, &nod); if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; } - regalloc(&nod1, n, Z); + regalloc(&nod1, n, nn); gopcode(OAS, &nod2, Z, &nod1); - gopcode(o, &nod, &nod1, &nod); - gopcode(OAS, &nod, Z, &nod2); + gopcode(o, &nod, Z, &nod1); + gopcode(OAS, &nod1, Z, &nod2); + if(nn != Z) + gopcode(OAS, &nod1, Z, nn); regfree(&nod); regfree(&nod1); if(l->addable < INDEXED) @@ -336,7 +373,7 @@ cgen(Node *n, Node *nn) } else cgen(l, &nod); regind(&nod, n); - gopcode(OAS, &nod, Z, nn); + gmove(&nod, nn); regfree(&nod); break; @@ -390,11 +427,15 @@ cgen(Node *n, Node *nn) cgen(l, nn); break; } + if(typev[l->type->etype] || typev[n->type->etype]) { + cgen64(n, nn); + break; + } regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, n, &nod); - gopcode(OAS, &nod, Z, &nod1); - gopcode(OAS, &nod1, Z, nn); + gmove(&nod, &nod1); + gmove(&nod1, nn); regfree(&nod1); regfree(&nod); break; @@ -496,6 +537,8 @@ cgen(Node *n, Node *nn) } else gopcode(OADD, nodconst(v), Z, &nod); gopcode(OAS, &nod, Z, &nod2); + if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */ + gins(ANOP, l, Z); regfree(&nod); if(l->addable < INDEXED) @@ -608,7 +651,7 @@ bcgen(Node *n, int true) void boolgen(Node *n, int true, Node *nn) { - int o; + int o, uns; Prog *p1, *p2; Node *l, *r, nod, nod1; long curs; @@ -617,6 +660,7 @@ boolgen(Node *n, int true, Node *nn) prtree(nn, "boolgen lhs"); prtree(n, "boolgen"); } + uns = 0; curs = cursafe; l = n->left; r = n->right; @@ -635,6 +679,10 @@ boolgen(Node *n, int true, Node *nn) } goto com; } + if(typev[n->type->etype]) { + testv(n, true); + goto com; + } regalloc(&nod, n, nn); cgen(n, &nod); o = ONE; @@ -701,16 +749,22 @@ boolgen(Node *n, int true, Node *nn) patch(p2, pc); goto com; + case OHI: + case OHS: + case OLO: + case OLS: + uns = 1; + /* fall through */ case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: - case OHI: - case OHS: - case OLO: - case OLS: + if(typev[l->type->etype]){ + cmpv(n, true, Z); + goto com; + } o = n->op; if(true) o = comrel[relindex(o)]; @@ -725,7 +779,7 @@ boolgen(Node *n, int true, Node *nn) boolgen(&nod, true, nn); break; } - if(sconst(r)) { + if(!uns && sconst(r) || (uns || o == OEQ || o == ONE) && uconst(r)) { regalloc(&nod, l, nn); cgen(l, &nod); gopcode(o, &nod, Z, r); @@ -773,13 +827,17 @@ sugen(Node *n, Node *nn, long w) if(n == Z || n->type == T) return; + if(nn == nodrat) + if(w > nrathole) + nrathole = w; if(debug['g']) { prtree(nn, "sugen lhs"); prtree(n, "sugen"); } - if(nn == nodrat) - if(w > nrathole) - nrathole = w; + if(typev[n->type->etype]) { + diag(n, "old vlong sugen: %O", n->op); + return; + } switch(n->op) { case OIND: if(nn == Z) { @@ -790,33 +848,6 @@ sugen(Node *n, Node *nn, long w) default: goto copy; - case OCONST: - if(n->type && typev[n->type->etype]) { - if(nn == Z) { - nullwarn(n->left, Z); - break; - } - - t = nn->type; - nn->type = types[TLONG]; - reglcgen(&nod1, nn, Z); - nn->type = t; - - if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ - gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); - else - gopcode(OAS, nod32const(n->vconst), Z, &nod1); - nod1.xoffset += SZ_LONG; - if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ - gopcode(OAS, nod32const(n->vconst), Z, &nod1); - else - gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); - - regfree(&nod1); - break; - } - goto copy; - case ODOT: l = n->left; sugen(l, nodrat, l->type->width); @@ -922,6 +953,7 @@ sugen(Node *n, Node *nn, long w) break; case OFUNC: + /* this transformation should probably be done earlier */ if(nn == Z) { sugen(n, nodrat, w); break; @@ -933,6 +965,7 @@ sugen(Node *n, Node *nn, long w) } else nn = nn->left; n = new(OFUNC, n->left, new(OLIST, nn, n->right)); + n->complex = FNX; n->type = types[TVOID]; n->left->type = types[TVOID]; cgen(n, Z); @@ -967,7 +1000,7 @@ copy: regsalloc(&nod2, nn); nn->type = t; - gopcode(OAS, &nod1, Z, &nod2); + gmove(&nod1, &nod2); regfree(&nod1); nod2.type = typ(TIND, t); @@ -1089,3 +1122,338 @@ layout(Node *f, Node *t, int c, int cv, Node *cn) regfree(&t1); regfree(&t2); } + +/* + * is the vlong's value directly addressible? + */ +int +isvdirect(Node *n) +{ + return n->op == ONAME || n->op == OCONST || n->op == OINDREG; +} + +/* + * can the constant be used with given vlong op? + */ +static int +isvconstable(int o, vlong v) +{ + switch(o) { + case OADD: + case OASADD: + /* there isn't an immediate form for ADDE/SUBE, but there are special ADDME/ADDZE etc */ + return v == 0 || v == -1; + case OAND: + case OOR: + case OXOR: + case OLSHR: + case OASHL: + case OASHR: + case OASLSHR: + case OASASHL: + case OASASHR: + return 1; + } + return 0; +} + +/* + * most 64-bit operations: cgen into a register pair, then operate. + * 64-bit comparisons are handled a little differently because the two underlying + * comparisons can be compiled separately, since the calculations don't interact. + */ + +static void +vcgen(Node *n, Node *o, int *f) +{ + *f = 0; + if(!isvdirect(n)) { + if(n->complex >= FNX) { + regsalloc(o, n); + cgen(n, o); + return; + } + *f = 1; + if(n->addable < INDEXED && n->op != OIND && n->op != OINDEX) { + regalloc(o, n, Z); + cgen(n, o); + } else + reglcgen(o, n, Z); + } else + *o = *n; +} + +static int +isuns(int op) +{ + switch(op){ + case OLO: + case OLS: + case OHI: + case OHS: + return 1; + default: + return 0; + } +} + +static void +gcmpv(Node *l, Node *r, void (*mov)(Node*, Node*, int), int op) +{ + Node vl, vr; + + regalloc(&vl, ®node, Z); + mov(l, &vl, 0); + regalloc(&vr, ®node, Z); + mov(r, &vr, 1+isuns(op)); + gopcode(op, &vl, Z, &vr); + if(vl.op == OREGISTER) + regfree(&vl); + if(vr.op == OREGISTER) + regfree(&vr); +} + +static void +brcondv(Node *l, Node *r, int chi, int clo) +{ + Prog *p1, *p2, *p3, *p4; + + gcmpv(l, r, gloadhi, chi); + p1 = p; + gins(ABNE, Z, Z); + p2 = p; + gcmpv(l, r, gloadlo, clo); + p3 = p; + gbranch(OGOTO); + p4 = p; + patch(p1, pc); + patch(p3, pc); + gbranch(OGOTO); + patch(p2, pc); + patch(p4, pc); +} + +static void +testv(Node *n, int true) +{ + Node nod; + + nod = znode; + nod.op = ONE; + nod.left = n; + nod.right = new1(0, Z, Z); + *nod.right = *nodconst(0); + nod.right->type = n->type; + nod.type = types[TLONG]; + cmpv(&nod, true, Z); +} + +/* + * comparison for vlong does high and low order parts separately, + * which saves loading the latter if the high order comparison suffices + */ +static void +cmpv(Node *n, int true, Node *nn) +{ + Node *l, *r, nod, nod1; + int o, f1, f2; + Prog *p1, *p2; + long curs; + + if(debug['g']) { + if(nn != nil) + prtree(nn, "cmpv lhs"); + prtree(n, "cmpv"); + } + curs = cursafe; + l = n->left; + r = n->right; + if(l->complex >= FNX && r->complex >= FNX) { + regsalloc(&nod1, r); + cgen(r, &nod1); + nod = *n; + nod.right = &nod1; + cmpv(&nod, true, nn); + cursafe = curs; + return; + } + if(l->complex >= r->complex) { + vcgen(l, &nod1, &f1); + vcgen(r, &nod, &f2); + } else { + vcgen(r, &nod, &f2); + vcgen(l, &nod1, &f1); + } + nod.type = types[TLONG]; + nod1.type = types[TLONG]; + o = n->op; + if(true) + o = comrel[relindex(o)]; + switch(o){ + case OEQ: + gcmpv(&nod1, &nod, gloadhi, ONE); + p1 = p; + gcmpv(&nod1, &nod, gloadlo, ONE); + p2 = p; + gbranch(OGOTO); + patch(p1, pc); + patch(p2, pc); + break; + case ONE: + gcmpv(&nod1, &nod, gloadhi, ONE); + p1 = p; + gcmpv(&nod1, &nod, gloadlo, OEQ); + p2 = p; + patch(p1, pc); + gbranch(OGOTO); + patch(p2, pc); + break; + case OLE: + brcondv(&nod1, &nod, OLT, OLS); + break; + case OGT: + brcondv(&nod1, &nod, OGT, OHI); + break; + case OLS: + brcondv(&nod1, &nod, OLO, OLS); + break; + case OHI: + brcondv(&nod1, &nod, OHI, OHI); + break; + case OLT: + brcondv(&nod1, &nod, OLT, OLO); + break; + case OGE: + brcondv(&nod1, &nod, OGT, OHS); + break; + case OLO: + brcondv(&nod1, &nod, OLO, OLO); + break; + case OHS: + brcondv(&nod1, &nod, OHI, OHS); + break; + default: + diag(n, "bad cmpv"); + return; + } + if(f1) + regfree(&nod1); + if(f2) + regfree(&nod); + cursafe = curs; +} + +static void +cgen64(Node *n, Node *nn) +{ + Node *l, *r, *d; + Node nod, nod1; + long curs; + Type *t; + int o, m; + + curs = cursafe; + l = n->left; + r = n->right; + o = n->op; + switch(o) { + + case OCONST: + if(nn == Z) { + nullwarn(n->left, Z); + break; + } + if(nn->op != OREGPAIR) { +//prtree(n, "cgen64 const"); + t = nn->type; + nn->type = types[TLONG]; + reglcgen(&nod1, nn, Z); + nn->type = t; + + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gmove(nod32const(n->vconst>>32), &nod1); + else + gmove(nod32const(n->vconst), &nod1); + nod1.xoffset += SZ_LONG; + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gmove(nod32const(n->vconst), &nod1); + else + gmove(nod32const(n->vconst>>32), &nod1); + + regfree(&nod1); + } else + gmove(n, nn); + break; + + case OCAST: + /* + * convert from types l->n->nn + */ + if(typev[l->type->etype]){ + /* vlong to non-vlong */ + if(!isvdirect(l)) { + if(l->addable < INDEXED && l->op != OIND && l->op != OINDEX) { + regalloc(&nod, l, l); + cgen(l, &nod); + regalloc(&nod1, n, nn); + gmove(nod.right, &nod1); + } else { + reglcgen(&nod, l, Z); + regalloc(&nod1, n, nn); + gloadlo(&nod, &nod1, 0); /* TO DO: not correct for typefd */ + } + regfree(&nod); + } else { + regalloc(&nod1, n, nn); + gloadlo(l, &nod1, 0); /* TO DO: not correct for typefd */ + } + }else{ + /* non-vlong to vlong */ + regalloc(&nod, l, Z); + cgen(l, &nod); + regalloc(&nod1, n, nn); + gmove(&nod, nod1.right); + if(typeu[l->type->etype]) + gmove(nodconst(0), nod1.left); + else + gopcode(OASHR, nodconst(31), nod1.right, nod1.left); + regfree(&nod); + } + gmove(&nod1, nn); + regfree(&nod1); + break; + + case OFUNC: + /* this transformation should probably be done earlier */ + if(nn == Z) { + regsalloc(&nod1, n); + nn = &nod1; + } + m = 0; + if(nn->op != OIND) { + if(nn->op == OREGPAIR) { + m = 1; + regsalloc(&nod1, nn); + d = &nod1; + }else + d = nn; + d = new1(OADDR, d, Z); + d->type = types[TIND]; + d->addable = 0; + } else + d = nn->left; + n = new(OFUNC, l, new(OLIST, d, r)); + n->complex = FNX; + n->type = types[TVOID]; + n->left->type = types[TVOID]; + cgen(n, Z); + if(m) + gmove(&nod1, nn); + break; + + default: + diag(n, "bad cgen64 %O", o); + break; + } + cursafe = curs; +} diff --git a/utils/qc/enam.c b/utils/qc/enam.c index 70535f8a..98d0edcf 100644 --- a/utils/qc/enam.c +++ b/utils/qc/enam.c @@ -130,21 +130,11 @@ char *anames[] = "MOVW", "MOVWU", "MOVFL", - "MOVCRFXXX", "MOVCRFS", - "MOVCRXRXXX", - "MOVFCRXXX", - "MFFSXXX", - "MFFSCCXXX", - "MTCRFXXX", "MTFSB0", "MTFSB0CC", "MTFSB1", "MTFSB1CC", - "MTFSFXXX", - "MTFSFCCXXX", - "MTFSFIXXX", - "MTFSFIXXXCC", "MULHW", "MULHWCC", "MULHWU", @@ -184,9 +174,7 @@ char *anames[] = "SRAW", "SRAWCC", "SRWCC", - "ILLXXX1", "STSW", - "STWBRXXX", "STWCCC", "SUB", "SUBCC", @@ -323,5 +311,76 @@ char *anames[] = "NMACLHWV", "NMACLHWVCC", "RFCI", + "FRES", + "FRESCC", + "FRSQRTE", + "FRSQRTECC", + "FSEL", + "FSELCC", + "FSQRT", + "FSQRTCC", + "FSQRTS", + "FSQRTSCC", + "FPSEL", + "FPMUL", + "FXMUL", + "FXPMUL", + "FXSMUL", + "FPADD", + "FPSUB", + "FPRE", + "FPRSQRTE", + "FPMADD", + "FXMADD", + "FXCPMADD", + "FXCSMADD", + "FPNMADD", + "FXNMADD", + "FXCPNMADD", + "FXCSNMADD", + "FPMSUB", + "FXMSUB", + "FXCPMSUB", + "FXCSMSUB", + "FPNMSUB", + "FXNMSUB", + "FXCPNMSUB", + "FXCSNMSUB", + "FPMOVD", + "FPABS", + "FPNEG", + "FPRSP", + "FPNABS", + "FSMOVD", + "FSCMP", + "FSABS", + "FSNEG", + "FSNABS", + "FXMOVD", + "FPCTIW", + "FPCTIWZ", + "FSMOVP", + "FPMOVS", + "FXCPNPMA", + "FXCSNPMA", + "FXCPNSMA", + "FXCSNSMA", + "FXCXNPMA", + "FXCXNSMA", + "FXCXMA", + "FXCXNMS", + "FMOVSS", + "FMOVSSU", + "FMOVSD", + "FMOVSDU", + "FMOVXS", + "FMOVSXU", + "FMOVXD", + "FMOVXDU", + "FMOVPS", + "FMOVPSU", + "FMOVPD", + "FMOVPDU", + "FMOVPIW", "LAST", }; diff --git a/utils/qc/gc.h b/utils/qc/gc.h index bf4e9091..16aab0ba 100644 --- a/utils/qc/gc.h +++ b/utils/qc/gc.h @@ -58,6 +58,7 @@ struct Case long val; long label; char def; + char isv; }; #define C ((Case*)0) @@ -129,6 +130,7 @@ struct Rgn }; EXTERN long breakpc; +EXTERN long nbreak; EXTERN Case* cases; EXTERN Node constnode; EXTERN Node fconstnode; @@ -141,10 +143,10 @@ EXTERN int hintabsize; EXTERN long maxargsafe; EXTERN Multab multab[20]; EXTERN int mnstring; -EXTERN int retok; EXTERN Node* nodrat; EXTERN Node* nodret; EXTERN Node* nodsafe; +EXTERN Node* nodretv; EXTERN long nrathole; EXTERN long nstring; EXTERN Prog* p; @@ -244,8 +246,11 @@ void regind(Node*, Node*); void gprep(Node*, Node*); void raddr(Node*, Prog*); void naddr(Node*, Adr*); +void gloadhi(Node*, Node*, int); +void gloadlo(Node*, Node*, int); void gmove(Node*, Node*); void gins(int a, Node*, Node*); +void gins3(int a, Node*, Node*, Node*); void gopcode(int, Node*, Node*, Node*); int samaddr(Node*, Node*); void gbranch(int); @@ -253,6 +258,10 @@ void patch(Prog*, long); int sconst(Node*); int sval(long); int uconst(Node*); +long hi64v(Node*); +long lo64v(Node*); +Node* hi64(Node*); +Node* lo64(Node*); void gpseudo(int, Sym*, Node*); /* @@ -260,8 +269,9 @@ void gpseudo(int, Sym*, Node*); */ int swcmp(void*, void*); void doswit(Node*); -void swit1(C1*, int, long, Node*, Node*); -void cas(void); +void swit1(C1*, int, long, Node*); +void swit2(C1*, int, long, Node*, Node*); +void casf(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); long outstring(char*, long); diff --git a/utils/qc/list.c b/utils/qc/list.c index 3538c621..2f7eeb18 100644 --- a/utils/qc/list.c +++ b/utils/qc/list.c @@ -72,7 +72,7 @@ Aconv(Fmt *fp) a = va_arg(fp->args, int); s = "???"; - if(a >= AXXX && a <= AEND) + if(a >= AXXX && a <= ALAST) s = anames[a]; return fmtstrcpy(fp, s); } diff --git a/utils/qc/machcap.c b/utils/qc/machcap.c new file mode 100644 index 00000000..5fae5731 --- /dev/null +++ b/utils/qc/machcap.c @@ -0,0 +1,16 @@ +#include "gc.h" + +/* default, like old cc */ +int +machcap(Node *n) +{ + if(n == Z) + return 0; /* test */ + switch(n->op){ + case OCOMMA: + case OCOND: + case OLIST: + return 1; + } + return 0; +} diff --git a/utils/qc/mkfile b/utils/qc/mkfile index 21933876..19258dba 100644 --- a/utils/qc/mkfile +++ b/utils/qc/mkfile @@ -3,14 +3,17 @@ TARG=qc OFILES=\ cgen.$O\ - reg.$O\ - txt.$O\ - peep.$O\ - swt.$O\ - sgen.$O\ - list.$O\ enam.$O\ + list.$O\ + machcap.$O\ mul.$O\ + peep.$O\ + pgen.$O\ + pswt.$O\ + reg.$O\ + sgen.$O\ + swt.$O\ + txt.$O\ HFILES=\ gc.h\ @@ -27,3 +30,9 @@ $ROOT/$OBJDIR/lib/libcc.a: cd ../cc mk $MKFLAGS install mk $MKFLAGS clean + +%.$O: ../cc/%.c + $CC $CFLAGS ../cc/$stem.c + +#enam.c: q.out.h +# rc mkenam diff --git a/utils/qc/peep.c b/utils/qc/peep.c index 69d021be..cf1114f0 100644 --- a/utils/qc/peep.c +++ b/utils/qc/peep.c @@ -167,7 +167,16 @@ loop1: case AORNCC: case AXORCC: case ASUBCC: + case ASUBECC: + case ASUBMECC: + case ASUBZECC: case AADDCC: + case AADDCCC: + case AADDECC: + case AADDMECC: + case AADDZECC: + case ARLWMICC: + case ARLWNMCC: t = p1->as; break; /* don't deal with floating point instructions for now */ @@ -269,6 +278,7 @@ excise(Reg *r) p = r->prog; p->as = ANOP; p->from = zprog.from; + p->from3 = zprog.from3; p->to = zprog.to; p->reg = zprog.reg; /**/ } @@ -309,7 +319,6 @@ uniqs(Reg *r) * if the system forces R0 to be zero, * convert references to $0 to references to R0. */ -int regzer(Adr *a) { if(R0ISZERO) { @@ -324,7 +333,6 @@ regzer(Adr *a) return 0; } -int regtyp(Adr *a) { @@ -376,10 +384,22 @@ subprop(Reg *r0) return 0; case AADD: + case AADDC: + case AADDCC: + case AADDE: + case AADDECC: case ASUB: + case ASUBCC: + case ASUBC: + case ASUBCCC: + case ASUBE: + case ASUBECC: case ASLW: + case ASLWCC: case ASRW: + case ASRWCC: case ASRAW: + case ASRAWCC: case AOR: case AORCC: case AORN: @@ -394,13 +414,17 @@ subprop(Reg *r0) case ANORCC: case AXOR: case AXORCC: + case AMULHW: + case AMULHWU: case AMULLW: case ADIVW: case ADIVWU: case AREM: case AREMU: - case ANEG: - case ANEGCC: + case ARLWNM: + case ARLWNMCC: + case ARLWMI: + case ARLWMICC: case AFADD: case AFADDS: @@ -410,8 +434,6 @@ subprop(Reg *r0) case AFMULS: case AFDIV: case AFDIVS: - case AFNEG: - case AFNEGCC: if(p->to.type == v1->type) if(p->to.reg == v1->reg) { if(p->reg == NREG) @@ -420,6 +442,18 @@ subprop(Reg *r0) } break; + case AADDME: + case AADDMECC: + case AADDZE: + case AADDZECC: + case ASUBME: + case ASUBMECC: + case ASUBZE: + case ASUBZECC: + case ANEG: + case ANEGCC: + case AFNEG: + case AFNEGCC: case AFMOVS: case AFMOVD: case AMOVW: @@ -492,7 +526,6 @@ copyprop(Reg *r0) return copy1(v1, v2, r0->s1, 0); } -int copy1(Adr *v1, Adr *v2, Reg *r, int f) { int t; @@ -585,7 +618,7 @@ copyu(Prog *p, Adr *v, Adr *s) default: if(debug['P']) - print(" (?)"); + print(" (???)"); return 2; @@ -598,6 +631,14 @@ copyu(Prog *p, Adr *v, Adr *s) case ANEG: case ANEGCC: + case AADDME: + case AADDMECC: + case AADDZE: + case AADDZECC: + case ASUBME: + case ASUBMECC: + case ASUBZE: + case ASUBZECC: case AFCTIW: case AFCTIWZ: @@ -626,6 +667,8 @@ copyu(Prog *p, Adr *v, Adr *s) return 0; case AADD: /* read read write */ + case AADDC: + case AADDE: case ASUB: case ASLW: case ASRW: @@ -643,11 +686,17 @@ copyu(Prog *p, Adr *v, Adr *s) case ANOR: case ANORCC: case AXOR: + case AMULHW: + case AMULHWU: case AMULLW: case ADIVW: case ADIVWU: case AREM: case AREMU: + case ARLWMI: + case ARLWMICC: + case ARLWNM: + case ARLWNMCC: case AFADDS: case AFADD: @@ -763,9 +812,25 @@ a2type(Prog *p) switch(p->as) { case AADD: + case AADDC: case AADDCC: + case AADDCCC: + case AADDE: + case AADDECC: + case AADDME: + case AADDMECC: + case AADDZE: + case AADDZECC: case ASUB: + case ASUBC: case ASUBCC: + case ASUBCCC: + case ASUBE: + case ASUBECC: + case ASUBME: + case ASUBMECC: + case ASUBZE: + case ASUBZECC: case ASLW: case ASLWCC: case ASRW: @@ -784,6 +849,8 @@ a2type(Prog *p) case AXORCC: case ANEG: case ANEGCC: + case AMULHW: + case AMULHWU: case AMULLW: case AMULLWCC: case ADIVW: @@ -798,6 +865,10 @@ a2type(Prog *p) case ANANDCC: case ANOR: case ANORCC: + case ARLWMI: + case ARLWMICC: + case ARLWNM: + case ARLWNMCC: return D_REG; case AFADDS: diff --git a/utils/qc/q.out.h b/utils/qc/q.out.h index 795da7f7..1c5a141e 100644 --- a/utils/qc/q.out.h +++ b/utils/qc/q.out.h @@ -169,21 +169,11 @@ enum as AMOVW, AMOVWU, AMOVFL, - AMOVCRFXXX, AMOVCRFS, - AMOVCRXRXXX, - AMOVFCRXXX, - AMFFSXXX, - AMFFSCCXXX, - AMTCRFXXX, AMTFSB0, AMTFSB0CC, AMTFSB1, AMTFSB1CC, - AMTFSFXXX, - AMTFSFCCXXX, - AMTFSFIXXX, - AMTFSFIXXXCC, AMULHW, AMULHWCC, AMULHWU, @@ -223,9 +213,7 @@ enum as ASRAW, ASRAWCC, ASRWCC, - AILLXXX1, ASTSW, - ASTWBRXXX, ASTWCCC, ASUB, ASUBCC, @@ -368,6 +356,83 @@ enum as ARFCI, + /* optional on 32-bit */ + AFRES, + AFRESCC, + AFRSQRTE, + AFRSQRTECC, + AFSEL, + AFSELCC, + AFSQRT, + AFSQRTCC, + AFSQRTS, + AFSQRTSCC, + + /* parallel, cross, and secondary */ + AFPSEL, + AFPMUL, + AFXMUL, + AFXPMUL, + AFXSMUL, + AFPADD, + AFPSUB, + AFPRE, + AFPRSQRTE, + AFPMADD, + AFXMADD, + AFXCPMADD, + AFXCSMADD, + AFPNMADD, + AFXNMADD, + AFXCPNMADD, + AFXCSNMADD, + AFPMSUB, + AFXMSUB, + AFXCPMSUB, + AFXCSMSUB, + AFPNMSUB, + AFXNMSUB, + AFXCPNMSUB, + AFXCSNMSUB, + AFPMOVD, + AFPABS, + AFPNEG, + AFPRSP, + AFPNABS, + AFSMOVD, + AFSCMP, + AFSABS, + AFSNEG, + AFSNABS, + AFXMOVD, + AFPCTIW, + AFPCTIWZ, + AFSMOVP, + AFPMOVS, + AFXCPNPMA, + AFXCSNPMA, + AFXCPNSMA, + AFXCSNSMA, + AFXCXNPMA, + AFXCXNSMA, + AFXCXMA, + AFXCXNMS, + + /* parallel, cross, and secondary load and store */ + AFMOVSS, + AFMOVSSU, + AFMOVSD, + AFMOVSDU, + AFMOVXS, + AFMOVSXU, + AFMOVXD, + AFMOVXDU, + AFMOVPS, + AFMOVPSU, + AFMOVPD, + AFMOVPDU, + AFMOVPIW, + ALAST }; diff --git a/utils/qc/reg.c b/utils/qc/reg.c index c1a900b0..33152f27 100644 --- a/utils/qc/reg.c +++ b/utils/qc/reg.c @@ -840,7 +840,6 @@ allreg(ulong b, Rgn *r) } break; - case TVLONG: case TDOUBLE: case TFLOAT: i = BtoF(~b); diff --git a/utils/qc/sgen.c b/utils/qc/sgen.c index d557d375..37542ebb 100644 --- a/utils/qc/sgen.c +++ b/utils/qc/sgen.c @@ -1,381 +1,6 @@ #include "gc.h" void -codgen(Node *n, Node *nn) -{ - Prog *sp; - Node *n1, nod, nod1; - - cursafe = 0; - curarg = 0; - maxargsafe = 0; - - /* - * isolate name - */ - for(n1 = nn;; n1 = n1->left) { - if(n1 == Z) { - diag(nn, "cant find function name"); - return; - } - if(n1->op == ONAME) - break; - } - nearln = nn->lineno; - gpseudo(ATEXT, n1->sym, nodconst(stkoff)); - sp = p; - - /* - * isolate first argument - */ - if(REGARG) { - if(typesuv[thisfn->link->etype]) { - nod1 = *nodret->left; - nodreg(&nod, &nod1, REGARG); - gopcode(OAS, &nod, Z, &nod1); - } else - if(firstarg && typechlp[firstargtype->etype]) { - nod1 = *nodret->left; - nod1.sym = firstarg; - nod1.type = firstargtype; - nod1.xoffset = align(0, firstargtype, Aarg1); - nod1.etype = firstargtype->etype; - nodreg(&nod, &nod1, REGARG); - gopcode(OAS, &nod, Z, &nod1); - } - } - - retok = 0; - gen(n); - if(!retok) - if(thisfn->link->etype != TVOID) - warn(Z, "no return at end of function: %s", n1->sym->name); - noretval(3); - gbranch(ORETURN); - - if(!debug['N'] || debug['R'] || debug['P']) - regopt(sp); - - sp->to.offset += maxargsafe; -} - -void -supgen(Node *n) -{ - long spc; - Prog *sp; - - if(n == Z) - return; - suppress++; - spc = pc; - sp = lastp; - gen(n); - lastp = sp; - pc = spc; - sp->link = nil; - suppress--; -} - -void -gen(Node *n) -{ - Node *l, nod; - Prog *sp, *spc, *spb; - Case *cn; - long sbc, scc; - int o, f; - -loop: - if(n == Z) - return; - nearln = n->lineno; - o = n->op; - if(debug['G']) - if(o != OLIST) - print("%L %O\n", nearln, o); - retok = 0; - switch(o) { - - default: - complex(n); - cgen(n, Z); - break; - - case OLIST: - gen(n->left); - - rloop: - n = n->right; - goto loop; - - case ORETURN: - retok = 1; - complex(n); - if(n->type == T) - break; - l = n->left; - if(l == Z) { - noretval(3); - gbranch(ORETURN); - break; - } - if(typesuv[n->type->etype]) { - sugen(l, nodret, n->type->width); - noretval(3); - gbranch(ORETURN); - break; - } - regret(&nod, n); - cgen(l, &nod); - regfree(&nod); - if(typefd[n->type->etype]) - noretval(1); - else - noretval(2); - gbranch(ORETURN); - break; - - case OLABEL: - l = n->left; - if(l) { - l->xoffset = pc; - if(l->label) - patch(l->label, pc); - } - gbranch(OGOTO); /* prevent self reference in reg */ - patch(p, pc); - goto rloop; - - case OGOTO: - retok = 1; - n = n->left; - if(n == Z) - return; - if(n->complex == 0) { - diag(Z, "label undefined: %s", n->sym->name); - return; - } - if(suppress) - return; - gbranch(OGOTO); - if(n->xoffset) { - patch(p, n->xoffset); - return; - } - if(n->label) - patch(n->label, pc-1); - n->label = p; - return; - - case OCASE: - l = n->left; - if(cases == C) - diag(n, "case/default outside a switch"); - if(l == Z) { - cas(); - cases->val = 0; - cases->def = 1; - cases->label = pc; - goto rloop; - } - complex(l); - if(l->type == T) - goto rloop; - if(l->op == OCONST) - if(typechl[l->type->etype]) { - cas(); - cases->val = l->vconst; - cases->def = 0; - cases->label = pc; - goto rloop; - } - diag(n, "case expression must be integer constant"); - goto rloop; - - case OSWITCH: - l = n->left; - complex(l); - if(l->type == T) - break; - if(!typechl[l->type->etype]) { - diag(n, "switch expression must be integer"); - break; - } - - gbranch(OGOTO); /* entry */ - sp = p; - - cn = cases; - cases = C; - cas(); - - sbc = breakpc; - breakpc = pc; - gbranch(OGOTO); - spb = p; - - gen(n->right); - gbranch(OGOTO); - patch(p, breakpc); - - patch(sp, pc); - regalloc(&nod, l, Z); - nod.type = types[TLONG]; - cgen(l, &nod); - doswit(&nod); - regfree(&nod); - patch(spb, pc); - - cases = cn; - breakpc = sbc; - break; - - case OWHILE: - case ODWHILE: - l = n->left; - gbranch(OGOTO); /* entry */ - sp = p; - - scc = continpc; - continpc = pc; - gbranch(OGOTO); - spc = p; - - sbc = breakpc; - breakpc = pc; - gbranch(OGOTO); - spb = p; - - patch(spc, pc); - if(n->op == OWHILE) - patch(sp, pc); - bcomplex(l, Z); /* test */ - patch(p, breakpc); - - if(n->op == ODWHILE) - patch(sp, pc); - gen(n->right); /* body */ - gbranch(OGOTO); - patch(p, continpc); - - patch(spb, pc); - continpc = scc; - breakpc = sbc; - break; - - case OFOR: - l = n->left; - gen(l->right->left); /* init */ - gbranch(OGOTO); /* entry */ - sp = p; - - scc = continpc; - continpc = pc; - gbranch(OGOTO); - spc = p; - - sbc = breakpc; - breakpc = pc; - gbranch(OGOTO); - spb = p; - - patch(spc, pc); - gen(l->right->right); /* inc */ - patch(sp, pc); - if(l->left != Z) { /* test */ - bcomplex(l->left, Z); - patch(p, breakpc); - } - gen(n->right); /* body */ - gbranch(OGOTO); - patch(p, continpc); - - patch(spb, pc); - continpc = scc; - breakpc = sbc; - break; - - case OCONTINUE: - if(continpc < 0) { - diag(n, "continue not in a loop"); - break; - } - gbranch(OGOTO); - patch(p, continpc); - break; - - case OBREAK: - if(breakpc < 0) { - diag(n, "break not in a loop"); - break; - } - gbranch(OGOTO); - patch(p, breakpc); - break; - - case OIF: - l = n->left; - if(bcomplex(l, n->right)) { - if(typefd[l->type->etype]) - f = !l->fconst; - else - f = !l->vconst; - if(debug['c']) - print("%L const if %s\n", nearln, f ? "false" : "true"); - if(f) { - supgen(n->right->left); - gen(n->right->right); - } - else { - gen(n->right->left); - supgen(n->right->right); - } - } - else { - sp = p; - if(n->right->left != Z) - gen(n->right->left); - if(n->right->right != Z) { - gbranch(OGOTO); - patch(sp, pc); - sp = p; - gen(n->right->right); - } - patch(sp, pc); - } - break; - - case OSET: - case OUSED: - usedset(n->left, o); - break; - } -} - -void -usedset(Node *n, int o) -{ - if(n->op == OLIST) { - usedset(n->left, o); - usedset(n->right, o); - return; - } - complex(n); - switch(n->op) { - case OADDR: /* volatile */ - gins(ANOP, n, Z); - break; - case ONAME: - if(o == OSET) - gins(ANOP, Z, n); - else - gins(ANOP, n, Z); - break; - } -} - -void noretval(int n) { @@ -410,7 +35,7 @@ void xcom(Node *n) { Node *l, *r; - int v; + int v, nr; if(n == Z) return; @@ -568,14 +193,23 @@ xcom(Node *n) if(l != Z) n->complex = l->complex; if(r != Z) { + nr = 1; + if(r->type != T && typev[r->type->etype] || n->type != T && typev[n->type->etype]) { + nr = 2; + if(n->op == OMUL || n->op == OLMUL) + nr += 3; + } if(r->complex == n->complex) - n->complex = r->complex+1; + n->complex = r->complex+nr; else if(r->complex > n->complex) n->complex = r->complex; } - if(n->complex == 0) + if(n->complex == 0){ n->complex++; + if(n->type != T && typev[n->type->etype]) + n->complex++; + } if(com64(n)) return; @@ -621,20 +255,3 @@ xcom(Node *n) } } -int -bcomplex(Node *n, Node *c) -{ - - complex(n); - if(n->type != T) - if(tcompat(n, T, n->type, tnot)) - n->type = T; - if(n->type != T) { - if(c != Z && n->op == OCONST && deadheads(c)) - return 1; - bool64(n); - boolgen(n, 1, Z); - } else - gbranch(OGOTO); - return 0; -} diff --git a/utils/qc/swt.c b/utils/qc/swt.c index 9bf0e58e..0170bad1 100644 --- a/utils/qc/swt.c +++ b/utils/qc/swt.c @@ -1,59 +1,20 @@ #include "gc.h" -int -swcmp(void *a1, void *a2) -{ - C1 *p1, *p2; - - p1 = a1; - p2 = a2; - if(p1->val < p2->val) - return -1; - return p1->val > p2->val; -} +int hasdoubled; +static int doubleflag; void -doswit(Node *n) +swit1(C1 *q, int nc, long def, Node *n) { - Case *c; - C1 *q, *iq; - long def, nc, i; Node tn; - - def = 0; - nc = 0; - for(c = cases; c->link != C; c = c->link) { - if(c->def) { - if(def) - diag(n, "more than one default in switch"); - def = c->label; - continue; - } - nc++; - } - - iq = alloc(nc*sizeof(C1)); - q = iq; - for(c = cases; c->link != C; c = c->link) { - if(c->def) - continue; - q->label = c->label; - q->val = c->val; - q++; - } - qsort(iq, nc, sizeof(C1), swcmp); - if(def == 0) - def = breakpc; - for(i=0; i<nc-1; i++) - if(iq[i].val == iq[i+1].val) - diag(n, "duplicate cases in switch %ld", iq[i].val); + regalloc(&tn, ®node, Z); - swit1(iq, nc, def, n, &tn); + swit2(q, nc, def, n, &tn); regfree(&tn); } void -swit1(C1 *q, int nc, long def, Node *n, Node *tn) +swit2(C1 *q, int nc, long def, Node *n, Node *tn) { C1 *r; int i; @@ -87,20 +48,10 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn) gbranch(OGOTO); p->as = ABEQ; patch(p, r->label); - swit1(q, i, def, n, tn); + swit2(q, i, def, n, tn); patch(sp, pc); - swit1(r+1, nc-i-1, def, n, tn); -} - -void -cas(void) -{ - Case *c; - - c = alloc(sizeof(*c)); - c->link = cases; - cases = c; + swit2(r+1, nc-i-1, def, n, tn); } void @@ -200,33 +151,6 @@ outstring(char *s, long n) return r; } -long -outlstring(ushort *s, long n) -{ - char buf[2]; - int c; - long r; - - if(suppress) - return nstring; - while(nstring & 1) - outstring("", 1); - r = nstring; - while(n > 0) { - c = *s++; - if(align(0, types[TCHAR], Aarg1)) { - buf[0] = c>>8; - buf[1] = c; - } else { - buf[0] = c; - buf[1] = c>>8; - } - outstring(buf, 2); - n -= sizeof(ushort); - } - return r; -} - int mulcon(Node *n, Node *nn) { @@ -317,16 +241,6 @@ loop: } void -nullwarn(Node *l, Node *r) -{ - warn(Z, "result of operation not used"); - if(l != Z) - cgen(l, Z); - if(r != Z) - cgen(r, Z); -} - -void sextern(Sym *s, Node *a, long o, long w) { long e, lw; @@ -454,13 +368,14 @@ zwrite(Biobuf *b, Prog *p, int sf, int st) long l; bf[0] = p->as; - bf[1] = p->reg; + bf[1] = p->as>>8; + bf[2] = p->reg; l = p->lineno; - bf[2] = l; - bf[3] = l>>8; - bf[4] = l>>16; - bf[5] = l>>24; - bp = zaddr(bf+6, &p->from, sf); + bf[3] = l; + bf[4] = l>>8; + bf[5] = l>>16; + bf[6] = l>>24; + bp = zaddr(bf+7, &p->from, sf); bp = zaddr(bp, &p->to, st); Bwrite(b, bf, bp-bf); } @@ -510,6 +425,7 @@ outhist(Biobuf *b) } if(n) { Bputc(b, ANAME); + Bputc(b, ANAME>>8); Bputc(b, D_FILE); Bputc(b, 1); Bputc(b, '<'); @@ -535,27 +451,29 @@ outhist(Biobuf *b) void zname(Biobuf *b, Sym *s, int t) { - char *n, bf[7]; + char *n, bf[8]; ulong sig; n = s->name; if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ sig = sign(s); bf[0] = ASIGNAME; - bf[1] = sig; - bf[2] = sig>>8; - bf[3] = sig>>16; - bf[4] = sig>>24; - bf[5] = t; - bf[6] = s->sym; - Bwrite(b, bf, 7); + bf[1] = ASIGNAME>>8; + bf[2] = sig; + bf[3] = sig>>8; + bf[4] = sig>>16; + bf[5] = sig>>24; + bf[6] = t; + bf[7] = s->sym; + Bwrite(b, bf, 8); s->sig = SIGDONE; } else{ bf[0] = ANAME; - bf[1] = t; /* type */ - bf[2] = s->sym; /* sym */ - Bwrite(b, bf, 3); + bf[1] = ANAME>>8; + bf[2] = t; /* type */ + bf[3] = s->sym; /* sym */ + Bwrite(b, bf, 4); } Bwrite(b, n, strlen(n)+1); } @@ -616,33 +534,32 @@ zaddr(char *bp, Adr *a, int s) return bp; } -void -ieeedtod(Ieee *ieee, double native) +static int +doubled(Type *t) { - double fr, ho, f; - int exp; + Type *v; - if(native < 0) { - ieeedtod(ieee, -native); - ieee->h |= 0x80000000L; - return; - } - if(native == 0) { - ieee->l = 0; - ieee->h = 0; - return; + if(debug['4']) + return 0; + if(t->nbits != 0) + return 0; + switch(t->etype){ + case TDOUBLE: + return 1; + + case TARRAY: + for(v=t; v->etype==TARRAY; v=v->link) + ; + return v->etype == TDOUBLE; + + case TSTRUCT: + case TUNION: + for(v = t->link; v != T; v = v->down) + if(doubled(v)) + return 1; + break; } - fr = frexp(native, &exp); - f = 2097152L; /* shouldnt use fp constants here */ - fr = modf(fr*f, &ho); - ieee->h = ho; - ieee->h &= 0xfffffL; - ieee->h |= (exp+1022L) << 20; - f = 65536L; - fr = modf(fr*f, &ho); - ieee->l = ho; - ieee->l <<= 16; - ieee->l |= (long)(fr*f); + return 0; } long @@ -650,27 +567,33 @@ align(long i, Type *t, int op) { long o; Type *v; - int w; + int w, pc; o = i; w = 1; + pc = 0; switch(op) { default: diag(Z, "unknown align opcode %d", op); break; case Asu2: /* padding at end of a struct */ - w = SZ_LONG; + w = doubled(t)? SZ_DOUBLE: SZ_LONG; if(packflg) w = packflg; break; - case Ael1: /* initial allign of struct element */ + case Ael1: /* initial align of struct element (also automatic) */ for(v=t; v->etype==TARRAY; v=v->link) ; w = ewidth[v->etype]; - if(w <= 0 || w >= SZ_LONG) - w = SZ_LONG; + if(w <= 0 || w >= SZ_LONG){ + if(doubled(v)){ + w = SZ_DOUBLE; + doubleflag = 1; + }else + w = SZ_LONG; + } if(packflg) w = packflg; break; @@ -686,10 +609,15 @@ align(long i, Type *t, int op) } break; - case Aarg1: /* initial allign of parameter */ + case Aarg1: /* initial align of parameter */ w = ewidth[t->etype]; if(w <= 0 || w >= SZ_LONG) { - w = SZ_LONG; + if(doubled(t)){ + w = SZ_DOUBLE; + pc = SZ_LONG; /* alignment must account for pc */ + hasdoubled = 1; + }else + w = SZ_LONG; break; } o += SZ_LONG - w; /* big endian adjustment */ @@ -699,14 +627,20 @@ align(long i, Type *t, int op) case Aarg2: /* width of a parameter */ o += t->width; w = SZ_LONG; + if(doubled(t)){ + pc = SZ_LONG; + hasdoubled = 1; + } break; - case Aaut3: /* total allign of automatic */ + case Aaut3: /* total align of automatic */ + doubleflag = 0; o = align(o, t, Ael1); o = align(o, t, Ael2); + hasdoubled |= doubleflag; break; } - o = round(o, w); + o = round(o+pc, w)-pc; if(debug['A']) print("align %s %ld %T = %ld\n", bnames[op], i, t, o); return o; @@ -715,8 +649,13 @@ align(long i, Type *t, int op) long maxround(long max, long v) { - v += SZ_LONG-1; + int w; + + w = SZ_LONG; + if((debug['8'] || hasdoubled) && !debug['4']) + w = SZ_DOUBLE; + v += w-1; if(v > max) - max = round(v, SZ_LONG); + max = round(v, w); return max; } diff --git a/utils/qc/txt.c b/utils/qc/txt.c index c14386ac..d8102433 100644 --- a/utils/qc/txt.c +++ b/utils/qc/txt.c @@ -2,6 +2,9 @@ static int resvreg[nelem(reg)]; +static void gopcode64(int, Node*, Node*, Node*); +static void gori64(int, Node*, Node*, Node*); +static void gandi64(int, Node*, Node*, Node*); void ginit(void) @@ -30,6 +33,7 @@ ginit(void) zprog.from.type = D_NONE; zprog.from.name = D_NONE; zprog.from.reg = NREG; + zprog.from3 = zprog.from; zprog.to = zprog.from; regnode.op = OREGISTER; @@ -71,14 +75,6 @@ ginit(void) complex(nodrat); nodrat->type = t; - nodret = new(ONAME, Z, Z); - nodret->sym = slookup(".ret"); - nodret->type = types[TIND]; - nodret->etype = TIND; - nodret->class = CPARAM; - nodret = new(OIND, nodret, Z); - complex(nodret); - com64init(); memset(reg, 0, sizeof(reg)); @@ -188,10 +184,10 @@ garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp) if(typesuv[n->type->etype]) { regaalloc(tn2, n); if(n->complex >= FNX) { - sugen(*fnxp, tn2, n->type->width); + cgen(*fnxp, tn2); (*fnxp)++; } else - sugen(n, tn2, n->type->width); + cgen(n, tn2); return; } if(REGARG && curarg == 0 && typechlp[n->type->etype]) { @@ -314,6 +310,27 @@ regalloc(Node *n, Node *tn, Node *o) } diag(tn, "out of float registers"); goto err; + + case TVLONG: + case TUVLONG: + n->op = OREGPAIR; + n->complex = 0; /* already in registers */ + n->addable = 11; + n->type = tn->type; + n->lineno = nearln; + n->left = alloc(sizeof(Node)); + n->right = alloc(sizeof(Node)); + if(o != Z && o->op == OREGPAIR) { + regalloc(n->left, ®node, o->left); + regalloc(n->right, ®node, o->right); + } else { + regalloc(n->left, ®node, Z); + regalloc(n->right, ®node, Z); + } + n->right->type = types[TULONG]; + if(tn->type->etype == TUVLONG) + n->left->type = types[TULONG]; /* TO DO: is this a bad idea? */ + return; } diag(tn, "unknown type in regalloc: %T", tn->type); err: @@ -342,6 +359,11 @@ regfree(Node *n) { int i; + if(n->op == OREGPAIR) { + regfree(n->left); + regfree(n->right); + return; + } i = 0; if(n->op != OREGISTER && n->op != OINDREG) goto err; @@ -353,14 +375,19 @@ regfree(Node *n) reg[i]--; return; err: - diag(n, "error in regfree: %d", i); + diag(n, "error in regfree: %d [%d]", i, reg[i]); + prtree(n, "regfree"); } void regsalloc(Node *n, Node *nn) { - cursafe = align(cursafe, nn->type, Aaut3); + cursafe = align(cursafe+stkoff, nn->type, Aaut3)-stkoff; maxargsafe = maxround(maxargsafe, cursafe+curarg); +// if(nn->type->etype == TDOUBLE || nn->type->etype == TVLONG){ +// extern int hasdoubled; +// fprint(2, "stkoff=%ld cursafe=%ld curarg=%ld %d\n", stkoff, cursafe, curarg, hasdoubled); +// } *n = *nodsafe; n->xoffset = -(stkoff + cursafe); n->type = nn->type; @@ -450,6 +477,7 @@ naddr(Node *n, Adr *a) case OIND: naddr(n->left, a); + a->offset += n->xoffset; /* little hack for reglcgenv */ if(a->type == D_REG) { a->type = D_OREG; break; @@ -526,6 +554,59 @@ naddr(Node *n, Adr *a) } void +gloadhi(Node *f, Node *t, int c) +{ + Type *ot; + + if(f->op == OCONST){ + f = nodconst((long)(f->vconst>>32)); + if(c==1 && sconst(f) || c==2 && uconst(f)){ + if(t->op == OREGISTER) + regfree(t); + *t = *f; + return; + } + } + if(f->op == OREGPAIR) { + gmove(f->left, t); + return; + } + ot = f->type; + f->type = types[TLONG]; + gmove(f, t); + f->type = ot; +} + +void +gloadlo(Node *f, Node *t, int c) +{ + Type *ot; + + if(f->op == OCONST){ + f = nodconst((long)f->vconst); + if(c && uconst(f)){ + if(t->op == OREGISTER) + regfree(t); + *t = *f; + return; + } + } + if(f->op == OREGPAIR) { + gmove(f->right, t); + return; + } + ot = f->type; + f->type = types[TLONG]; + f->xoffset += SZ_LONG; + if(0){ + prtree(f, "gloadlo f"); prtree(t, "gloadlo t"); + } + gmove(f, t); + f->xoffset -= SZ_LONG; + f->type = ot; +} + +void fop(int as, int f1, int f2, Node *t) { Node nod1, nod2, nod3; @@ -602,6 +683,17 @@ gmove(Node *f, Node *t) return; } } + if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) { + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gmove(nod32const(f->vconst>>32), t->left); + else + gmove(nod32const(f->vconst), t->left); + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gmove(nod32const(f->vconst), t->right); + else + gmove(nod32const(f->vconst>>32), t->right); + return; + } /* * a load -- * put it into a register then @@ -631,8 +723,25 @@ gmove(Node *f, Node *t) a = AMOVHZ; break; } - regalloc(&nod, f, t); - gins(a, f, &nod); + if(typev[ft]) { + if(typev[tt]) { + regalloc(&nod, f, t); + /* low order first, because its value will be used first */ + f->xoffset += SZ_LONG; + gins(AMOVW, f, nod.right); + f->xoffset -= SZ_LONG; + gins(AMOVW, f, nod.left); + } else { + /* assumed not float or double */ + regalloc(&nod, ®node, t); + f->xoffset += SZ_LONG; + gins(AMOVW, f, &nod); + f->xoffset -= SZ_LONG; + } + } else { + regalloc(&nod, f, t); + gins(a, f, &nod); + } gmove(&nod, t); regfree(&nod); return; @@ -669,6 +778,11 @@ gmove(Node *f, Node *t) } if(R0ISZERO && !typefd[ft] && vconst(f) == 0) { gins(a, f, t); + if(typev[tt]) { + t->xoffset += SZ_LONG; + gins(a, f, t); + t->xoffset -= SZ_LONG; + } return; } if(ft == tt) @@ -676,7 +790,13 @@ gmove(Node *f, Node *t) else regalloc(&nod, t, Z); gmove(f, &nod); - gins(a, &nod, t); + if(typev[tt]) { + t->xoffset += SZ_LONG; + gins(a, nod.right, t); + t->xoffset -= SZ_LONG; + gins(a, nod.left, t); + } else + gins(a, &nod, t); regfree(&nod); return; } @@ -710,7 +830,7 @@ gmove(Node *f, Node *t) case TUCHAR: /* BUG: not right for unsigned long */ regalloc(&nod, f, Z); /* should be type float */ - regsalloc(&fxrat, f); + regsalloc(&fxrat, &fconstnode); gins(AFCTIWZ, f, &nod); gins(AFMOVD, &nod, &fxrat); regfree(&nod); @@ -817,7 +937,7 @@ gmove(Node *f, Node *t) */ regalloc(&fxc0, f, Z); regalloc(&fxc2, f, Z); - regsalloc(&fxrat, t); /* should be type float */ + regsalloc(&fxrat, &fconstnode); /* should be type float */ gins(AMOVW, nodconst(0x43300000L), &fxc0); gins(AMOVW, f, &fxc2); gins(AMOVW, &fxc0, &fxrat); @@ -876,13 +996,28 @@ gmove(Node *f, Node *t) break; } break; + case TVLONG: + case TUVLONG: + switch(tt) { + case TVLONG: + case TUVLONG: + a = AMOVW; + break; + } + break; } if(a == AGOK) diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type); if(a == AMOVW || a == AFMOVS || a == AFMOVD) if(samaddr(f, t)) return; - gins(a, f, t); + if(typev[ft]) { + if(f->op != OREGPAIR || t->op != OREGPAIR) + diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op); + gins(a, f->left, t->left); + gins(a, f->right, t->right); + } else + gins(a, f, t); } void @@ -900,21 +1035,75 @@ gins(int a, Node *f, Node *t) } void -gopcode(int o, Node *f1, Node *f2, Node *t) +gins3(int a, Node *f1, Node *f2, Node *t) { - int a, et; Adr ta; - int uns; - uns = 0; + nextpc(); + p->as = a; + if(f1 != Z) + naddr(f1, &p->from); + if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) { + ta = zprog.from; /* TO DO */ + naddr(f2, &ta); + p->reg = ta.reg; + if(ta.type == D_CONST && ta.offset == 0) { + if(R0ISZERO) + p->reg = REGZERO; + else + diag(Z, "REGZERO in gins3 %A", a); + }else if(ta.type == D_CONST) + p->from3 = ta; + } + if(t != Z) + naddr(t, &p->to); + if(debug['g']) + print("%P\n", p); +} + +void +gins4(int a, Node *f1, Node *f2, Node *f3, Node *t) +{ + Adr ta; + + nextpc(); + p->as = a; + naddr(f1, &p->from); + if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0)) + diag(f2, "invalid gins4"); + naddr(f2, &ta); + p->reg = ta.reg; + if(ta.type == D_CONST && ta.offset == 0) + p->reg = REGZERO; + naddr(f3, &p->from3); + naddr(t, &p->to); + if(debug['g']) + print("%P\n", p); +} + +void +gopcode(int o, Node *f1, Node *f2, Node *t) +{ + int a, et, uns; + + if(o == OAS) { + gmove(f1, t); + return; + } et = TLONG; - if(f1 != Z && f1->type != T) - et = f1->type->etype; + if(f1 != Z && f1->type != T) { + if(f1->op == OCONST && t != Z && t->type != T) + et = t->type->etype; + else + et = f1->type->etype; + } + if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) { + gopcode64(o, f1, f2, t); + return; + } + uns = 0; a = AGOK; switch(o) { - case OAS: - gmove(f1, t); - return; case OASADD: case OADD: @@ -965,7 +1154,7 @@ gopcode(int o, Node *f1, Node *f2, Node *t) case OASASHL: case OASHL: - a = ASLW; /* BUG? */ + a = ASLW; break; case OFUNC: @@ -1027,10 +1216,14 @@ gopcode(int o, Node *f1, Node *f2, Node *t) case OEQ: a = ABEQ; + if(t->op == OCONST && t->vconst >= (1<<15)) + goto cmpu; goto cmp; case ONE: a = ABNE; + if(t->op == OCONST && t->vconst >= (1<<15)) + goto cmpu; goto cmp; case OLT: @@ -1090,24 +1283,258 @@ gopcode(int o, Node *f1, Node *f2, Node *t) } if(a == AGOK) diag(Z, "bad in gopcode %O", o); - nextpc(); - p->as = a; - if(f1 != Z) - naddr(f1, &p->from); - if(f2 != Z) { - naddr(f2, &ta); - p->reg = ta.reg; - if(ta.type == D_CONST && ta.offset == 0) { - if(R0ISZERO) - p->reg = REGZERO; + gins3(a, f1, f2, t); +} + +static void +gopcode64(int o, Node *f1, Node *f2, Node *t) +{ + int a1, a2; + Node nod, nod1, nod2, sh; + ulong m; + Prog *p1; + + if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) { + diag(Z, "bad f2/dest in gopcode64 %O", o); + return; + } + if(f1->op != OCONST && + (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) { + diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o); + return; + } + /* a1 for low-order, a2 for high-order */ + a1 = AGOK; + a2 = AGOK; + switch(o) { + case OASADD: + case OADD: + if(f1->op == OCONST && sconst(f1)) { + if(f2 == Z) + f2 = t; + gins3(AADDC, f1, f2->right, t->right); + if((f1->vconst>>32) == 0) + gins(AADDZE, f2->left, t->left); + else if((f1->vconst>>32) == -1) + gins(AADDME, f2->left, t->left); else - diag(Z, "REGZERO in gopcode %O", o); + diag(t, "odd vlong ADD: %lld", f1->vconst); + return; + } + a1 = AADDC; + a2 = AADDE; + break; + + case OASSUB: + case OSUB: + a1 = ASUBC; + a2 = ASUBE; + break; + + case OASOR: + case OOR: + if(f1->op == OCONST) { + gori64(AOR, f1, f2, t); + return; + } + a1 = a2 = AOR; + break; + + case OASAND: + case OAND: + if(f1->op == OCONST) { + gandi64(AANDCC, f1, f2, t); + return; + } + a1 = a2 = AAND; + break; + + case OASXOR: + case OXOR: + if(f1->op == OCONST) { + gori64(AXOR, f1, f2, t); + return; + } + a1 = a2 = AXOR; + break; + + case OASLSHR: + case OLSHR: + if(f2 == Z) + f2 = t; + if(f1->op == OCONST) { + if(f1->vconst >= 32) { + if(f1->vconst == 32) + gmove(f2->left, t->right); + else if(f1->vconst < 64) + gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right); + else + gmove(nodconst(0), t->right); + gmove(nodconst(0), t->left); + return; + } + if(f1->vconst <= 0) { + if(f2 != t) + gmove(f2, t); + return; + } + sh = *nodconst(32 - f1->vconst); + m = 0xFFFFFFFFUL >> f1->vconst; + gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right); + gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right); + gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left); + return; + } + regalloc(&nod, ®node, Z); + gins3(ASUBC, f1, nodconst(32), &nod); + gins3(ASRW, f1, f2->right, t->right); + regalloc(&nod1, ®node, Z); + gins3(ASLW, &nod, f2->left, &nod1); + gins(AOR, &nod1, t->right); + gins3(AADD, nodconst(-32), f1, &nod); + gins3(ASRW, &nod, f2->left, &nod1); + gins(AOR, &nod1, t->right); + gins3(ASRW, f1, f2->left, t->left); + regfree(&nod); + regfree(&nod1); + return; + + case OASASHR: + case OASHR: + if(f2 == Z) + f2 = t; + if(f1->op == OCONST) { + if(f1->vconst >= 32) { + if(f1->vconst == 32) + gmove(f2->left, t->right); + else if(f1->vconst < 64) + gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right); + gins3(ASRAW, nodconst(31), f2->left, t->left); + if(f1->vconst >= 64) { + gmove(t->left, t->right); + return; + } + return; + } + if(f1->vconst <= 0) { + if(f2 != t) + gmove(f2, t); + return; + } + sh = *nodconst(32 - f1->vconst); + m = 0xFFFFFFFFUL >> f1->vconst; + gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right); + gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right); + gins3(ASRAW, &sh, f2->left, t->left); + return; + } + regalloc(&nod, ®node, Z); + gins3(ASUBC, f1, nodconst(32), &nod); + gins3(ASRW, f1, f2->right, t->right); + regalloc(&nod1, ®node, Z); + gins3(ASLW, &nod, f2->left, &nod1); + gins(AOR, &nod1, t->right); + gins3(AADDCCC, nodconst(-32), f1, &nod); + gins3(ASRAW, &nod, f2->left, &nod1); + gins(ABLE, Z, Z); + p1 = p; + gins(AMOVW, &nod1, t->right); + patch(p1, pc); + gins3(ASRAW, f1, f2->left, t->left); + regfree(&nod); + regfree(&nod1); + return; + + case OASASHL: + case OASHL: + if(f2 == Z) + f2 = t; + if(f1->op == OCONST) { + if(f1->vconst >= 32) { + if(f1->vconst == 32) + gmove(f2->right, t->left); + else if(f1->vconst >= 64) + gmove(nodconst(0), t->left); + else + gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left); + gmove(nodconst(0), t->right); + return; + } + if(f1->vconst <= 0) { + if(f2 != t) + gmove(f2, t); + return; + } + m = 0xFFFFFFFFUL << f1->vconst; + gins4(ARLWNM, f1, f2->left, nodconst(m), t->left); + gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left); + gins4(ARLWNM, f1, f2->right, nodconst(m), t->right); + return; + } + regalloc(&nod, ®node, Z); + gins3(ASUBC, f1, nodconst(32), &nod); + gins3(ASLW, f1, f2->left, t->left); + regalloc(&nod1, ®node, Z); + gins3(ASRW, &nod, f2->right, &nod1); + gins(AOR, &nod1, t->left); + gins3(AADD, nodconst(-32), f1, &nod); + gins3(ASLW, &nod, f2->right, &nod1); + gins(AOR, &nod1, t->left); + gins3(ASLW, f1, f2->right, t->right); + regfree(&nod); + regfree(&nod1); + return; + + case OASLMUL: + case OLMUL: + case OASMUL: + case OMUL: + if(f2 == Z) + f2 = t; + regalloc(&nod, ®node, Z); + gins3(AMULLW, f1->right, f2->right, &nod); /* lo(f2.low*f1.low) */ + a1 = AMULHW; + if(o == OLMUL || o == OASLMUL) + a1 = AMULHWU; + regalloc(&nod1, ®node, Z); + gins3(a1, f1->right, f2->right, &nod1); /* hi(f2.low*f1.low) */ + regalloc(&nod2, ®node, Z); + gins3(AMULLW, f2->right, f1->left, &nod2); /* lo(f2.low*f1.high) */ + gins(AADD, &nod2, &nod1); + gins3(AMULLW, f1->right, f2->left, &nod2); /* hi(f2.high*f1.low) */ + gins(AADD, &nod2, &nod1); + regfree(&nod2); + gmove(&nod, t->right); + gmove(&nod1, t->left); + regfree(&nod); + regfree(&nod1); + return; + + case OCOM: + a1 = a2 = ANOR; + break; + + case ONEG: + gins3(ASUBC, t->right, nodconst(0), t->right); + gins(ASUBZE, t->left, t->left); + return; + } + if(a1 == AGOK || a2 == AGOK) + diag(Z, "bad in gopcode64 %O", o); + if(f1->op == OCONST) { + if(f2 != Z & f2 != t) + diag(Z, "bad const in gopcode64 %O", o); + gins(a1, nod32const(f1->vconst), t->right); + gins(a2, nod32const(f1->vconst>>32), t->left); + } else { + if(f2 != Z && f2 != t) { + gins3(a1, f1->right, f2->right, t->right); + gins3(a2, f1->left, f2->left, t->left); + } else { + gins(a1, f1->right, t->right); + gins(a2, f1->left, t->left); } } - if(t != Z) - naddr(t, &p->to); - if(debug['g']) - print("%P\n", p); } samaddr(Node *f, Node *t) @@ -1121,10 +1548,51 @@ samaddr(Node *f, Node *t) if(f->reg != t->reg) break; return 1; + + case OREGPAIR: + return samaddr(f->left, t->left) && samaddr(f->right, t->right); } return 0; } +static void +gori64(int a, Node *f1, Node *f2, Node *t) +{ + ulong lo, hi; + + if(f2 == Z) + f2 = t; + lo = f1->vconst & MASK(32); + hi = (f1->vconst >> 32) & MASK(32); + if(lo & 0xFFFF) + gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right); + if((lo >> 16) != 0) + gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right); + if(hi & 0xFFFF) + gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left); + if((hi >> 16) != 0) + gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left); +} + +static void +gandi64(int a, Node *f1, Node *f2, Node *t) +{ + ulong lo, hi; + + if(f2 == Z) + f2 = t; + lo = f1->vconst & MASK(32); + hi = (f1->vconst >> 32) & MASK(32); + if(lo == 0) + gins(AMOVW, nodconst(0), t->right); + else + gins3(a, nodconst(lo), f2->right, t->right); + if(hi == 0) + gins(AMOVW, nodconst(0), t->left); + else + gins3(a, nodconst(hi), f2->left, t->left); +} + void gbranch(int o) { |
