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
}