summaryrefslogtreecommitdiff
path: root/src/cmd/6c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6c')
-rw-r--r--src/cmd/6c/cgen.c48
-rw-r--r--src/cmd/6c/gc.h3
-rw-r--r--src/cmd/6c/swt.c19
3 files changed, 64 insertions, 6 deletions
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
index 7f717dcbb..71822586c 100644
--- a/src/cmd/6c/cgen.c
+++ b/src/cmd/6c/cgen.c
@@ -1237,11 +1237,12 @@ void
boolgen(Node *n, int true, Node *nn)
{
int o;
- Prog *p1, *p2;
+ Prog *p1, *p2, *p3;
Node *l, *r, nod, nod1;
int32 curs;
if(debug['g']) {
+ print("boolgen %d\n", true);
prtree(nn, "boolgen lhs");
prtree(n, "boolgen");
}
@@ -1353,6 +1354,15 @@ boolgen(Node *n, int true, Node *nn)
case OLO:
case OLS:
o = n->op;
+ if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
+ // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
+ // Jump around instead.
+ boolgen(n, 0, Z);
+ p1 = p;
+ gbranch(OGOTO);
+ patch(p1, pc);
+ goto com;
+ }
if(true)
o = comrel[relindex(o)];
if(l->complex >= FNX && r->complex >= FNX) {
@@ -1367,6 +1377,10 @@ boolgen(Node *n, int true, Node *nn)
break;
}
if(immconst(l)) {
+ // NOTE: Reversing the comparison here is wrong
+ // for floating point ordering comparisons involving NaN,
+ // but we don't have any of those yet so we don't
+ // bother worrying about it.
o = invrel[relindex(o)];
/* bad, 13 is address of external that becomes constant */
if(r->addable < INDEXED || r->addable == 13) {
@@ -1388,10 +1402,11 @@ boolgen(Node *n, int true, Node *nn)
cgen(r, &nod1);
gopcode(o, l->type, &nod, &nod1);
regfree(&nod1);
- } else
+ } else {
gopcode(o, l->type, &nod, r);
+ }
regfree(&nod);
- goto com;
+ goto fixfloat;
}
regalloc(&nod, r, nn);
cgen(r, &nod);
@@ -1406,6 +1421,33 @@ boolgen(Node *n, int true, Node *nn)
} else
gopcode(o, l->type, l, &nod);
regfree(&nod);
+ fixfloat:
+ if(typefd[l->type->etype]) {
+ switch(o) {
+ case OEQ:
+ // Already emitted AJEQ; want AJEQ and AJPC.
+ p1 = p;
+ gbranch(OGOTO);
+ p2 = p;
+ patch(p1, pc);
+ gins(AJPC, Z, Z);
+ patch(p2, pc);
+ break;
+
+ case ONE:
+ // Already emitted AJNE; want AJNE or AJPS.
+ p1 = p;
+ gins(AJPS, Z, Z);
+ p2 = p;
+ gbranch(OGOTO);
+ p3 = p;
+ patch(p1, pc);
+ patch(p2, pc);
+ gbranch(OGOTO);
+ patch(p3, pc);
+ break;
+ }
+ }
com:
if(nn != Z) {
diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h
index 0c23b115c..b0081abb5 100644
--- a/src/cmd/6c/gc.h
+++ b/src/cmd/6c/gc.h
@@ -299,7 +299,8 @@ void gpseudo(int, Sym*, Node*);
int swcmp(const void*, const void*);
void doswit(Node*);
void swit1(C1*, int, int32, Node*);
-void cas(void);
+void swit2(C1*, int, int32, Node*);
+void newcase(void);
void bitload(Node*, Node*, Node*, Node*, Node*);
void bitstore(Node*, Node*, Node*, Node*, Node*);
int32 outstring(char*, int32);
diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c
index 3de86306d..f16d0f78a 100644
--- a/src/cmd/6c/swt.c
+++ b/src/cmd/6c/swt.c
@@ -33,6 +33,21 @@
void
swit1(C1 *q, int nc, int32 def, Node *n)
{
+ Node nreg;
+
+ regalloc(&nreg, n, Z);
+ if(typev[n->type->etype])
+ nreg.type = types[TVLONG];
+ else
+ nreg.type = types[TLONG];
+ cgen(n, &nreg);
+ swit2(q, nc, def, &nreg);
+ regfree(&nreg);
+}
+
+void
+swit2(C1 *q, int nc, int32 def, Node *n)
+{
C1 *r;
int i;
Prog *sp;
@@ -58,12 +73,12 @@ swit1(C1 *q, int nc, int32 def, Node *n)
gbranch(OGOTO);
p->as = AJEQ;
patch(p, r->label);
- swit1(q, i, def, n);
+ swit2(q, i, def, n);
if(debug['W'])
print("case < %.8llux\n", r->val);
patch(sp, pc);
- swit1(r+1, nc-i-1, def, n);
+ swit2(r+1, nc-i-1, def, n);
}
void