ref: 7c7acbef314c6998354219f24cfee3283cb45ec1
parent: 4a916ba86e700d5e99311b45a81dc7be8a50b843
author: cinap_lenrek <[email protected]>
date: Wed Oct 7 05:40:48 EDT 2015
qc: import changes from charles forsyth
--- a/sys/src/cmd/qc/cgen.c
+++ b/sys/src/cmd/qc/cgen.c
@@ -4,6 +4,7 @@
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 @@
regfree(&nod2);
break;
}
+ genasop(o, l, r, nn);
+ break;
case OASLMUL:
case OASLDIV:
@@ -264,31 +267,7 @@
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:
@@ -559,6 +538,43 @@
break;
}
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
--- a/sys/src/cmd/qc/machcap.c
+++ b/sys/src/cmd/qc/machcap.c
@@ -18,10 +18,12 @@
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 @@
case OASADD:
case OASSUB:
+ return !mixedasop(n->type, n->right->type);
+
case OASAND:
case OASOR:
case OASXOR:
--- a/sys/src/cmd/qc/swt.c
+++ b/sys/src/cmd/qc/swt.c
@@ -657,8 +657,8 @@
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;
}
--- a/sys/src/cmd/qc/txt.c
+++ b/sys/src/cmd/qc/txt.c
@@ -622,12 +622,86 @@
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 @@
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,17 +906,12 @@
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;
case TINT:
@@ -853,7 +922,8 @@
switch(tt) {
case TDOUBLE:
case TFLOAT:
- goto fxtofl;
+ fixtofloat(f, t);
+ return;
case TINT:
case TUINT:
case TLONG:
@@ -871,7 +941,8 @@
switch(tt) {
case TDOUBLE:
case TFLOAT:
- goto fxtofl;
+ fixtofloat(f, t);
+ return;
case TINT:
case TUINT:
case TLONG:
@@ -891,7 +962,8 @@
switch(tt) {
case TDOUBLE:
case TFLOAT:
- goto fxtofl;
+ fixtofloat(f, t);
+ return;
case TINT:
case TUINT:
case TLONG:
@@ -911,7 +983,8 @@
switch(tt) {
case TDOUBLE:
case TFLOAT:
- goto fxtofl;
+ fixtofloat(f, t);
+ return;
case TINT:
case TUINT:
case TLONG:
@@ -931,58 +1004,7 @@
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 @@
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);