diff --git a/sys/src/cmd/qc/cgen.c b/sys/src/cmd/qc/cgen.c index d26704deb..018d80bf3 100644 --- a/sys/src/cmd/qc/cgen.c +++ b/sys/src/cmd/qc/cgen.c @@ -4,6 +4,7 @@ static void cmpv(Node*, int, Node*); static void testv(Node*, int); static void cgen64(Node*, Node*); static int isvconstable(int, vlong); +static void genasop(int, Node*, Node*, Node*); void cgen(Node *n, Node *nn) @@ -255,6 +256,8 @@ cgen(Node *n, Node *nn) regfree(&nod2); break; } + genasop(o, l, r, nn); + break; case OASLMUL: case OASLDIV: @@ -264,31 +267,7 @@ cgen(Node *n, Node *nn) case OASMOD: if(l->op == OBIT) goto asbitop; - if(l->complex >= r->complex) { - if(l->addable < INDEXED) - reglcgen(&nod2, l, Z); - else - nod2 = *l; - regalloc(&nod, r, Z); - cgen(r, &nod); - } else { - regalloc(&nod, r, Z); - cgen(r, &nod); - if(l->addable < INDEXED) - reglcgen(&nod2, l, Z); - else - nod2 = *l; - } - regalloc(&nod1, n, nn); - gopcode(OAS, &nod2, Z, &nod1); - 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) - regfree(&nod2); + genasop(o, l, r, nn); break; asbitop: @@ -561,6 +540,43 @@ cgen(Node *n, Node *nn) cursafe = curs; } +static void +genasop(int o, Node *l, Node *r, Node *nn) +{ + Node nod, nod1, nod2; + int hardleft; + + hardleft = l->addable < INDEXED || l->complex >= FNX; + if(l->complex >= r->complex) { + if(hardleft) + reglcgen(&nod2, l, Z); + else + nod2 = *l; + regalloc(&nod1, r, Z); + cgen(r, &nod1); + } else { + regalloc(&nod1, r, Z); + cgen(r, &nod1); + if(hardleft) + reglcgen(&nod2, l, Z); + else + nod2 = *l; + } + if(nod1.type == nod2.type || !typefd[nod1.type->etype]) + regalloc(&nod, &nod2, nn); + else + regalloc(&nod, &nod1, Z); + gmove(&nod2, &nod); + gopcode(o, &nod1, Z, &nod); + gmove(&nod, &nod2); + if(nn != Z) + gmove(&nod2, nn); + regfree(&nod); + regfree(&nod1); + if(hardleft) + regfree(&nod2); +} + void reglcgen(Node *t, Node *n, Node *nn) { diff --git a/sys/src/cmd/qc/machcap.c b/sys/src/cmd/qc/machcap.c index e9f9a9881..e3e089fc7 100644 --- a/sys/src/cmd/qc/machcap.c +++ b/sys/src/cmd/qc/machcap.c @@ -18,10 +18,12 @@ machcap(Node *n) case OMUL: case OLMUL: - case OASMUL: case OASLMUL: return 1; + case OASMUL: + return !mixedasop(n->type, n->right->type); + case OLSHR: case OASHR: case OASHL: @@ -58,6 +60,8 @@ machcap(Node *n) case OASADD: case OASSUB: + return !mixedasop(n->type, n->right->type); + case OASAND: case OASOR: case OASXOR: diff --git a/sys/src/cmd/qc/swt.c b/sys/src/cmd/qc/swt.c index f0edacc87..90b6fda67 100644 --- a/sys/src/cmd/qc/swt.c +++ b/sys/src/cmd/qc/swt.c @@ -657,8 +657,8 @@ maxround(long max, long v) w = SZ_LONG; if((debug['8'] || hasdoubled) && !debug['4']) w = SZ_DOUBLE; - v += w-1; + v = round(v, w); if(v > max) - max = round(v, w); + return v; return max; } diff --git a/sys/src/cmd/qc/txt.c b/sys/src/cmd/qc/txt.c index 601c047b6..4f5e9c082 100644 --- a/sys/src/cmd/qc/txt.c +++ b/sys/src/cmd/qc/txt.c @@ -622,12 +622,86 @@ fop(int as, int f1, int f2, Node *t) regfree(&nod3); } +static void +floattofix(Node *f, Node *t) +{ + Node nod, fxrat; + + regalloc(&nod, f, Z); + regsalloc(&fxrat, &fconstnode); + gins(AFCTIWZ, f, &nod); + gins(AFMOVD, &nod, &fxrat); + regfree(&nod); + fxrat.type = nodrat->type; + fxrat.etype = nodrat->etype; + fxrat.xoffset += 4; + gins(AMOVW, &fxrat, t); + gmove(t, t); +} + +static void +fixtofloat(Node *f, Node *t) +{ + int a, ft, tt; + Prog *p1; + Node nod, fxc0, fxc1, fxc2, fxrat; + + ft = f->type->etype; + tt = t->type->etype; + + /* + * rat[0] = 0x43300000; rat[1] = f^0x80000000; + * t = *(double*)rat - FREGCVI; + * is-unsigned(t) => if(t<0) t += 2^32; + * could be streamlined for int-to-float + */ + regalloc(&fxc0, f, Z); + regalloc(&fxc2, f, Z); + regsalloc(&fxrat, &fconstnode); /* should be type float */ + gins(AMOVW, nodconst(0x43300000L), &fxc0); + gins(AMOVW, f, &fxc2); + gins(AMOVW, &fxc0, &fxrat); + gins(AXOR, nodconst(0x80000000L), &fxc2); + fxc1 = fxrat; + fxc1.type = nodrat->type; + fxc1.etype = nodrat->etype; + fxc1.xoffset += SZ_LONG; + gins(AMOVW, &fxc2, &fxc1); + regfree(&fxc2); + regfree(&fxc0); + regalloc(&nod, t, t); /* should be type float */ + gins(AFMOVD, &fxrat, &nod); + nodreg(&fxc1, t, NREG+FREGCVI); + gins(AFSUB, &fxc1, &nod); + a = AFMOVD; + if(tt == TFLOAT) + a = AFRSP; + gins(a, &nod, t); + regfree(&nod); + if(ft == TULONG) { + regalloc(&nod, t, Z); + gins(AFCMPU, t, Z); + p->to.type = D_FREG; + p->to.reg = FREGZERO; + gins(ABGE, Z, Z); + p1 = p; + if(tt == TFLOAT) { + gins(AFMOVS, nodfconst(4294967296.), &nod); + gins(AFADDS, &nod, t); + } else { + gins(AFMOVD, nodfconst(4294967296.), &nod); + gins(AFADD, &nod, t); + } + patch(p1, pc); + regfree(&nod); + } +} + void gmove(Node *f, Node *t) { int ft, tt, a; - Node nod, fxc0, fxc1, fxc2, fxrat; - Prog *p1; + Node nod; double d; ft = f->type->etype; @@ -727,7 +801,7 @@ gmove(Node *f, Node *t) break; } if(typev[ft]) { - if(typev[tt]) { + if(typev[tt] || typefd[tt]) { regalloc(&nod, f, t); /* low order first, because its value will be used first */ f->xoffset += SZ_LONG; @@ -832,16 +906,11 @@ gmove(Node *f, Node *t) case TCHAR: case TUCHAR: /* BUG: not right for unsigned long */ - regalloc(&nod, f, Z); /* should be type float */ - regsalloc(&fxrat, &fconstnode); - gins(AFCTIWZ, f, &nod); - gins(AFMOVD, &nod, &fxrat); - regfree(&nod); - fxrat.type = nodrat->type; - fxrat.etype = nodrat->etype; - fxrat.xoffset += 4; - gins(AMOVW, &fxrat, t); - gmove(t, t); + floattofix(f, t); + return; + case TVLONG: + case TUVLONG: + diag(f, "unimplemented double->vlong"); return; } break; @@ -853,7 +922,8 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - goto fxtofl; + fixtofloat(f, t); + return; case TINT: case TUINT: case TLONG: @@ -871,7 +941,8 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - goto fxtofl; + fixtofloat(f, t); + return; case TINT: case TUINT: case TLONG: @@ -891,7 +962,8 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - goto fxtofl; + fixtofloat(f, t); + return; case TINT: case TUINT: case TLONG: @@ -911,7 +983,8 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - goto fxtofl; + fixtofloat(f, t); + return; case TINT: case TUINT: case TLONG: @@ -931,58 +1004,7 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - fxtofl: - /* - * rat[0] = 0x43300000; rat[1] = f^0x80000000; - * t = *(double*)rat - FREGCVI; - * is-unsigned(t) => if(t<0) t += 2^32; - * could be streamlined for int-to-float - */ - regalloc(&fxc0, f, Z); - regalloc(&fxc2, f, Z); - regsalloc(&fxrat, &fconstnode); /* should be type float */ - gins(AMOVW, nodconst(0x43300000L), &fxc0); - gins(AMOVW, f, &fxc2); - gins(AMOVW, &fxc0, &fxrat); - gins(AXOR, nodconst(0x80000000L), &fxc2); - fxc1 = fxrat; - fxc1.type = nodrat->type; - fxc1.etype = nodrat->etype; - fxc1.xoffset += SZ_LONG; - gins(AMOVW, &fxc2, &fxc1); - regfree(&fxc2); - regfree(&fxc0); - regalloc(&nod, t, t); /* should be type float */ - gins(AFMOVD, &fxrat, &nod); - nodreg(&fxc1, t, NREG+FREGCVI); - gins(AFSUB, &fxc1, &nod); - a = AFMOVD; - if(tt == TFLOAT) - a = AFRSP; - gins(a, &nod, t); - regfree(&nod); - if(ft == TULONG) { - regalloc(&nod, t, Z); - if(tt == TFLOAT) { - gins(AFCMPU, t, Z); - p->to.type = D_FREG; - p->to.reg = FREGZERO; - gins(ABGE, Z, Z); - p1 = p; - gins(AFMOVS, nodfconst(4294967296.), &nod); - gins(AFADDS, &nod, t); - } else { - gins(AFCMPU, t, Z); - p->to.type = D_FREG; - p->to.reg = FREGZERO; - gins(ABGE, Z, Z); - p1 = p; - gins(AFMOVD, nodfconst(4294967296.), &nod); - gins(AFADD, &nod, t); - } - patch(p1, pc); - regfree(&nod); - } + fixtofloat(f, t); return; case TINT: case TUINT: @@ -1522,7 +1544,7 @@ gopcode64(int o, Node *f1, Node *f2, Node *t) if(a1 == AGOK || a2 == AGOK) diag(Z, "bad in gopcode64 %O", o); if(f1->op == OCONST) { - if(f2 != Z && f2 != t) + 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);