shithub: mc

Download patch

ref: 8fe6f9a431955e1fbede7bd3b37a7976f5161b57
parent: 63102e84123635698b1e23aa725f52bfdb39d2f0
author: Ori Bernstein <[email protected]>
date: Wed Sep 17 22:22:45 EDT 2014

Save and restore xmm registers correctly

    Generate instructions with the right mode and all that
    good stuff.

--- a/6/asm.h
+++ b/6/asm.h
@@ -185,6 +185,8 @@
     Bitset *initial;    /* initial set of locations used by this fn */
 };
 
+extern char *modenames[];
+
 /* entry points */
 void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab);
 void genasm(FILE *fd, Func *fn, Htab *globls, Htab *strtab);
@@ -208,6 +210,8 @@
 Loc *loclit(long val, Mode m);
 Loc *loclitl(char *lbl);
 Loc *coreg(Reg r, Mode m);
+int isfloatmode(Mode m);
+int isintmode(Mode m);
 
 void locprint(FILE *fd, Loc *l, char spec);
 void iprintf(FILE *fd, Insn *insn);
--- a/6/insns.def
+++ b/6/insns.def
@@ -90,7 +90,7 @@
 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())
+Insn(Iret,      "\tret\n",                      Use(.r={Rrax,Rxmm0d}), Def())
 
 /* not really an insn... */
 Insn(Ilbl,      "%v:\n",                        Use(), Def())
--- a/6/isel.c
+++ b/6/isel.c
@@ -92,16 +92,6 @@
     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;
@@ -176,7 +166,7 @@
     i = mkinsnv(op, ap);
     va_end(ap);
     if (debugopt['i']) {
-        printf("GEN ");
+        printf("GEN[uid=%zd] ", i->uid);
         iprintf(stdout, i);
     }
     lappend(&s->curbb->il, &s->curbb->ni, i);
@@ -783,7 +773,7 @@
                    spec == 'x' ||
                    spec == 'u');
             if (l->reg.colour == Rnone)
-                fprintf(fd, "%%P.%zd", l->reg.id);
+                fprintf(fd, "%%P.%zd%s", l->reg.id, modenames[l->mode]);
             else
                 fprintf(fd, "%s", regnames[l->reg.colour]);
             break;
@@ -847,11 +837,14 @@
             }
             break;
         case Imovs:
+            if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
+                break;
             /* moving a reg to itself is dumb. */
             if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
                 return;
             break;
         case Imov:
+            assert(!isfloatmode(insn->args[0]->mode));
             if (insn->args[0]->type != Locreg || insn->args[1]->type != Locreg)
                 break;
             if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
@@ -950,7 +943,11 @@
     for (i = 0; savedregs[i] != Rnone; i++) {
         phys = locphysreg(savedregs[i]);
         s->calleesave[i] = locreg(phys->mode);
-        g(s, Imov, phys, s->calleesave[i], NULL);
+        if (isfloatmode(phys->mode)) {
+            g(s, Imovs, phys, s->calleesave[i], NULL);
+        } else {
+            g(s, Imov, phys, s->calleesave[i], NULL);
+        }
     }
     s->nsaved = i;
     s->stksz = stksz; /* need to update if we spill */
@@ -972,8 +969,13 @@
             g(s, Imov, ret, coreg(Rax, ret->mode), NULL);
     }
     /* restore registers */
-    for (i = 0; savedregs[i] != Rnone; i++)
-        g(s, Imov, s->calleesave[i], locphysreg(savedregs[i]), NULL);
+    for (i = 0; savedregs[i] != Rnone; i++) {
+        if (isfloatmode(s->calleesave[i]->mode)) {
+            g(s, Imovs, s->calleesave[i], locphysreg(savedregs[i]), NULL);
+        } else {
+            g(s, Imov, s->calleesave[i], locphysreg(savedregs[i]), NULL);
+        }
+    }
     /* leave function */
     g(s, Imov, rbp, rsp, NULL);
     g(s, Ipop, rbp, NULL);
--- a/6/locs.c
+++ b/6/locs.c
@@ -63,6 +63,15 @@
     [Rebp] = {Rebp},
 };
 
+int isintmode(Mode m)
+{
+    return m == ModeB || m == ModeW || m == ModeL || m == ModeQ;
+}
+
+int isfloatmode(Mode m)
+{
+    return m == ModeF || m == ModeD;
+}
 char *genlblstr(char *buf, size_t sz)
 {
     static int nextlbl;
--- a/6/ra.c
+++ b/6/ra.c
@@ -284,7 +284,7 @@
 /* we're only interested in register->register moves */
 static int ismove(Insn *i)
 {
-    if (i->op != Imov)
+    if (i->op != Imov && i->op != Imovs)
         return 0;
     return i->args[0]->type == Locreg && i->args[1]->type == Locreg;
 }
@@ -1084,7 +1084,10 @@
         /* if there is a remapping, insert the loads and stores as needed */
         if (remap(s, bb->il[j], use, &nuse, def, &ndef)) {
             for (i = 0; i < nuse; i++) {
-                insn = mkinsn(Imov, spillslot(s, use[i].oldreg), use[i].newreg, NULL);
+                if (isfloatmode(use[i].newreg->mode))
+                    insn = mkinsn(Imovs, spillslot(s, use[i].oldreg), use[i].newreg, NULL);
+                else
+                    insn = mkinsn(Imov, spillslot(s, use[i].oldreg), use[i].newreg, NULL);
                 lappend(&new, &nnew, insn);
                 if (debugopt['r']) {
                     printf("loading ");
@@ -1098,7 +1101,10 @@
             updatelocs(s, insn, use, nuse, def, ndef);
             lappend(&new, &nnew, insn);
             for (i = 0; i < ndef; i++) {
-                insn = mkinsn(Imov, def[i].newreg, spillslot(s, def[i].oldreg), NULL);
+                if (isfloatmode(def[i].newreg->mode))
+                    insn = mkinsn(Imovs, def[i].newreg, spillslot(s, def[i].oldreg), NULL);
+                else
+                    insn = mkinsn(Imov, def[i].newreg, spillslot(s, def[i].oldreg), NULL);
                 lappend(&new, &nnew, insn);
                 if (debugopt['r']) {
                     printf("storing ");
--- a/libstd/fltfmt.myr
+++ b/libstd/fltfmt.myr
@@ -224,13 +224,14 @@
 	var n, i
 
 	n = 0
-	if k == 0
-		n += encode(buf[n:], '.')
-	elif k < 0
+	if k < 0
 		for i = 0; i < -k; i++
 			n += encode(buf[n:], '0')
 		;;
 	;;
 	buf[n++] = dig[d]
+	if k == 0
+		n += encode(buf[n:], '.')
+	;;
 	-> n
 }