shithub: mc

Download patch

ref: e8e64a97011517107df79b4fa2905a58d1eb2280
parent: 2788f5eea5708ab8554bac41411543bef360389e
author: Ori Bernstein <[email protected]>
date: Sun Dec 29 08:13:43 EST 2013

More principled FP support started.

--- a/6/insns.def
+++ b/6/insns.def
@@ -2,12 +2,13 @@
    is defined by the following macro:
         Insn(enumval, fmt, attr)
     The format string 'fmt' has the following expansions:
-        %r            - reg
+        %r            - int reg
+        %f            - xmm reg
         %m            - mem
         %i            - imm
         %v            - reg/mem
         %u            - reg/imm
-        %x            - reg/mem/imm
+        %x            - reg/freg/mem/imm
         %[1-9]*t      - Mode of an operand. The optional number
                         preceeding it is the operand desired for
                         the mode.
@@ -20,9 +21,10 @@
 
 Insn(Inone,     "BAD_INSN",                     Use(), Def())
 /* Note, the mov instruction is specified in an overly general manner. */
-Insn(Imov,      "\tmov%t %x,%x\n",             Use(.l={1}),                    Def(.l={2}))
-Insn(Imovz,     "\tmovz%1t%2t %x,%x\n",         Use(.l={1}),                    Def(.l={2}))
-Insn(Imovs,     "\tmovs%1t%2t %x,%x\n",         Use(.l={1}),                    Def(.l={2}))
+Insn(Imov,      "\tmov%t %x,%x\n",              Use(.l={1}),                    Def(.l={2}))
+Insn(Imovt,      "PSEUDO: TRUNCATE\n",          Use(.l={1}),                    Def(.l={2}))
+Insn(Imovzx,    "\tmovz%1t%2t %x,%x\n",         Use(.l={1}),                    Def(.l={2}))
+Insn(Imovsx,    "\tmovs%1t%2t %x,%x\n",         Use(.l={1}),                    Def(.l={2}))
 Insn(Irepmovsb, "\trep movsb\n",                Use(.r={Rrcx,Rrsi,Rrdi}),       Def())
 Insn(Irepmovsw, "\trep movsw\n",                Use(.r={Rrcx,Rrsi,Rrdi}),       Def())
 Insn(Irepmovsl, "\trep movsl\n",                Use(.r={Rrcx,Rrsi,Rrdi}),       Def())
@@ -59,12 +61,15 @@
 Insn(Isetge,    "\tsetge %v\n",                 Use(),  Def(.l={1}))
 
 /* fp specific instructions */
+Insn(Imovs,      "\tmovs%1t %x,%f\n",                 Use(.l={1}),                    Def(.l={2}))
 Insn(Icvttsd2si, "\tcvttsd2si%2t %x,%r\n",      Use(.l={1}),                    Def(.l={2}))
-Insn(Icvttsi2sd, "\tcvttsd2si%2t %x,%r\n",      Use(.l={1}),                    Def(.l={2}))
-Insn(Ifdiv,      "\tdiv%t %x,%r\n",             Use(.l={1},.r={Reax,Redx}),     Def(.r={Reax,Redx}))
-Insn(Ifmul,      "\tmul%t %x,%r\n",             Use(.l={1,2}),                  Def(.l={2}))
-Insn(Ifmov,      "\tmov%t %x,%x\n",             Use(.l={1,2}),                  Def(.l={2}))
-Insn(Icomi,      "\tcomi%t %x,%r\n",            Use(.l={1,2}),                  Def())
+Insn(Icvttsi2sd, "\tcvttsi2sd%2t %x,%f\n",      Use(.l={1}),                    Def(.l={2}))
+Insn(Iadds,      "\tadds%t %x,%f\n",             Use(.l={1},.r={Reax,Redx}),     Def(.r={Reax,Redx}))
+Insn(Isubs,      "\tsubs%t %x,%f\n",             Use(.l={1},.r={Reax,Redx}),     Def(.r={Reax,Redx}))
+Insn(Imuls,      "\tmuls%t %x,%f\n",            Use(.l={1,2}),                  Def(.l={2}))
+Insn(Idivs,      "\tdiv%t %x,%f\n",             Use(.l={1},.r={Reax,Redx}),     Def(.r={Reax,Redx}))
+Insn(Icomi,      "\tcomi%t %x,%f\n",            Use(.l={1,2}),                  Def())
+Insn(Ixorp,      "\tmuls%t %x,%f\n",            Use(.l={1,2}),                  Def(.l={2}))
 
 /* branch instructions */
 Insn(Icall,     "\tcall %v\n",                  Use(.l={1}), Def(.r={Rrax}))
--- a/6/isel.c
+++ b/6/isel.c
@@ -28,8 +28,8 @@
   [ModeW] = "w",
   [ModeL] = "l",
   [ModeQ] = "q",
-  [ModeF] = "ss",
-  [ModeD] = "sd"
+  [ModeF] = "s",
+  [ModeD] = "d"
 };
 
 /* forward decls */
@@ -78,6 +78,16 @@
     return ModeQ;
 }
 
+static int isintmode(Mode m)
+{
+    return m == ModeB || m == ModeW || m == ModeL || m == ModeQ;
+}
+
+static int isfloatmode(Mode m)
+{
+    return m == ModeF || m == ModeD;
+}
+
 static Loc *loc(Isel *s, Node *n)
 {
     ssize_t stkoff;
@@ -161,7 +171,7 @@
     if (src->mode == dst->mode)
         g(s, Imov, src, dst, NULL);
     else
-        g(s, Imovz, src, dst, NULL);
+        g(s, Imovzx, src, dst, NULL);
 }
 
 static void load(Isel *s, Loc *a, Loc *b)
@@ -173,7 +183,10 @@
         l = locmem(0, b, Rnone, a->mode);
     else
         l = a;
-    g(s, Imov, l, b, NULL);
+    if (isfloatmode(b->mode))
+        g(s, Imovs, l, b, NULL);
+    else
+        g(s, Imov, l, b, NULL);
 }
 
 static void stor(Isel *s, Loc *a, Loc *b)
@@ -467,7 +480,6 @@
     Loc *a, *b, *c, *d, *r;
     Loc *eax, *edx, *cl; /* x86 wants some hard-coded regs */
     Node **args;
-    int sz;
 
     args = n->expr.args;
     eax = locphysreg(Reax);
@@ -480,10 +492,8 @@
         case Obor:      r = binop(s, Ior,  args[0], args[1]); break;
         case Oband:     r = binop(s, Iand, args[0], args[1]); break;
         case Obxor:     r = binop(s, Ixor, args[0], args[1]); break;
-        case Omul:      
-            if (floattype(exprtype(n)))
-                r = binop(s, Ifmul, args[0], args[1]);
-            else if (size(args[0]) == 1) {
+        case Omul:
+            if (size(args[0]) == 1) {
                 a = selexpr(s, args[0]);
                 b = selexpr(s, args[1]);
 
@@ -498,53 +508,52 @@
             break;
         case Odiv:
         case Omod:
-            if (floattype(exprtype(n))) {
-                r = binop(s, Ifdiv, args[0], args[1]);
-            } else {
-                /* these get clobbered by the div insn */
-                a = selexpr(s, args[0]);
-                b = selexpr(s, args[1]);
-                b = inr(s, b);
-                c = coreg(Reax, mode(n));
-                r = locreg(a->mode);
-                if (r->mode == ModeB)
-                    g(s, Ixor, eax, eax, NULL);
-                else
-                    g(s, Ixor, edx, edx, NULL);
-                g(s, Imov, a, c, NULL);
-                g(s, Idiv, b, NULL);
-                if (exprop(n) == Odiv)
-                    d = coreg(Reax, mode(n));
-                else if (r->mode != ModeB)
-                    d = coreg(Redx, mode(n));
-                else
-                    d = locphysreg(Rah);
-                g(s, Imov, d, r, NULL);
-            }
+            /* these get clobbered by the div insn */
+            a = selexpr(s, args[0]);
+            b = selexpr(s, args[1]);
+            b = inr(s, b);
+            c = coreg(Reax, mode(n));
+            r = locreg(a->mode);
+            if (r->mode == ModeB)
+                g(s, Ixor, eax, eax, NULL);
+            else
+                g(s, Ixor, edx, edx, NULL);
+            g(s, Imov, a, c, NULL);
+            g(s, Idiv, b, NULL);
+            if (exprop(n) == Odiv)
+                d = coreg(Reax, mode(n));
+            else if (r->mode != ModeB)
+                d = coreg(Redx, mode(n));
+            else
+                d = locphysreg(Rah);
+            g(s, Imov, d, r, NULL);
             break;
         case Oneg:
             r = selexpr(s, args[0]);
             r = inr(s, r);
-            if (floatnode(args[0])) {
-                sz = size(args[0]);
-                a = NULL;
-                b = NULL;
-                if (sz == 4) {
-                    a = locreg(ModeD);
-                    b = loclit(1 << (8*sz-1), ModeD);
-                    g(s, Imov, r, a);
-                } else if (size(args[0]) == 8) {
-                    a = locreg(ModeQ);
-                    b = loclit(1 << (8*sz-1), ModeQ);
-                    g(s, Imov, r, a, NULL);
-                }
-                g(s, Ixor, b, a, NULL);
-                g(s, Imov, a, r, NULL);
-            } else {
-                g(s, Ineg, r, NULL);
-            }
+            g(s, Ineg, r, NULL);
             break;
 
+        /* fp expressions */
+        case Ofadd:      r = binop(s, Iadds, args[0], args[1]); break;
+        case Ofsub:      r = binop(s, Isubs, args[0], args[1]); break;
+        case Ofmul:      r = binop(s, Imuls, args[0], args[1]); break;
+        case Ofdiv:      r = binop(s, Idivs, args[0], args[1]); break;
+        case Ofneg:
+            a = NULL;
+            b = NULL;
+            if (mode(args[0]) == ModeF) {
+                a = locreg(ModeF);
+                b = loclit(1LL << (31), ModeF);
+                g(s, Imovs, r, a);
+            } else if (mode(args[0]) == ModeD) {
+                a = locreg(ModeQ);
+                b = loclit(1LL << 63, ModeQ);
+                g(s, Imov, r, a, NULL);
+            }
+            g(s, Ixor, b, a, NULL);
+            g(s, Imov, a, r, NULL);
+            break;
         case Obsl:
         case Obsr:
             a = inr(s, selexpr(s, args[0]));
@@ -670,17 +679,21 @@
             a = selexpr(s, args[0]);
             a = inr(s, a);
             r = locreg(mode(n));
-            g(s, Imovs, a, r, NULL);
+            g(s, Imovsx, a, r, NULL);
             break;
         case Oint2flt:
             a = selexpr(s, args[0]);
+            b = locreg(ModeQ);
             r = locreg(mode(n));
-            g(s, Icvttsi2sd, a, r, NULL);
+            g(s, Imovs, a, b, NULL);
+            g(s, Icvttsi2sd, b, r, NULL);
             break;
         case Oflt2int:
             a = selexpr(s, args[0]);
+            b = locreg(ModeQ);
             r = locreg(mode(n));
-            g(s, Icvttsi2sd, a, r, NULL);
+            g(s, Icvttsd2si, a, b, NULL);
+            g(s, Imov, b, r, NULL);
             break;
 
         /* These operators should never show up in the reduced trees,
@@ -713,7 +726,11 @@
             fprintf(fd, "%s", l->lbl);
             break;
         case Locreg:
-            assert(spec == 'r' || spec == 'v' || spec == 'x' || spec == 'u');
+            assert((spec == 'r' && isintmode(l->mode)) || 
+                   (spec == 'f' && isfloatmode(l->mode)) ||
+                   spec == 'v' ||
+                   spec == 'x' ||
+                   spec == 'u');
             if (l->reg.colour == Rnone)
                 fprintf(fd, "%%P.%zd", l->reg.id);
             else
@@ -770,7 +787,7 @@
      * we don't know the name of the reg to use, we need to sub it in when
      * writing... */
     switch (insn->op) {
-        case Imovz:
+        case Imovzx:
             if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
                 if (insn->args[1]->reg.colour) {
                     insn->op = Imov;
@@ -808,7 +825,8 @@
         switch (*p) {
             case '\0':
                 goto done; /* skip the final p++ */
-            case 'r': /* register */
+            case 'r': /* int register */
+            case 'f': /* float register */
             case 'm': /* memory */
             case 'i': /* imm */
             case 'v': /* reg/mem */
--- a/6/simp.c
+++ b/6/simp.c
@@ -1388,6 +1388,16 @@
                 r = t->expr.args[0];
             break;
         default:
+            if (istyfloat(exprtype(n))) {
+                switch (exprop(n)) {
+                    case Oadd: n->expr.op = Ofadd; break;
+                    case Osub: n->expr.op = Ofsub; break;
+                    case Omul: n->expr.op = Ofmul; break;
+                    case Odiv: n->expr.op = Ofdiv; break;
+                    case Oneg: n->expr.op = Ofneg; break;
+                    default: break;
+                }
+            }
             r = visit(s, n);
     }
     return r;
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1201,6 +1201,7 @@
         case Oblit: case Numops:
         case Otrunc: case Oswiden: case Ozwiden:
         case Oint2flt: case Oflt2int:
+        case Ofadd: case Ofsub: case Ofmul: case Ofdiv: case Ofneg:
         case Ouget:
             die("Should not see %s in fe", opstr(exprop(n)));
             break;
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -65,3 +65,8 @@
 O(Oswiden, 1)      /* sign-extending widening cast */
 O(Oflt2int, 1)     /* float to int conversion */
 O(Oint2flt, 1)     /* int to float conversion */
+O(Ofadd, 1)
+O(Ofsub, 1)
+O(Ofmul, 1)
+O(Ofdiv, 1)
+O(Ofneg, 1)
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -384,6 +384,7 @@
 Cstr *mkcstr(int line, char *name, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs);
 Type *mktylike(int line, Ty ty); /* constrains tyvar t like it was builtin ty */
 int   istysigned(Type *t);
+int   istyfloat(Type *t);
 int   isgeneric(Type *t);
 int   hasparams(Type *t);
 
--- a/parse/type.c
+++ b/parse/type.c
@@ -258,9 +258,19 @@
 
 int istysigned(Type *t)
 {
-    switch (t->type) {
+    switch (tybase(t)->type) {
         case Tyint8: case Tyint16: case Tyint:
         case Tyint32: case Tyint64: case Tylong:
+            return 1;
+        default:
+            return 0;
+    }
+}
+
+int istyfloat(Type *t)
+{
+    switch (tybase(t)->type) {
+        case Tyfloat32: case Tyfloat64:
             return 1;
         default:
             return 0;