shithub: mc

Download patch

ref: 064b5d2b2f9c54fcbd0e928d75253032e51f7e6f
parent: 1750fba1a4fc55641cfd5a9ced3a33f012ff221f
author: Ori Bernstein <[email protected]>
date: Mon Jan 20 11:47:23 EST 2014

Correctly handle signed/unsigned comparisons.

--- a/6/insns.def
+++ b/6/insns.def
@@ -60,6 +60,10 @@
 Insn(Isetle,    "\tsetle %v\n",                 Use(),  Def(.l={1}))
 Insn(Isetg,     "\tsetg %v\n",                  Use(),  Def(.l={1}))
 Insn(Isetge,    "\tsetge %v\n",                 Use(),  Def(.l={1}))
+Insn(Isetb,     "\tsetb  %v\n",                 Use(),  Def(.l={1}))
+Insn(Isetbe,    "\tsetbe %v\n",                 Use(),  Def(.l={1}))
+Insn(Iseta,     "\tseta %v\n",                  Use(),  Def(.l={1}))
+Insn(Isetae,    "\tsetae %v\n",                 Use(),  Def(.l={1}))
 
 /* fp specific instructions */
 Insn(Imovs,      "\tmovs%1t %x,%x\n",           Use(.l={1}),                    Def(.l={2}))
@@ -82,6 +86,10 @@
 Insn(Ijle,      "\tjle %v\n",                   Use(.l={1}), Def())
 Insn(Ijg,       "\tjg %v\n",                    Use(.l={1}), Def())
 Insn(Ijge,      "\tjge %v\n",                   Use(.l={1}), Def())
+Insn(Ijb,       "\tjb %v\n",                    Use(.l={1}), Def())
+Insn(Ijbe,      "\tjbe %v\n",                   Use(.l={1}), Def())
+Insn(Ija,       "\tja %v\n",                    Use(.l={1}), Def())
+Insn(Ijae,      "\tjae %v\n",                   Use(.l={1}), Def())
 Insn(Iret,      "\tret\n",                      Use(), Def())
 
 /* not really an insn... */
--- a/6/isel.c
+++ b/6/isel.c
@@ -40,18 +40,32 @@
 /* used to decide which operator is appropriate
  * for implementing various conditional operators */
 struct {
-    AsmOp itest;
-    AsmOp fptest;
+    AsmOp test;
     AsmOp jmp;
     AsmOp getflag;
 } reloptab[Numops] = {
-    [Olnot] = {Itest, 0, Ijz, Isetz}, /* lnot invalid for floats */
-    [Oeq] = {Icmp, Icomis, Ijz,  Isetz},
-    [One] = {Icmp, Icomis, Ijnz, Isetnz},
-    [Ogt] = {Icmp, Icomis, Ijg,  Isetg},
-    [Oge] = {Icmp, Icomis, Ijge, Isetge},
-    [Olt] = {Icmp, Icomis, Ijl,  Isetl},
-    [Ole] = {Icmp, Icomis, Ijle, Isetle}
+    [Olnot] = {Itest, Ijz, Isetz}, /* lnot invalid for floats */
+    /* signed int */
+    [Oeq] = {Icmp, Ijz,  Isetz},
+    [One] = {Icmp, Ijnz, Isetnz},
+    [Ogt] = {Icmp, Ijg,  Isetg},
+    [Oge] = {Icmp, Ijge, Isetge},
+    [Olt] = {Icmp, Ijl,  Isetl},
+    [Ole] = {Icmp, Ijle, Isetle},
+    /* unsigned int */
+    [Oueq] = {Icmp, Ijz,  Isetz},
+    [Oune] = {Icmp, Ijnz, Isetnz},
+    [Ougt] = {Icmp, Ija,  Iseta},
+    [Ouge] = {Icmp, Ijae, Isetae},
+    [Oult] = {Icmp, Ijb,  Isetb},
+    [Oule] = {Icmp, Ijbe, Isetbe},
+    /* float */
+    [Ofeq] = {Icomis, Ijz,  Isetz},
+    [Ofne] = {Icomis, Ijnz, Isetnz},
+    [Ofgt] = {Icomis, Ija,  Iseta},
+    [Ofge] = {Icomis, Ijae, Isetae},
+    [Oflt] = {Icomis, Ijb,  Isetb},
+    [Ofle] = {Icomis, Ijbe, Isetbe},
 };
 
 static Mode mode(Node *n)
@@ -235,14 +249,6 @@
         return inr(s, a);
 }
 
-static int floatcompare(Node *e)
-{
-    if (exprop(e) == Ovar || exprop(e) == Olit)
-        return floatnode(e);
-    assert(e->expr.nargs > 0);
-    return floatnode(e->expr.args[0]);
-}
-
 /* If we're testing equality, etc, it's a bit silly
  * to generate the test, store it to a bite, expand it
  * to the right width, and then test it again. Try to optimize
@@ -258,10 +264,7 @@
     Loc *l1, *l2;
     AsmOp cond, jmp;
 
-    if (floatcompare(args[0]))
-        cond = reloptab[exprop(args[0])].fptest;
-    else
-        cond = reloptab[exprop(args[0])].itest;
+    cond = reloptab[exprop(args[0])].test;
     jmp = reloptab[exprop(args[0])].jmp;
     /* if we have a cond, we're knocking off the redundant test,
      * and want to eval the children */
@@ -610,21 +613,20 @@
             b = locreg(ModeB);
             r = locreg(mode(n));
             /* lnot only valid for integer-like values */
-            g(s, reloptab[exprop(n)].itest, a, a, NULL);
+            g(s, reloptab[exprop(n)].test, a, a, NULL);
             g(s, reloptab[exprop(n)].getflag, b, NULL);
             movz(s, b, r);
             break;
 
         case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
+        case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
+        case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
             a = selexpr(s, args[0]);
             b = selexpr(s, args[1]);
             a = inr(s, a);
             c = locreg(ModeB);
             r = locreg(mode(n));
-            if (floatnode(args[0]))
-                g(s, reloptab[exprop(n)].fptest, b, a, NULL);
-            else
-                g(s, reloptab[exprop(n)].itest, b, a, NULL);
+            g(s, reloptab[exprop(n)].test, b, a, NULL);
             g(s, reloptab[exprop(n)].getflag, c, NULL);
             movz(s, c, r);
             return r;
--- a/6/simp.c
+++ b/6/simp.c
@@ -1246,8 +1246,15 @@
         [Obsleq]        = Obsl,
         [Obsreq]        = Obsr,
     };
+    const Op cmpmap[Numops][3] = {
+        [Oeq]   = {Oeq, Ofeq, Oueq},
+        [One]   = {One, Ofne, Oune},
+        [Ogt]   = {Ogt, Ofgt, Ougt},
+        [Oge]   = {Oge, Ofge, Ouge},
+        [Olt]   = {Olt, Oflt, Oult},
+        [Ole]   = {Ole, Ofle, Oule}
+    };
 
-
     r = NULL;
     args = n->expr.args;
     switch (exprop(n)) {
@@ -1431,6 +1438,17 @@
             if (s->nloopstep == 0)
                 fatal(n->line, "trying to continue when not in loop");
             jmp(s, s->loopstep[s->nloopstep - 1]);
+            break;
+        case Oeq: case One: case Ogt: case Oge: case Olt: case Ole:
+            if (istyfloat(tybase(exprtype(args[0]))))
+                i = 1;
+            else if (istysigned(tybase(exprtype(args[0]))))
+                i = 0;
+            else
+                i = 2;
+            assert(cmpmap[n->expr.op][i] != Obad);
+            n->expr.op = cmpmap[n->expr.op][i];
+            r = visit(s, n);
             break;
         default:
             if (istyfloat(exprtype(n))) {
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1245,6 +1245,8 @@
         case Otrunc: case Oswiden: case Ozwiden:
         case Oint2flt: case Oflt2int:
         case Ofadd: case Ofsub: case Ofmul: case Ofdiv: case Ofneg:
+        case Ofeq: case Ofne: case Ofgt: case Ofge: case Oflt: case Ofle:
+        case Oueq: case Oune: case Ougt: case Ouge: case Oult: case Oule:
         case Ouget:
             die("Should not see %s in fe", opstr(exprop(n)));
             break;
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -56,7 +56,8 @@
 O(Otup, 1)
 O(Ostruct, 1)
 O(Oarr, 1)
-/* backend-only */
+
+/* all below this point are backend-only */
 O(Ocjmp, 1)        /* conditional jump */
 O(Oset, 1)         /* store to var */
 O(Osllen, 1)       /* size of slice */
@@ -72,3 +73,18 @@
 O(Ofmul, 1)
 O(Ofdiv, 1)
 O(Ofneg, 1)
+
+/* floating point comparisons */
+O(Ofeq, 1)
+O(Ofne, 1)
+O(Ofgt, 1)
+O(Ofge, 1)
+O(Oflt, 1)
+O(Ofle, 1)
+/* unsigned comparisons */
+O(Oueq, 1)
+O(Oune, 1)
+O(Ougt, 1)
+O(Ouge, 1)
+O(Oult, 1)
+O(Oule, 1)