ref: b85c69ca0c686edc76fcf4bb2da54e3b5263bbba
parent: 2433e863b1b3e802f38dd6db534b52867f670269
author: Ori Bernstein <[email protected]>
date: Sun Dec 21 13:41:45 EST 2014
First attempt at supporting plan9 assemblers.
--- a/6/Makefile
+++ b/6/Makefile
@@ -1,6 +1,8 @@
INSTBIN=6m
OBJ= \
gen.o \
+ gengas.o \
+ genp9.o \
isel.o \
locs.o \
main.o \
--- a/6/asm.h
+++ b/6/asm.h
@@ -20,7 +20,7 @@
} AsmOp;
typedef enum {
-#define Reg(r, name, mode) r,
+#define Reg(r, gasname, p9name, mode) r,
#include "regs.def"
#undef Reg
Nreg
@@ -54,6 +54,11 @@
Nclass,
} Rclass;
+typedef enum {
+ Gnugas,
+ Plan9,
+} Asmsyntax;
+
/* a register, label, or memory location */
struct Loc {
Loctype type; /* the type of loc */
@@ -186,7 +191,6 @@
};
/* globals */
-extern char *modenames[];
extern Type *tyintptr;
extern Type *tyword;
extern Type *tyvoid;
@@ -197,7 +201,9 @@
void simpglobl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, size_t *nblob);
void selfunc(Isel *is, Func *fn, Htab *globls, Htab *strtab);
-void gen(Node *file, char *out);
+void gen(Asmsyntax syn, Node *file, char *out);
+void gengas(Node *file, char *out);
+void genp9(Node *file, char *out);
/* location generation */
extern size_t maxregid;
@@ -222,13 +228,10 @@
/* emitting instructions */
Insn *mkinsn(AsmOp op, ...);
-void iprintf(FILE *fd, Insn *insn);
-void locprint(FILE *fd, Loc *l, char spec);
+void dbgiprintf(FILE *fd, Insn *insn);
+void dbglocprint(FILE *fd, Loc *l, char spec);
/* register allocation */
-extern char *regnames[]; /* name table */
-extern Mode regmodes[]; /* mode table */
-extern size_t modesize[]; /* mode size table */
void regalloc(Isel *s);
Rclass rclass(Loc *l);
--- a/6/gen.c
+++ b/6/gen.c
@@ -14,557 +14,11 @@
#include "asm.h"
#include "../config.h"
-/* string tables */
-char *gasinsnfmt[] = {
-#define Insn(val, gasfmt, p9fmt, use, def) gasfmt,
-#include "insns.def"
-#undef Insn
-};
-
-char *p9insnfmt[] = {
-#define Insn(val, gasfmt, p9fmt, use, def) p9fmt,
-#include "insns.def"
-#undef Insn
-};
-
-char* gasmodenames[] = {
- [ModeB] = "b",
- [ModeW] = "w",
- [ModeL] = "l",
- [ModeQ] = "q",
- [ModeF] = "s",
- [ModeD] = "d"
-};
-
-char* p9modenames[] = {
- [ModeB] = "B",
- [ModeW] = "W",
- [ModeL] = "L",
- [ModeQ] = "Q",
- [ModeF] = "S",
- [ModeD] = "D"
-};
-
-static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *blob);
-
-static void fillglobls(Stab *st, Htab *globls)
+void gen(Asmsyntax syn, Node *file, char *out)
{
- void **k;
- size_t i, nk;
- Stab *stab;
- Node *s;
-
- k = htkeys(st->dcl, &nk);
- for (i = 0; i < nk; i++) {
- s = htget(st->dcl, k[i]);
- htput(globls, s, asmname(s->decl.name));
+ switch (syn) {
+ case Plan9: genp9(file, out); break;
+ case Gnugas: gengas(file, out); break;
+ default: die("unknown target"); break;
}
- free(k);
-
- k = htkeys(st->ns, &nk);
- for (i = 0; i < nk; i++) {
- stab = htget(st->ns, k[i]);
- fillglobls(stab, globls);
- }
- free(k);
-}
-
-static void initconsts(Htab *globls)
-{
- Type *ty;
- Node *name;
- Node *dcl;
-
- tyintptr = mktype(Zloc, Tyuint64);
- tyword = mktype(Zloc, Tyuint);
- tyvoid = mktype(Zloc, Tyvoid);
-
- ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
- name = mknsname(Zloc, "_rt", "abort_oob");
- dcl = mkdecl(Zloc, name, ty);
- dcl->decl.isconst = 1;
- dcl->decl.isextern = 1;
- htput(globls, dcl, asmname(dcl->decl.name));
-
- abortoob = mkexpr(Zloc, Ovar, name, NULL);
- abortoob->expr.type = ty;
- abortoob->expr.did = dcl->decl.did;
- abortoob->expr.isconst = 1;
-}
-
-void gasprintmem(FILE *fd, Loc *l, char spec)
-{
- if (l->type == Locmem) {
- if (l->mem.constdisp)
- fprintf(fd, "%ld", l->mem.constdisp);
- } else {
- if (l->mem.lbldisp)
- fprintf(fd, "%s", l->mem.lbldisp);
- }
- if (l->mem.base) {
- fprintf(fd, "(");
- locprint(fd, l->mem.base, 'r');
- if (l->mem.idx) {
- fprintf(fd, ",");
- locprint(fd, l->mem.idx, 'r');
- }
- if (l->mem.scale > 1)
- fprintf(fd, ",%d", l->mem.scale);
- if (l->mem.base)
- fprintf(fd, ")");
- } else if (l->type != Locmeml) {
- die("Only locmeml can have unspecified base reg");
- }
-}
-
-void p9printmem(FILE *fd, Loc *l, char spec)
-{
- gasprintmem(fd, l, spec);
-}
-
-void locprint(FILE *fd, Loc *l, char spec)
-{
- int isp9;
-
- isp9 = isupper(spec);
- spec = tolower(spec);
- assert(l->mode);
- switch (l->type) {
- case Loclitl:
- assert(spec == 'i' || spec == 'x' || spec == 'u');
- fprintf(fd, "$%s", l->lbl);
- break;
- case Loclbl:
- assert(spec == 'm' || spec == 'v' || spec == 'x');
- fprintf(fd, "%s", l->lbl);
- break;
- case Locreg:
- 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%s", l->reg.id, gasmodenames[l->mode]);
- else
- fprintf(fd, "%s", regnames[l->reg.colour]);
- break;
- case Locmem:
- case Locmeml:
- assert(spec == 'm' || spec == 'v' || spec == 'x');
- if (isp9)
- p9printmem(fd, l, spec);
- else
- gasprintmem(fd, l, spec);
- break;
- case Loclit:
- assert(spec == 'i' || spec == 'x' || spec == 'u');
- fprintf(fd, "$%ld", l->lit);
- break;
- case Locnone:
- die("Bad location in locprint()");
- break;
- }
-}
-
-static int issubreg(Loc *a, Loc *b)
-{
- return rclass(a) == rclass(b) && a->mode != b->mode;
-}
-
-void iprintf(FILE *fd, Insn *insn)
-{
- char *p;
- int i;
- int modeidx;
-
- /* x64 has a quirk; it has no movzlq because mov zero extends. This
- * means that we need to do a movl when we really want a movzlq. Since
- * we don't know the name of the reg to use, we need to sub it in when
- * writing... */
- switch (insn->op) {
- case Imovzx:
- if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
- if (insn->args[1]->reg.colour) {
- insn->op = Imov;
- insn->args[1] = coreg(insn->args[1]->reg.colour, ModeL);
- }
- }
- 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)
- break;
- /* if one reg is a subreg of another, we can just use the right
- * mode to move between them. */
- if (issubreg(insn->args[0], insn->args[1]))
- insn->args[0] = coreg(insn->args[0]->reg.colour, insn->args[1]->mode);
- /* moving a reg to itself is dumb. */
- if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
- return;
- break;
- default:
- break;
- }
- p = insnfmt[insn->op];
- i = 0;
- modeidx = 0;
- for (; *p; p++) {
- if (*p != '%') {
- fputc(*p, fd);
- continue;
- }
-
- /* %-formating */
- p++;
- switch (*p) {
- case '\0':
- goto done; /* skip the final p++ */
- case 'r': /* int register */
- case 'f': /* float register */
- case 'm': /* memory */
- case 'i': /* imm */
- case 'v': /* reg/mem */
- case 'u': /* reg/imm */
- case 'x': /* reg/mem/imm */
- locprint(fd, insn->args[i], *p);
- i++;
- break;
- case 'R': /* int register */
- case 'F': /* float register */
- case 'M': /* memory */
- case 'I': /* imm */
- case 'V': /* reg/mem */
- case 'U': /* reg/imm */
- case 'X': /* reg/mem/imm */
- locprint(fd, insn->args[i], *p);
- i++;
- break;
- case 't':
- case 'T':
- default:
- /* the asm description uses 1-based indexing, so that 0
- * can be used as a sentinel. */
- if (isdigit(*p))
- modeidx = strtol(p, &p, 10) - 1;
-
- if (*p == 't')
- fputs(gasmodenames[insn->args[modeidx]->mode], fd);
- else if (*p == 'T')
- fputs(p9modenames[insn->args[modeidx]->mode], fd);
- else
- die("Invalid %%-specifier '%c'", *p);
- break;
- }
- }
-done:
- return;
-}
-
-
-static void writebytes(FILE *fd, char *p, size_t sz)
-{
- size_t i;
-
- for (i = 0; i < sz; i++) {
- if (i % 60 == 0)
- fprintf(fd, "\t.ascii \"");
- if (p[i] == '"' || p[i] == '\\')
- fprintf(fd, "\\");
- if (isprint(p[i]))
- fprintf(fd, "%c", p[i]);
- else
- fprintf(fd, "\\%03o", (uint8_t)p[i] & 0xff);
- /* line wrapping for readability */
- if (i % 60 == 59 || i == sz - 1)
- fprintf(fd, "\"\n");
- }
-}
-
-static size_t writelit(FILE *fd, Htab *strtab, Node *v, Type *ty)
-{
- char buf[128];
- char *lbl;
- size_t sz;
- char *intsz[] = {
- [1] = ".byte",
- [2] = ".short",
- [4] = ".long",
- [8] = ".quad"
- };
- union {
- float fv;
- double dv;
- uint64_t qv;
- uint32_t lv;
- } u;
-
- assert(v->type == Nlit);
- sz = tysize(ty);
- switch (v->lit.littype) {
- case Lint: fprintf(fd, "\t%s %lld\n", intsz[sz], v->lit.intval); break;
- case Lbool: fprintf(fd, "\t.byte %d\n", v->lit.boolval); break;
- case Lchr: fprintf(fd, "\t.long %d\n", v->lit.chrval); break;
- case Lflt:
- if (tybase(v->lit.type)->type == Tyflt32) {
- u.fv = v->lit.fltval;
- fprintf(fd, "\t.long 0x%" PRIx32 "\n", u.lv);
- } else if (tybase(v->lit.type)->type == Tyflt64) {
- u.dv = v->lit.fltval;
- fprintf(fd, "\t.quad 0x%" PRIx64 "\n", u.qv);
- }
- break;
- case Lstr:
- if (hthas(strtab, &v->lit.strval)) {
- lbl = htget(strtab, &v->lit.strval);
- } else {
- lbl = genlblstr(buf, sizeof buf);
- htput(strtab, &v->lit.strval, strdup(lbl));
- }
- fprintf(fd, "\t.quad %s\n", lbl);
- fprintf(fd, "\t.quad %zd\n", v->lit.strval.len);
- break;
- case Lfunc:
- die("Generating this shit ain't ready yet ");
- break;
- case Llbl:
- die("Can't generate literal labels, ffs. They're not data.");
- break;
- }
- return sz;
-}
-
-static size_t writepad(FILE *fd, size_t sz)
-{
- assert((ssize_t)sz >= 0);
- if (sz > 0)
- fprintf(fd, "\t.fill %zd,1,0\n", sz);
- return sz;
-}
-
-static size_t getintlit(Node *n, char *failmsg)
-{
- if (exprop(n) != Olit)
- fatal(n, "%s", failmsg);
- n = n->expr.args[0];
- if (n->lit.littype != Lint)
- fatal(n, "%s", failmsg);
- return n->lit.intval;
-}
-
-static size_t writeslice(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
- Node *base, *lo, *hi;
- ssize_t loval, hival, sz;
- char *lbl;
-
- base = n->expr.args[0];
- lo = n->expr.args[1];
- hi = n->expr.args[2];
-
- /* by this point, all slicing operations should have had their bases
- * pulled out, and we should have vars with their pseudo-decls in their
- * place */
- if (exprop(base) != Ovar || !base->expr.isconst)
- fatal(base, "slice base is not a constant value");
- loval = getintlit(lo, "lower bound in slice is not constant literal");
- hival = getintlit(hi, "upper bound in slice is not constant literal");
- sz = tysize(tybase(exprtype(base))->sub[0]);
-
- lbl = htget(globls, base);
- fprintf(fd, "\t.quad %s + (%zd*%zd)\n", lbl, loval, sz);
- fprintf(fd, "\t.quad %zd\n", (hival - loval));
- return size(n);
-}
-
-static size_t writestruct(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
- Type *t;
- Node **dcl;
- int found;
- size_t i, j;
- size_t sz, pad, end;
- size_t ndcl;
-
- sz = 0;
- t = tybase(exprtype(n));
- assert(t->type == Tystruct);
- dcl = t->sdecls;
- ndcl = t->nmemb;
- for (i = 0; i < ndcl; i++) {
- pad = alignto(sz, decltype(dcl[i]));
- sz += writepad(fd, pad - sz);
- found = 0;
- for (j = 0; j < n->expr.nargs; j++)
- if (!strcmp(namestr(n->expr.args[j]->expr.idx), declname(dcl[i]))) {
- found = 1;
- sz += writeblob(fd, globls, strtab, n->expr.args[j]);
- }
- if (!found)
- sz += writepad(fd, size(dcl[i]));
- }
- end = alignto(sz, t);
- sz += writepad(fd, end - sz);
- return sz;
-}
-static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
- size_t i, sz;
-
- switch(exprop(n)) {
- case Otup:
- case Oarr:
- sz = 0;
- for (i = 0; i < n->expr.nargs; i++)
- sz += writeblob(fd, globls, strtab, n->expr.args[i]);
- break;
- case Ostruct:
- sz = writestruct(fd, globls, strtab, n);
- break;
- case Olit:
- sz = writelit(fd, strtab, n->expr.args[0], exprtype(n));
- break;
- case Oslice:
- sz = writeslice(fd, globls, strtab, n);
- break;
- default:
- dump(n, stdout);
- die("Nonliteral initializer for global");
- break;
- }
- return sz;
-}
-
-void genstrings(FILE *fd, Htab *strtab)
-{
- void **k;
- Str *s;
- size_t i, nk;
-
- k = htkeys(strtab, &nk);
- for (i = 0; i < nk; i++) {
- s = k[i];
- fprintf(fd, "%s:\n", (char*)htget(strtab, k[i]));
- writebytes(fd, s->buf, s->len);
- }
-}
-
-
-static void writeasm(FILE *fd, Isel *s, Func *fn)
-{
- size_t i, j;
-
- if (fn->isexport || !strcmp(fn->name, Symprefix "main"))
- fprintf(fd, ".globl %s\n", fn->name);
- fprintf(fd, "%s:\n", fn->name);
- for (j = 0; j < s->cfg->nbb; j++) {
- if (!s->bb[j])
- continue;
- for (i = 0; i < s->bb[j]->nlbls; i++)
- fprintf(fd, "%s:\n", s->bb[j]->lbls[i]);
- for (i = 0; i < s->bb[j]->ni; i++)
- iprintf(fd, s->bb[j]->il[i]);
- }
-}
-
-void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
-{
- char *lbl;
-
- /* lits and such also get wrapped in decls */
- assert(blob->type == Ndecl);
-
- lbl = htget(globls, blob);
- if (blob->decl.vis != Visintern)
- fprintf(fd, ".globl %s\n", lbl);
- fprintf(fd, "%s:\n", lbl);
- if (blob->decl.init)
- writeblob(fd, globls, strtab, blob->decl.init);
- else
- writepad(fd, size(blob));
-}
-
-/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
- * natively supported, as promised in the output of reduce(). No 64-bit
- * operations on x32, no structures, and so on. */
-void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
-{
- Isel is = {0,};
-
- is.reglocs = mkht(varhash, vareq);
- is.stkoff = fn->stkoff;
- is.globls = globls;
- is.ret = fn->ret;
- is.cfg = fn->cfg;
-
- selfunc(&is, fn, globls, strtab);
- if (debugopt['i'])
- writeasm(stdout, &is, fn);
- writeasm(fd, &is, fn);
-}
-
-void gen(Node *file, char *out)
-{
- Htab *globls, *strtab;
- Node *n, **blob;
- Func **fn;
- size_t nfn, nblob;
- size_t i;
- FILE *fd;
-
- /* ensure that all physical registers have a loc created before any
- * other locs, so that locmap[Physreg] maps to the Loc for the physreg
- * in question */
- for (i = 0; i < Nreg; i++)
- locphysreg(i);
-
- fn = NULL;
- nfn = 0;
- blob = NULL;
- nblob = 0;
- globls = mkht(varhash, vareq);
- initconsts(globls);
-
- /* We need to define all global variables before use */
- fillglobls(file->file.globls, globls);
-
- pushstab(file->file.globls);
- for (i = 0; i < file->file.nstmts; i++) {
- n = file->file.stmts[i];
- switch (n->type) {
- case Nuse: /* nothing to do */
- case Nimpl:
- break;
- case Ndecl:
- simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
- break;
- default:
- die("Bad node %s in toplevel", nodestr(n->type));
- break;
- }
- }
- popstab();
-
- fd = fopen(out, "w");
- if (!fd)
- die("Couldn't open fd %s", out);
-
- strtab = mkht(strlithash, strliteq);
- fprintf(fd, ".data\n");
- for (i = 0; i < nblob; i++)
- genblob(fd, blob[i], globls, strtab);
- fprintf(fd, ".text\n");
- for (i = 0; i < nfn; i++)
- genfunc(fd, fn[i], globls, strtab);
- genstrings(fd, strtab);
- fclose(fd);
}
--- /dev/null
+++ b/6/gengas.c
@@ -1,0 +1,557 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+#include "mi.h"
+#include "asm.h"
+#include "../config.h"
+
+static char *insnfmt[] = {
+#define Insn(val, gasfmt, p9fmt, use, def) gasfmt,
+#include "insns.def"
+#undef Insn
+};
+
+static char *regnames[] = {
+#define Reg(r, gasname, p9name, mode) gasname,
+#include "regs.def"
+#undef Reg
+};
+
+static char* modenames[] = {
+ [ModeB] = "b",
+ [ModeW] = "w",
+ [ModeL] = "l",
+ [ModeQ] = "q",
+ [ModeF] = "s",
+ [ModeD] = "d"
+};
+
+static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *blob);
+static void locprint(FILE *fd, Loc *l, char spec);
+
+static void fillglobls(Stab *st, Htab *globls)
+{
+ void **k;
+ size_t i, nk;
+ Stab *stab;
+ Node *s;
+
+ k = htkeys(st->dcl, &nk);
+ for (i = 0; i < nk; i++) {
+ s = htget(st->dcl, k[i]);
+ htput(globls, s, asmname(s->decl.name));
+ }
+ free(k);
+
+ k = htkeys(st->ns, &nk);
+ for (i = 0; i < nk; i++) {
+ stab = htget(st->ns, k[i]);
+ fillglobls(stab, globls);
+ }
+ free(k);
+}
+
+static void initconsts(Htab *globls)
+{
+ Type *ty;
+ Node *name;
+ Node *dcl;
+
+ tyintptr = mktype(Zloc, Tyuint64);
+ tyword = mktype(Zloc, Tyuint);
+ tyvoid = mktype(Zloc, Tyvoid);
+
+ ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
+ name = mknsname(Zloc, "_rt", "abort_oob");
+ dcl = mkdecl(Zloc, name, ty);
+ dcl->decl.isconst = 1;
+ dcl->decl.isextern = 1;
+ htput(globls, dcl, asmname(dcl->decl.name));
+
+ abortoob = mkexpr(Zloc, Ovar, name, NULL);
+ abortoob->expr.type = ty;
+ abortoob->expr.did = dcl->decl.did;
+ abortoob->expr.isconst = 1;
+}
+
+void printmem(FILE *fd, Loc *l, char spec)
+{
+ if (l->type == Locmem) {
+ if (l->mem.constdisp)
+ fprintf(fd, "%ld", l->mem.constdisp);
+ } else {
+ if (l->mem.lbldisp)
+ fprintf(fd, "%s", l->mem.lbldisp);
+ }
+ if (l->mem.base) {
+ fprintf(fd, "(");
+ locprint(fd, l->mem.base, 'r');
+ if (l->mem.idx) {
+ fprintf(fd, ",");
+ locprint(fd, l->mem.idx, 'r');
+ }
+ if (l->mem.scale > 1)
+ fprintf(fd, ",%d", l->mem.scale);
+ if (l->mem.base)
+ fprintf(fd, ")");
+ } else if (l->type != Locmeml) {
+ die("Only locmeml can have unspecified base reg");
+ }
+}
+
+static void locprint(FILE *fd, Loc *l, char spec)
+{
+ assert(l->mode);
+ switch (l->type) {
+ case Loclitl:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%s", l->lbl);
+ break;
+ case Loclbl:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ fprintf(fd, "%s", l->lbl);
+ break;
+ case Locreg:
+ 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%s", l->reg.id, modenames[l->mode]);
+ else
+ fprintf(fd, "%s", regnames[l->reg.colour]);
+ break;
+ case Locmem:
+ case Locmeml:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ printmem(fd, l, spec);
+ break;
+ case Loclit:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%ld", l->lit);
+ break;
+ case Locnone:
+ die("Bad location in locprint()");
+ break;
+ }
+}
+
+static int issubreg(Loc *a, Loc *b)
+{
+ return rclass(a) == rclass(b) && a->mode != b->mode;
+}
+
+void iprintf(FILE *fd, Insn *insn)
+{
+ char *p;
+ int i;
+ int modeidx;
+
+ /* x64 has a quirk; it has no movzlq because mov zero extends. This
+ * means that we need to do a movl when we really want a movzlq. Since
+ * we don't know the name of the reg to use, we need to sub it in when
+ * writing... */
+ switch (insn->op) {
+ case Imovzx:
+ if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
+ if (insn->args[1]->reg.colour) {
+ insn->op = Imov;
+ insn->args[1] = coreg(insn->args[1]->reg.colour, ModeL);
+ }
+ }
+ 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)
+ break;
+ /* if one reg is a subreg of another, we can just use the right
+ * mode to move between them. */
+ if (issubreg(insn->args[0], insn->args[1]))
+ insn->args[0] = coreg(insn->args[0]->reg.colour, insn->args[1]->mode);
+ /* moving a reg to itself is dumb. */
+ if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
+ return;
+ break;
+ default:
+ break;
+ }
+ p = insnfmt[insn->op];
+ i = 0;
+ modeidx = 0;
+ for (; *p; p++) {
+ if (*p != '%') {
+ fputc(*p, fd);
+ continue;
+ }
+
+ /* %-formating */
+ p++;
+ switch (*p) {
+ case '\0':
+ goto done; /* skip the final p++ */
+ case 'r': /* int register */
+ case 'f': /* float register */
+ case 'm': /* memory */
+ case 'i': /* imm */
+ case 'v': /* reg/mem */
+ case 'u': /* reg/imm */
+ case 'x': /* reg/mem/imm */
+ locprint(fd, insn->args[i], *p);
+ i++;
+ break;
+ case 'R': /* int register */
+ case 'F': /* float register */
+ case 'M': /* memory */
+ case 'I': /* imm */
+ case 'V': /* reg/mem */
+ case 'U': /* reg/imm */
+ case 'X': /* reg/mem/imm */
+ locprint(fd, insn->args[i], *p);
+ i++;
+ break;
+ case 't':
+ case 'T':
+ default:
+ /* the asm description uses 1-based indexing, so that 0
+ * can be used as a sentinel. */
+ if (isdigit(*p))
+ modeidx = strtol(p, &p, 10) - 1;
+
+ if (*p == 't')
+ fputs(modenames[insn->args[modeidx]->mode], fd);
+ else
+ die("Invalid %%-specifier '%c'", *p);
+ break;
+ }
+ }
+done:
+ return;
+}
+
+
+static void writebytes(FILE *fd, char *p, size_t sz)
+{
+ size_t i;
+
+ for (i = 0; i < sz; i++) {
+ if (i % 60 == 0)
+ fprintf(fd, "\t.ascii \"");
+ if (p[i] == '"' || p[i] == '\\')
+ fprintf(fd, "\\");
+ if (isprint(p[i]))
+ fprintf(fd, "%c", p[i]);
+ else
+ fprintf(fd, "\\%03o", (uint8_t)p[i] & 0xff);
+ /* line wrapping for readability */
+ if (i % 60 == 59 || i == sz - 1)
+ fprintf(fd, "\"\n");
+ }
+}
+
+static size_t writelit(FILE *fd, Htab *strtab, Node *v, Type *ty)
+{
+ char buf[128];
+ char *lbl;
+ size_t sz;
+ char *intsz[] = {
+ [1] = ".byte",
+ [2] = ".short",
+ [4] = ".long",
+ [8] = ".quad"
+ };
+ union {
+ float fv;
+ double dv;
+ uint64_t qv;
+ uint32_t lv;
+ } u;
+
+ assert(v->type == Nlit);
+ sz = tysize(ty);
+ switch (v->lit.littype) {
+ case Lint: fprintf(fd, "\t%s %lld\n", intsz[sz], v->lit.intval); break;
+ case Lbool: fprintf(fd, "\t.byte %d\n", v->lit.boolval); break;
+ case Lchr: fprintf(fd, "\t.long %d\n", v->lit.chrval); break;
+ case Lflt:
+ if (tybase(v->lit.type)->type == Tyflt32) {
+ u.fv = v->lit.fltval;
+ fprintf(fd, "\t.long 0x%" PRIx32 "\n", u.lv);
+ } else if (tybase(v->lit.type)->type == Tyflt64) {
+ u.dv = v->lit.fltval;
+ fprintf(fd, "\t.quad 0x%" PRIx64 "\n", u.qv);
+ }
+ break;
+ case Lstr:
+ if (hthas(strtab, &v->lit.strval)) {
+ lbl = htget(strtab, &v->lit.strval);
+ } else {
+ lbl = genlblstr(buf, sizeof buf);
+ htput(strtab, &v->lit.strval, strdup(lbl));
+ }
+ fprintf(fd, "\t.quad %s\n", lbl);
+ fprintf(fd, "\t.quad %zd\n", v->lit.strval.len);
+ break;
+ case Lfunc:
+ die("Generating this shit ain't ready yet ");
+ break;
+ case Llbl:
+ die("Can't generate literal labels, ffs. They're not data.");
+ break;
+ }
+ return sz;
+}
+
+static size_t writepad(FILE *fd, size_t sz)
+{
+ assert((ssize_t)sz >= 0);
+ if (sz > 0)
+ fprintf(fd, "\t.fill %zd,1,0\n", sz);
+ return sz;
+}
+
+static size_t getintlit(Node *n, char *failmsg)
+{
+ if (exprop(n) != Olit)
+ fatal(n, "%s", failmsg);
+ n = n->expr.args[0];
+ if (n->lit.littype != Lint)
+ fatal(n, "%s", failmsg);
+ return n->lit.intval;
+}
+
+static size_t writeslice(FILE *fd, Htab *globls, Htab *strtab, Node *n)
+{
+ Node *base, *lo, *hi;
+ ssize_t loval, hival, sz;
+ char *lbl;
+
+ base = n->expr.args[0];
+ lo = n->expr.args[1];
+ hi = n->expr.args[2];
+
+ /* by this point, all slicing operations should have had their bases
+ * pulled out, and we should have vars with their pseudo-decls in their
+ * place */
+ if (exprop(base) != Ovar || !base->expr.isconst)
+ fatal(base, "slice base is not a constant value");
+ loval = getintlit(lo, "lower bound in slice is not constant literal");
+ hival = getintlit(hi, "upper bound in slice is not constant literal");
+ sz = tysize(tybase(exprtype(base))->sub[0]);
+
+ lbl = htget(globls, base);
+ fprintf(fd, "\t.quad %s + (%zd*%zd)\n", lbl, loval, sz);
+ fprintf(fd, "\t.quad %zd\n", (hival - loval));
+ return size(n);
+}
+
+static size_t writestruct(FILE *fd, Htab *globls, Htab *strtab, Node *n)
+{
+ Type *t;
+ Node **dcl;
+ int found;
+ size_t i, j;
+ size_t sz, pad, end;
+ size_t ndcl;
+
+ sz = 0;
+ t = tybase(exprtype(n));
+ assert(t->type == Tystruct);
+ dcl = t->sdecls;
+ ndcl = t->nmemb;
+ for (i = 0; i < ndcl; i++) {
+ pad = alignto(sz, decltype(dcl[i]));
+ sz += writepad(fd, pad - sz);
+ found = 0;
+ for (j = 0; j < n->expr.nargs; j++)
+ if (!strcmp(namestr(n->expr.args[j]->expr.idx), declname(dcl[i]))) {
+ found = 1;
+ sz += writeblob(fd, globls, strtab, n->expr.args[j]);
+ }
+ if (!found)
+ sz += writepad(fd, size(dcl[i]));
+ }
+ end = alignto(sz, t);
+ sz += writepad(fd, end - sz);
+ return sz;
+}
+static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *n)
+{
+ size_t i, sz;
+
+ switch(exprop(n)) {
+ case Otup:
+ case Oarr:
+ sz = 0;
+ for (i = 0; i < n->expr.nargs; i++)
+ sz += writeblob(fd, globls, strtab, n->expr.args[i]);
+ break;
+ case Ostruct:
+ sz = writestruct(fd, globls, strtab, n);
+ break;
+ case Olit:
+ sz = writelit(fd, strtab, n->expr.args[0], exprtype(n));
+ break;
+ case Oslice:
+ sz = writeslice(fd, globls, strtab, n);
+ break;
+ default:
+ dump(n, stdout);
+ die("Nonliteral initializer for global");
+ break;
+ }
+ return sz;
+}
+
+void genstrings(FILE *fd, Htab *strtab)
+{
+ void **k;
+ Str *s;
+ size_t i, nk;
+
+ k = htkeys(strtab, &nk);
+ for (i = 0; i < nk; i++) {
+ s = k[i];
+ fprintf(fd, "%s:\n", (char*)htget(strtab, k[i]));
+ writebytes(fd, s->buf, s->len);
+ }
+}
+
+
+static void writeasm(FILE *fd, Isel *s, Func *fn)
+{
+ size_t i, j;
+
+ if (fn->isexport || !strcmp(fn->name, Symprefix "main"))
+ fprintf(fd, ".globl %s\n", fn->name);
+ fprintf(fd, "%s:\n", fn->name);
+ for (j = 0; j < s->cfg->nbb; j++) {
+ if (!s->bb[j])
+ continue;
+ for (i = 0; i < s->bb[j]->nlbls; i++)
+ fprintf(fd, "%s:\n", s->bb[j]->lbls[i]);
+ for (i = 0; i < s->bb[j]->ni; i++)
+ iprintf(fd, s->bb[j]->il[i]);
+ }
+}
+
+void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
+{
+ char *lbl;
+
+ /* lits and such also get wrapped in decls */
+ assert(blob->type == Ndecl);
+
+ lbl = htget(globls, blob);
+ if (blob->decl.vis != Visintern)
+ fprintf(fd, ".globl %s\n", lbl);
+ fprintf(fd, "%s:\n", lbl);
+ if (blob->decl.init)
+ writeblob(fd, globls, strtab, blob->decl.init);
+ else
+ writepad(fd, size(blob));
+}
+
+/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
+ * natively supported, as promised in the output of reduce(). No 64-bit
+ * operations on x32, no structures, and so on. */
+void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
+{
+ Isel is = {0,};
+
+ is.reglocs = mkht(varhash, vareq);
+ is.stkoff = fn->stkoff;
+ is.globls = globls;
+ is.ret = fn->ret;
+ is.cfg = fn->cfg;
+
+ selfunc(&is, fn, globls, strtab);
+ if (debugopt['i'])
+ writeasm(stdout, &is, fn);
+ writeasm(fd, &is, fn);
+}
+
+void gengas(Node *file, char *out)
+{
+ Htab *globls, *strtab;
+ Node *n, **blob;
+ Func **fn;
+ size_t nfn, nblob;
+ size_t i;
+ FILE *fd;
+
+ /* ensure that all physical registers have a loc created before any
+ * other locs, so that locmap[Physreg] maps to the Loc for the physreg
+ * in question */
+ for (i = 0; i < Nreg; i++)
+ locphysreg(i);
+
+ fn = NULL;
+ nfn = 0;
+ blob = NULL;
+ nblob = 0;
+ globls = mkht(varhash, vareq);
+ initconsts(globls);
+
+ /* We need to define all global variables before use */
+ fillglobls(file->file.globls, globls);
+
+ pushstab(file->file.globls);
+ for (i = 0; i < file->file.nstmts; i++) {
+ n = file->file.stmts[i];
+ switch (n->type) {
+ case Nuse: /* nothing to do */
+ case Nimpl:
+ break;
+ case Ndecl:
+ simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
+ break;
+ default:
+ die("Bad node %s in toplevel", nodestr(n->type));
+ break;
+ }
+ }
+ popstab();
+
+ fd = fopen(out, "w");
+ if (!fd)
+ die("Couldn't open fd %s", out);
+
+ strtab = mkht(strlithash, strliteq);
+ fprintf(fd, ".data\n");
+ for (i = 0; i < nblob; i++)
+ genblob(fd, blob[i], globls, strtab);
+ fprintf(fd, ".text\n");
+ for (i = 0; i < nfn; i++)
+ genfunc(fd, fn[i], globls, strtab);
+ genstrings(fd, strtab);
+ fclose(fd);
+}
+
+void dbglocprint(FILE *fd, Loc *l, char spec)
+{
+ locprint(fd, l, spec);
+}
+
+void dbgiprintf(FILE *fd, Insn *i)
+{
+ iprintf(fd, i);
+}
--- /dev/null
+++ b/6/genp9.c
@@ -1,0 +1,550 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+#include "mi.h"
+#include "asm.h"
+#include "../config.h"
+
+/* string tables */
+static char *insnfmt[] = {
+#define Insn(val, gasfmt, p9fmt, use, def) p9fmt,
+#include "insns.def"
+#undef Insn
+};
+
+static char *regnames[] = {
+#define Reg(r, gasname, p9name, mode) p9name,
+#include "regs.def"
+#undef Reg
+};
+
+static char* modenames[] = {
+ [ModeB] = "B",
+ [ModeW] = "W",
+ [ModeL] = "L",
+ [ModeQ] = "Q",
+ [ModeF] = "S",
+ [ModeD] = "D"
+};
+
+static size_t writeblob(FILE *fd, char *name, size_t off, Htab *globls, Htab *strtab, Node *blob);
+static void locprint(FILE *fd, Loc *l, char spec);
+
+static void fillglobls(Stab *st, Htab *globls)
+{
+ void **k;
+ size_t i, nk;
+ Stab *stab;
+ Node *s;
+
+ k = htkeys(st->dcl, &nk);
+ for (i = 0; i < nk; i++) {
+ s = htget(st->dcl, k[i]);
+ htput(globls, s, asmname(s->decl.name));
+ }
+ free(k);
+
+ k = htkeys(st->ns, &nk);
+ for (i = 0; i < nk; i++) {
+ stab = htget(st->ns, k[i]);
+ fillglobls(stab, globls);
+ }
+ free(k);
+}
+
+static void initconsts(Htab *globls)
+{
+ Type *ty;
+ Node *name;
+ Node *dcl;
+
+ tyintptr = mktype(Zloc, Tyuint64);
+ tyword = mktype(Zloc, Tyuint);
+ tyvoid = mktype(Zloc, Tyvoid);
+
+ ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
+ name = mknsname(Zloc, "_rt", "abort_oob");
+ dcl = mkdecl(Zloc, name, ty);
+ dcl->decl.isconst = 1;
+ dcl->decl.isextern = 1;
+ htput(globls, dcl, asmname(dcl->decl.name));
+
+ abortoob = mkexpr(Zloc, Ovar, name, NULL);
+ abortoob->expr.type = ty;
+ abortoob->expr.did = dcl->decl.did;
+ abortoob->expr.isconst = 1;
+}
+
+static void printmem(FILE *fd, Loc *l, char spec)
+{
+ if (l->type == Locmem) {
+ if (l->mem.constdisp)
+ fprintf(fd, "%ld", l->mem.constdisp);
+ } else {
+ if (l->mem.lbldisp)
+ fprintf(fd, "%s", l->mem.lbldisp);
+ }
+ if (l->mem.base && l->mem.base->reg.colour != Rrip) {
+ fprintf(fd, "(");
+ locprint(fd, l->mem.base, 'r');
+ if (l->mem.idx) {
+ fprintf(fd, ",");
+ locprint(fd, l->mem.idx, 'r');
+ }
+ if (l->mem.scale > 1)
+ fprintf(fd, ",%d", l->mem.scale);
+ if (l->mem.base)
+ fprintf(fd, ")");
+ } else if (l->type != Locmeml) {
+ die("Only locmeml can have unspecified base reg");
+ }
+}
+
+static void locprint(FILE *fd, Loc *l, char spec)
+{
+ spec = tolower(spec);
+ assert(l->mode);
+ switch (l->type) {
+ case Loclitl:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%s", l->lbl);
+ break;
+ case Loclbl:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ fprintf(fd, "%s", l->lbl);
+ break;
+ case Locreg:
+ 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%s", l->reg.id, modenames[l->mode]);
+ else
+ fprintf(fd, "%s", regnames[l->reg.colour]);
+ break;
+ case Locmem:
+ case Locmeml:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ printmem(fd, l, spec);
+ break;
+ case Loclit:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%ld", l->lit);
+ break;
+ case Locnone:
+ die("Bad location in locprint()");
+ break;
+ }
+}
+
+static int issubreg(Loc *a, Loc *b)
+{
+ return rclass(a) == rclass(b) && a->mode != b->mode;
+}
+
+static void iprintf(FILE *fd, Insn *insn)
+{
+ char *p;
+ int i;
+ int modeidx;
+
+ /* x64 has a quirk; it has no movzlq because mov zero extends. This
+ * means that we need to do a movl when we really want a movzlq. Since
+ * we don't know the name of the reg to use, we need to sub it in when
+ * writing... */
+ switch (insn->op) {
+ case Imovzx:
+ if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
+ if (insn->args[1]->reg.colour) {
+ insn->op = Imov;
+ insn->args[1] = coreg(insn->args[1]->reg.colour, ModeL);
+ }
+ }
+ 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)
+ break;
+ /* if one reg is a subreg of another, we can just use the right
+ * mode to move between them. */
+ if (issubreg(insn->args[0], insn->args[1]))
+ insn->args[0] = coreg(insn->args[0]->reg.colour, insn->args[1]->mode);
+ /* moving a reg to itself is dumb. */
+ if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
+ return;
+ break;
+ default:
+ break;
+ }
+ p = insnfmt[insn->op];
+ i = 0;
+ modeidx = 0;
+ for (; *p; p++) {
+ if (*p != '%') {
+ fputc(*p, fd);
+ continue;
+ }
+
+ /* %-formating */
+ p++;
+ switch (*p) {
+ case '\0':
+ goto done; /* skip the final p++ */
+ case 'r': /* int register */
+ case 'f': /* float register */
+ case 'm': /* memory */
+ case 'i': /* imm */
+ case 'v': /* reg/mem */
+ case 'u': /* reg/imm */
+ case 'x': /* reg/mem/imm */
+ locprint(fd, insn->args[i], *p);
+ i++;
+ break;
+ case 'R': /* int register */
+ case 'F': /* float register */
+ case 'M': /* memory */
+ case 'I': /* imm */
+ case 'V': /* reg/mem */
+ case 'U': /* reg/imm */
+ case 'X': /* reg/mem/imm */
+ locprint(fd, insn->args[i], *p);
+ i++;
+ break;
+ case 't':
+ case 'T':
+ default:
+ /* the asm description uses 1-based indexing, so that 0
+ * can be used as a sentinel. */
+ if (isdigit(*p))
+ modeidx = strtol(p, &p, 10) - 1;
+
+ if (*p == 'T')
+ fputs(modenames[insn->args[modeidx]->mode], fd);
+ else
+ die("Invalid %%-specifier '%c'", *p);
+ break;
+ }
+ }
+done:
+ return;
+}
+
+
+static size_t writebytes(FILE *fd, char *name, size_t off, char *p, size_t sz)
+{
+ size_t i, len;
+
+ for (i = 0; i < sz; i++) {
+ len = min(i, 8);
+ if (i % 8 == 0)
+ fprintf(fd, "DATA %s+%zd(SB)/%zd,$\"", name, off + i, len);
+ if (p[i] == '"' || p[i] == '\\')
+ fprintf(fd, "\\");
+ if (isprint(p[i]))
+ fprintf(fd, "%c", p[i]);
+ else
+ fprintf(fd, "\\%03o", (uint8_t)p[i] & 0xff);
+ /* line wrapping for readability */
+ if (i % 8 == 7 || i == sz - 1)
+ fprintf(fd, "\"\n");
+ }
+
+ return sz;
+}
+
+static size_t writelit(FILE *fd, char *name, size_t off, Htab *strtab, Node *v, Type *ty)
+{
+ char buf[128];
+ char *lbl;
+ size_t sz;
+ union {
+ float fv;
+ double dv;
+ uint64_t qv;
+ uint32_t lv;
+ } u;
+
+ assert(v->type == Nlit);
+ sz = tysize(ty);
+ switch (v->lit.littype) {
+ case Lint:
+ fprintf(fd, "DATA %s+%zd(SB)/%zd,$%lld\n", name, off, sz, v->lit.intval);
+ break;
+ case Lbool:
+ fprintf(fd, "DATA %s+%zd(SB)/%zd,$%d\n", name, off, sz, v->lit.boolval);
+ break;
+ case Lchr:
+ fprintf(fd, "DATA %s+%zd(SB)/%zd,$%d\n", name, off, sz, v->lit.chrval);
+ break;
+ case Lflt:
+ if (tybase(v->lit.type)->type == Tyflt32) {
+ u.fv = v->lit.fltval;
+ fprintf(fd, "DATA %s+%zd(SB)/%zd, $0x%llx\n", name, off, sz, (vlong)u.lv);
+ } else if (tybase(v->lit.type)->type == Tyflt64) {
+ u.dv = v->lit.fltval;
+ fprintf(fd, "DATA %s+%zd(SB)/%zd, $0x%llx\n", name, off, sz, (vlong)u.qv);
+ }
+ break;
+ case Lstr:
+ if (hthas(strtab, &v->lit.strval)) {
+ lbl = htget(strtab, &v->lit.strval);
+ } else {
+ lbl = genlblstr(buf, sizeof buf);
+ htput(strtab, &v->lit.strval, strdup(lbl));
+ }
+ fprintf(fd, "DATA %s+%zd(SB)/8,%s<>+0(SB)\n", name, off, lbl);
+ fprintf(fd, "DATA %s+%zd(SB)/8,$%zd\n", name, off+8, v->lit.strval.len);
+ break;
+ case Lfunc:
+ die("Generating this shit ain't ready yet ");
+ break;
+ case Llbl:
+ die("Can't generate literal labels, ffs. They're not data.");
+ break;
+ }
+ return sz;
+}
+
+static size_t writepad(FILE *fd, size_t sz)
+{
+ assert((ssize_t)sz >= 0);
+ if (sz > 0)
+ fprintf(fd, "\t.fill %zd,1,0\n", sz);
+ return sz;
+}
+
+static size_t getintlit(Node *n, char *failmsg)
+{
+ if (exprop(n) != Olit)
+ fatal(n, "%s", failmsg);
+ n = n->expr.args[0];
+ if (n->lit.littype != Lint)
+ fatal(n, "%s", failmsg);
+ return n->lit.intval;
+}
+
+static size_t writeslice(FILE *fd, Htab *globls, Htab *strtab, Node *n)
+{
+ Node *base, *lo, *hi;
+ ssize_t loval, hival, sz;
+ char *lbl;
+
+ base = n->expr.args[0];
+ lo = n->expr.args[1];
+ hi = n->expr.args[2];
+
+ /* by this point, all slicing operations should have had their bases
+ * pulled out, and we should have vars with their pseudo-decls in their
+ * place */
+ if (exprop(base) != Ovar || !base->expr.isconst)
+ fatal(base, "slice base is not a constant value");
+ loval = getintlit(lo, "lower bound in slice is not constant literal");
+ hival = getintlit(hi, "upper bound in slice is not constant literal");
+ sz = tysize(tybase(exprtype(base))->sub[0]);
+
+ lbl = htget(globls, base);
+ fprintf(fd, "\t.quad %s + (%zd*%zd)\n", lbl, loval, sz);
+ fprintf(fd, "\t.quad %zd\n", (hival - loval));
+ return size(n);
+}
+
+static size_t writestruct(FILE *fd, char *name, size_t off, Htab *globls, Htab *strtab, Node *n)
+{
+ Type *t;
+ Node **dcl;
+ int found;
+ size_t i, j;
+ size_t pad, start, end;
+ size_t ndcl;
+
+ start = off;
+ t = tybase(exprtype(n));
+ assert(t->type == Tystruct);
+ dcl = t->sdecls;
+ ndcl = t->nmemb;
+ for (i = 0; i < ndcl; i++) {
+ pad = alignto(off, decltype(dcl[i]));
+ off += writepad(fd, pad - off);
+ found = 0;
+ for (j = 0; j < n->expr.nargs; j++)
+ if (!strcmp(namestr(n->expr.args[j]->expr.idx), declname(dcl[i]))) {
+ found = 1;
+ off += writeblob(fd, name, off, globls, strtab, n->expr.args[j]);
+ }
+ if (!found)
+ off += writepad(fd, size(dcl[i]));
+ }
+ end = alignto(off, t);
+ off += writepad(fd, end - off);
+ return off - start;
+}
+static size_t writeblob(FILE *fd, char *name, size_t off, Htab *globls, Htab *strtab, Node *n)
+{
+ size_t i, sz;
+
+ switch(exprop(n)) {
+ case Otup:
+ case Oarr:
+ sz = 0;
+ for (i = 0; i < n->expr.nargs; i++)
+ sz += writeblob(fd, name, off, globls, strtab, n->expr.args[i]);
+ break;
+ case Ostruct:
+ sz = writestruct(fd, name, off, globls, strtab, n);
+ break;
+ case Olit:
+ sz = writelit(fd, name, off, strtab, n->expr.args[0], exprtype(n));
+ break;
+ case Oslice:
+ sz = writeslice(fd, globls, strtab, n);
+ break;
+ default:
+ dump(n, stdout);
+ die("Nonliteral initializer for global");
+ break;
+ }
+ return sz;
+}
+
+static void genstrings(FILE *fd, Htab *strtab)
+{
+ void **k;
+ Str *s;
+ size_t i, nk;
+
+ k = htkeys(strtab, &nk);
+ for (i = 0; i < nk; i++) {
+ s = k[i];
+ writebytes(fd, htget(strtab, k[i]), 0, s->buf, s->len);
+ }
+}
+
+
+static void writeasm(FILE *fd, Isel *s, Func *fn)
+{
+ size_t i, j;
+ char *hidden;
+
+ hidden = "<>";
+ if (fn->isexport || streq(fn->name, Symprefix "main"))
+ hidden = "";
+ fprintf(fd, "TEXT %s%s+0(SB),$%zd\n", fn->name, hidden, fn->stksz);
+ for (j = 0; j < s->cfg->nbb; j++) {
+ if (!s->bb[j])
+ continue;
+ for (i = 0; i < s->bb[j]->nlbls; i++)
+ fprintf(fd, "%s:\n", s->bb[j]->lbls[i]);
+ for (i = 0; i < s->bb[j]->ni; i++)
+ iprintf(fd, s->bb[j]->il[i]);
+ }
+}
+
+static void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
+{
+ char *lbl;
+
+ /* lits and such also get wrapped in decls */
+ assert(blob->type == Ndecl);
+
+ lbl = htget(globls, blob);
+ if (blob->decl.vis != Visintern)
+ fprintf(fd, "GLOBL %s,%zd\n", lbl, size(blob));
+ if (blob->decl.init)
+ writeblob(fd, lbl, 0, globls, strtab, blob->decl.init);
+ else
+ writepad(fd, size(blob));
+}
+
+/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
+ * natively supported, as promised in the output of reduce(). No 64-bit
+ * operations on x32, no structures, and so on. */
+static void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
+{
+ Isel is = {0,};
+
+ is.reglocs = mkht(varhash, vareq);
+ is.stkoff = fn->stkoff;
+ is.globls = globls;
+ is.ret = fn->ret;
+ is.cfg = fn->cfg;
+
+ selfunc(&is, fn, globls, strtab);
+ if (debugopt['i'])
+ writeasm(stdout, &is, fn);
+ writeasm(fd, &is, fn);
+}
+
+void genp9(Node *file, char *out)
+{
+ Htab *globls, *strtab;
+ Node *n, **blob;
+ Func **fn;
+ size_t nfn, nblob;
+ size_t i;
+ FILE *fd;
+
+ /* ensure that all physical registers have a loc created before any
+ * other locs, so that locmap[Physreg] maps to the Loc for the physreg
+ * in question */
+ for (i = 0; i < Nreg; i++)
+ locphysreg(i);
+
+ fn = NULL;
+ nfn = 0;
+ blob = NULL;
+ nblob = 0;
+ globls = mkht(varhash, vareq);
+ initconsts(globls);
+
+ /* We need to define all global variables before use */
+ fillglobls(file->file.globls, globls);
+
+ pushstab(file->file.globls);
+ for (i = 0; i < file->file.nstmts; i++) {
+ n = file->file.stmts[i];
+ switch (n->type) {
+ case Nuse: /* nothing to do */
+ case Nimpl:
+ break;
+ case Ndecl:
+ simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
+ break;
+ default:
+ die("Bad node %s in toplevel", nodestr(n->type));
+ break;
+ }
+ }
+ popstab();
+
+ fd = fopen(out, "w");
+ if (!fd)
+ die("Couldn't open fd %s", out);
+
+ strtab = mkht(strlithash, strliteq);
+ for (i = 0; i < nblob; i++)
+ genblob(fd, blob[i], globls, strtab);
+ for (i = 0; i < nfn; i++)
+ genfunc(fd, fn[i], globls, strtab);
+ genstrings(fd, strtab);
+ fclose(fd);
+}
--- a/6/insns.def
+++ b/6/insns.def
@@ -28,7 +28,7 @@
/* Note, the mov instruction is specified in an overly general manner. */
Insn(Imov,
"\tmov%t %x,%x\n",
- "\tMOV%t %X,%X\n",
+ "\tMOV%T %X,%X\n",
Use(.l={1}),
Def(.l={2}))
Insn(Imovt,
@@ -38,7 +38,7 @@
Def(.l={2}))
Insn(Imovzx,
"\tmovz%1t%2t %x,%x\n",
- "\tMOVZ%1t%2t %X,%X\n",
+ "\tMOVZ%1T%2T %X,%X\n",
Use(.l={1}),
Def(.l={2}))
Insn(Imovsx,
@@ -347,9 +347,15 @@
Use(.r={Rrax,Rxmm0d}),
Def(None))
-/* not really an insn... */
+/* not actually insns */
Insn(Ilbl,
"%v:\n",
"%V:\n",
+ Use(None),
+ Def(None))
+
+Insn(Icomment,
+ "\t#%v\n",
+ "\t//%v:\n",
Use(None),
Def(None))
--- a/6/isel.c
+++ b/6/isel.c
@@ -150,7 +150,7 @@
va_end(ap);
if (debugopt['i']) {
printf("GEN[uid=%zd] ", i->uid);
- iprintf(stdout, i);
+ dbgiprintf(stdout, i);
}
lappend(&s->curbb->il, &s->curbb->ni, i);
}
@@ -868,9 +868,9 @@
for (i = 0; i < bb->nnl; i++) {
/* put in a comment that says where this line comes from */
n = bb->nl[i];
- snprintf(buf, sizeof buf, "\n\t# bb = %ld, bbidx = %ld, %s:%d",
+ snprintf(buf, sizeof buf, "bb = %ld, bbidx = %ld, %s:%d",
j, i, file->file.files[n->loc.file], n->loc.line);
- g(is, Ilbl, locstrlbl(buf), NULL);
+ g(is, Icomment, locstrlbl(buf), NULL);
isel(is, fn->cfg->bb[j]->nl[i]);
}
}
--- a/6/locs.c
+++ b/6/locs.c
@@ -16,52 +16,9 @@
#include "../config.h"
Mode regmodes[] = {
-#define Reg(r, name, mode) mode,
+#define Reg(r, gasname, p9name, mode) mode,
#include "regs.def"
#undef Reg
-};
-
-char *regnames[] = {
-#define Reg(r, name, mode) name,
-#include "regs.def"
-#undef Reg
-};
-
-size_t modesize[Nmode] = {
- [ModeNone] = 0,
- [ModeB] = 1,
- [ModeW] = 2,
- [ModeL] = 4,
- [ModeQ] = 8,
- [ModeF] = 4,
- [ModeD] = 8,
-};
-
-
-const Reg reginterferes[Nreg][Nmode + 1] = {
- /* byte */
- [Ral] = {Ral, Rax, Reax},
- [Rcl] = {Rcl, Rcx, Recx},
- [Rdl] = {Rdl, Rdx, Redx},
- [Rbl] = {Rbl, Rbx, Rebx},
-
- /* word */
- [Rax] = {Ral, Rax, Reax},
- [Rcx] = {Rcl, Rcx, Recx},
- [Rdx] = {Rdl, Rdx, Redx},
- [Rbx] = {Rbl, Rbx, Rebx},
- [Rsi] = {Rsi, Resi},
- [Rdi] = {Rdi, Redi},
-
- /* dword */
- [Reax] = {Ral, Rax, Reax},
- [Recx] = {Rcl, Rcx, Recx},
- [Redx] = {Rdl, Rdx, Redx},
- [Rebx] = {Rbl, Rbx, Rebx},
- [Resi] = {Rsi, Resi},
- [Redi] = {Rdi, Redi},
- [Resp] = {Resp},
- [Rebp] = {Rebp},
};
int isintmode(Mode m)
--- a/6/main.c
+++ b/6/main.c
@@ -46,7 +46,7 @@
printf("\t-S\tGenerate assembly instead of object code\n");
}
-static void assem(char *asmsrc, char *path)
+static void assemble(char *asmsrc, char *path)
{
char *asmcmd[] = Asmcmd;
char objfile[1024];
@@ -126,9 +126,11 @@
char buf[1024];
Stab *globls;
Optctx ctx;
+ Asmsyntax asmsyntax;
size_t i;
- optinit(&ctx, "d:hSo:I:", argv, argc);
+ optinit(&ctx, "d:hSo:I:9G", argv, argc);
+ asmsyntax = Defaultasm;
while (!optdone(&ctx)) {
switch (optnext(&ctx)) {
case 'o':
@@ -147,6 +149,12 @@
while (ctx.optarg && *ctx.optarg)
debugopt[*ctx.optarg++ & 0x7f]++;
break;
+ case '9':
+ asmsyntax = Plan9;
+ break;
+ case 'G':
+ asmsyntax = Gnugas;
+ break;
case 'I':
lappend(&incpaths, &nincpaths, ctx.optarg);
break;
@@ -180,8 +188,8 @@
} else {
gentemp(buf, sizeof buf, ctx.args[i], ".s");
}
- gen(file, buf);
- assem(buf, ctx.args[i]);
+ gen(asmsyntax, file, buf);
+ assemble(buf, ctx.args[i]);
genuse(ctx.args[i]);
}
--- a/6/ra.c
+++ b/6/ra.c
@@ -118,6 +118,17 @@
[Rxmm15f] = 31, [Rxmm15d] = 31,
};
+size_t modesize[Nmode] = {
+ [ModeNone] = 0,
+ [ModeB] = 1,
+ [ModeW] = 2,
+ [ModeL] = 4,
+ [ModeQ] = 8,
+ [ModeF] = 4,
+ [ModeD] = 8,
+};
+
+
static int _K[Nclass] = {
[Classbad] = 0,
[Classint] = 14,
@@ -943,11 +954,6 @@
found = 0;
for (i = 0; i < Northogonal; i++) {
if (regmap[i][n->mode] && !taken[i]) {
- if (debugopt['r']) {
- fprintf(stdout, "\tselecting ");
- locprint(stdout, n, 'x');
- fprintf(stdout, " = %s\n", regnames[regmap[i][n->mode]]);
- }
n->reg.colour = regmap[i][n->mode];
found = 1;
break;
@@ -1105,9 +1111,9 @@
lappend(&new, &nnew, insn);
if (debugopt['r']) {
printf("loading ");
- locprint(stdout, locmap[use[i].oldreg], 'x');
+ dbglocprint(stdout, locmap[use[i].oldreg], 'x');
printf(" -> ");
- locprint(stdout, use[i].newreg, 'x');
+ dbglocprint(stdout, use[i].newreg, 'x');
printf("\n");
}
}
@@ -1122,9 +1128,9 @@
lappend(&new, &nnew, insn);
if (debugopt['r']) {
printf("storing ");
- locprint(stdout, locmap[def[i].oldreg], 'x');
+ dbglocprint(stdout, locmap[def[i].oldreg], 'x');
printf(" -> ");
- locprint(stdout, def[i].newreg, 'x');
+ dbglocprint(stdout, def[i].newreg, 'x');
printf("\n");
}
}
@@ -1143,7 +1149,7 @@
s->stksz->lit = align(s->stksz->lit, modesize[l->mode]);
if (debugopt['r']) {
printf("spill ");
- locprint(stdout, l, 'x');
+ dbglocprint(stdout, l, 'x');
printf(" to %zd(%%rbp)\n", s->stksz->lit);
}
htput(s->spillslots, itop(l->reg.id), itop(s->stksz->lit));
@@ -1265,7 +1271,7 @@
fprintf(fd, "%s = [", name);
for (i = 0; i < nwl; i++) {
fprintf(fd, "%s", sep);
- locprint(fd, wl[i], 'x');
+ dbglocprint(fd, wl[i], 'x');
fprintf(fd, "(%zd)", wl[i]->reg.id);
sep = ",";
}
@@ -1296,7 +1302,7 @@
for (i = 0; i < bsmax(s); i++) {
if (bshas(s, i)) {
fprintf(fd, "%s", sep);
- locprint(fd, locmap[i], 'x');
+ dbglocprint(fd, locmap[i], 'x');
sep = ",";
}
}
@@ -1306,9 +1312,9 @@
static void printedge(FILE *fd, char *msg, size_t a, size_t b)
{
fprintf(fd, "\t%s ", msg);
- locprint(fd, locmap[a], 'x');
+ dbglocprint(fd, locmap[a], 'x');
fprintf(fd, " -- ");
- locprint(fd, locmap[b], 'x');
+ dbglocprint(fd, locmap[b], 'x');
fprintf(fd, "\n");
}
@@ -1360,7 +1366,7 @@
fprintf(fd, "Liveout: ");
locsetprint(fd, bb->liveout);
for (i = 0; i < bb->ni; i++)
- iprintf(fd, bb->il[i]);
+ dbgiprintf(fd, bb->il[i]);
}
fprintf(fd, "ENDASM -------- \n");
}
--- a/6/regs.def
+++ b/6/regs.def
@@ -1,117 +1,117 @@
-Reg(Rnone, "%NOREG", ModeB)
+Reg(Rnone, "%NOREG", "NOREG", ModeB)
/* byte regs */
-Reg(Ral, "%al", ModeB)
-Reg(Rcl, "%cl", ModeB)
-Reg(Rdl, "%dl", ModeB)
-Reg(Rbl, "%bl", ModeB)
-Reg(Rsil, "%sil", ModeB)
-Reg(Rdil, "%dil", ModeB)
-Reg(Rspl, "%spl", ModeB)
-Reg(Rbpl, "%bpl", ModeB)
-Reg(Rr8b, "%r8b", ModeB)
-Reg(Rr9b, "%r9b", ModeB)
-Reg(Rr10b, "%r10b", ModeB)
-Reg(Rr11b, "%r11b", ModeB)
-Reg(Rr12b, "%r12b", ModeB)
-Reg(Rr13b, "%r13b", ModeB)
-Reg(Rr14b, "%r14b", ModeB)
-Reg(Rr15b, "%r15b", ModeB)
+Reg(Ral, "%al", "AL", ModeB)
+Reg(Rcl, "%cl", "CL", ModeB)
+Reg(Rdl, "%dl", "DL", ModeB)
+Reg(Rbl, "%bl", "BL", ModeB)
+Reg(Rsil, "%sil", "SIL", ModeB)
+Reg(Rdil, "%dil", "DIL", ModeB)
+Reg(Rspl, "%spl", "SPL", ModeB)
+Reg(Rbpl, "%bpl", "BPL", ModeB)
+Reg(Rr8b, "%r8b", "BPL", ModeB)
+Reg(Rr9b, "%r9b", "BPL", ModeB)
+Reg(Rr10b, "%r10b", "R10", ModeB)
+Reg(Rr11b, "%r11b", "R11", ModeB)
+Reg(Rr12b, "%r12b", "R12", ModeB)
+Reg(Rr13b, "%r13b", "R13", ModeB)
+Reg(Rr14b, "%r14b", "R14", ModeB)
+Reg(Rr15b, "%r15b", "R15", ModeB)
/* high byte regs. We *NEVER* allocate these */
-Reg(Rah, "%ah", ModeB)
-Reg(Rch, "%ch", ModeB)
-Reg(Rdh, "%dh", ModeB)
-Reg(Rbh, "%bh", ModeB)
+Reg(Rah, "%ah", "AH", ModeB)
+Reg(Rch, "%ch", "CH", ModeB)
+Reg(Rdh, "%dh", "DH", ModeB)
+Reg(Rbh, "%bh", "BH", ModeB)
/* short regs */
-Reg(Rax, "%ax", ModeW)
-Reg(Rbx, "%bx", ModeW)
-Reg(Rcx, "%cx", ModeW)
-Reg(Rdx, "%dx", ModeW)
-Reg(Rsi, "%si", ModeW)
-Reg(Rdi, "%di", ModeW)
-Reg(Rsp, "%sp", ModeW)
-Reg(Rbp, "%bp", ModeW)
-Reg(Rr8w, "%r8w", ModeW)
-Reg(Rr9w, "%r9w", ModeW)
-Reg(Rr10w, "%r10w", ModeW)
-Reg(Rr11w, "%r11w", ModeW)
-Reg(Rr12w, "%r12w", ModeW)
-Reg(Rr13w, "%r13w", ModeW)
-Reg(Rr14w, "%r14w", ModeW)
-Reg(Rr15w, "%r15w", ModeW)
+Reg(Rax, "%ax", "AX", ModeW)
+Reg(Rbx, "%bx", "BX", ModeW)
+Reg(Rcx, "%cx", "CX", ModeW)
+Reg(Rdx, "%dx", "DX", ModeW)
+Reg(Rsi, "%si", "SI", ModeW)
+Reg(Rdi, "%di", "DI", ModeW)
+Reg(Rsp, "%sp", "SP", ModeW)
+Reg(Rbp, "%bp", "BP", ModeW)
+Reg(Rr8w, "%r8w", "R8", ModeW)
+Reg(Rr9w, "%r9w", "R9", ModeW)
+Reg(Rr10w, "%r10w", "R10", ModeW)
+Reg(Rr11w, "%r11w", "R11", ModeW)
+Reg(Rr12w, "%r12w", "R12", ModeW)
+Reg(Rr13w, "%r13w", "R13", ModeW)
+Reg(Rr14w, "%r14w", "R14", ModeW)
+Reg(Rr15w, "%r15w", "R15", ModeW)
/* long regs */
-Reg(Reax, "%eax", ModeL)
-Reg(Recx, "%ecx", ModeL)
-Reg(Redx, "%edx", ModeL)
-Reg(Rebx, "%ebx", ModeL)
-Reg(Resi, "%esi", ModeL)
-Reg(Redi, "%edi", ModeL)
-Reg(Resp, "%esp", ModeL)
-Reg(Rebp, "%ebp", ModeL)
-Reg(Rr8d, "%r8d", ModeL)
-Reg(Rr9d, "%r9d", ModeL)
-Reg(Rr10d, "%r10d", ModeL)
-Reg(Rr11d, "%r11d", ModeL)
-Reg(Rr12d, "%r12d", ModeL)
-Reg(Rr13d, "%r13d", ModeL)
-Reg(Rr14d, "%r14d", ModeL)
-Reg(Rr15d, "%r15d", ModeL)
+Reg(Reax, "%eax", "AX", ModeL)
+Reg(Recx, "%ecx", "BX", ModeL)
+Reg(Redx, "%edx", "CX", ModeL)
+Reg(Rebx, "%ebx", "DX", ModeL)
+Reg(Resi, "%esi", "SI", ModeL)
+Reg(Redi, "%edi", "DI", ModeL)
+Reg(Resp, "%esp", "SP", ModeL)
+Reg(Rebp, "%ebp", "BP", ModeL)
+Reg(Rr8d, "%r8d", "R8", ModeL)
+Reg(Rr9d, "%r9d", "R9", ModeL)
+Reg(Rr10d, "%r10d", "R10", ModeL)
+Reg(Rr11d, "%r11d", "R11", ModeL)
+Reg(Rr12d, "%r12d", "R12", ModeL)
+Reg(Rr13d, "%r13d", "R13", ModeL)
+Reg(Rr14d, "%r14d", "R14", ModeL)
+Reg(Rr15d, "%r15d", "R15", ModeL)
/* quad regs */
-Reg(Rrax, "%rax", ModeQ)
-Reg(Rrcx, "%rcx", ModeQ)
-Reg(Rrdx, "%rdx", ModeQ)
-Reg(Rrbx, "%rbx", ModeQ)
-Reg(Rrsi, "%rsi", ModeQ)
-Reg(Rrdi, "%rdi", ModeQ)
-Reg(Rr8, "%r8", ModeQ)
-Reg(Rr9, "%r9", ModeQ)
-Reg(Rr10, "%r10", ModeQ)
-Reg(Rr11, "%r11", ModeQ)
-Reg(Rr12, "%r12", ModeQ)
-Reg(Rr13, "%r13", ModeQ)
-Reg(Rr14, "%r14", ModeQ)
-Reg(Rr15, "%r15", ModeQ)
+Reg(Rrax, "%rax", "AX", ModeQ)
+Reg(Rrcx, "%rcx", "BX", ModeQ)
+Reg(Rrdx, "%rdx", "CX", ModeQ)
+Reg(Rrbx, "%rbx", "DX", ModeQ)
+Reg(Rrsi, "%rsi", "SI", ModeQ)
+Reg(Rrdi, "%rdi", "DI", ModeQ)
+Reg(Rrsp, "%rsp", "SP", ModeQ)
+Reg(Rrbp, "%rbp", "BP", ModeQ)
+Reg(Rr8, "%r8", "R8", ModeQ)
+Reg(Rr9, "%r9", "R9", ModeQ)
+Reg(Rr10, "%r10", "R10", ModeQ)
+Reg(Rr11, "%r11", "R11", ModeQ)
+Reg(Rr12, "%r12", "R12", ModeQ)
+Reg(Rr13, "%r13", "R13", ModeQ)
+Reg(Rr14, "%r14", "R14", ModeQ)
+Reg(Rr15, "%r15", "R15", ModeQ)
/* floating point registers */
-Reg(Rxmm0f, "%xmm0", ModeF)
-Reg(Rxmm1f, "%xmm1", ModeF)
-Reg(Rxmm2f, "%xmm2", ModeF)
-Reg(Rxmm3f, "%xmm3", ModeF)
-Reg(Rxmm4f, "%xmm4", ModeF)
-Reg(Rxmm5f, "%xmm5", ModeF)
-Reg(Rxmm6f, "%xmm6", ModeF)
-Reg(Rxmm7f, "%xmm7", ModeF)
-Reg(Rxmm8f, "%xmm8", ModeF)
-Reg(Rxmm9f, "%xmm9", ModeF)
-Reg(Rxmm10f, "%xmm10", ModeF)
-Reg(Rxmm11f, "%xmm11", ModeF)
-Reg(Rxmm12f, "%xmm12", ModeF)
-Reg(Rxmm13f, "%xmm13", ModeF)
-Reg(Rxmm14f, "%xmm14", ModeF)
-Reg(Rxmm15f, "%xmm15", ModeF)
+Reg(Rxmm0f, "%xmm0", "MM0", ModeF)
+Reg(Rxmm1f, "%xmm1", "MM1", ModeF)
+Reg(Rxmm2f, "%xmm2", "MM2", ModeF)
+Reg(Rxmm3f, "%xmm3", "MM3", ModeF)
+Reg(Rxmm4f, "%xmm4", "MM4", ModeF)
+Reg(Rxmm5f, "%xmm5", "MM5", ModeF)
+Reg(Rxmm6f, "%xmm6", "MM6", ModeF)
+Reg(Rxmm7f, "%xmm7", "MM7", ModeF)
+Reg(Rxmm8f, "%xmm8", "MM8", ModeF)
+Reg(Rxmm9f, "%xmm9", "MM9", ModeF)
+Reg(Rxmm10f, "%xmm10", "MM10", ModeF)
+Reg(Rxmm11f, "%xmm11", "MM11", ModeF)
+Reg(Rxmm12f, "%xmm12", "MM12", ModeF)
+Reg(Rxmm13f, "%xmm13", "MM13", ModeF)
+Reg(Rxmm14f, "%xmm14", "MM14", ModeF)
+Reg(Rxmm15f, "%xmm15", "MM15", ModeF)
/* double precision floating point registers */
-Reg(Rxmm0d, "%xmm0", ModeD)
-Reg(Rxmm1d, "%xmm1", ModeD)
-Reg(Rxmm2d, "%xmm2", ModeD)
-Reg(Rxmm3d, "%xmm3", ModeD)
-Reg(Rxmm4d, "%xmm4", ModeD)
-Reg(Rxmm5d, "%xmm5", ModeD)
-Reg(Rxmm6d, "%xmm6", ModeD)
-Reg(Rxmm7d, "%xmm7", ModeD)
-Reg(Rxmm8d, "%xmm8", ModeD)
-Reg(Rxmm9d, "%xmm9", ModeD)
-Reg(Rxmm10d, "%xmm10", ModeD)
-Reg(Rxmm11d, "%xmm11", ModeD)
-Reg(Rxmm12d, "%xmm12", ModeD)
-Reg(Rxmm13d, "%xmm13", ModeD)
-Reg(Rxmm14d, "%xmm14", ModeD)
-Reg(Rxmm15d, "%xmm15", ModeD)
+Reg(Rxmm0d, "%xmm0", "MM0", ModeD)
+Reg(Rxmm1d, "%xmm1", "MM1", ModeD)
+Reg(Rxmm2d, "%xmm2", "MM2", ModeD)
+Reg(Rxmm3d, "%xmm3", "MM3", ModeD)
+Reg(Rxmm4d, "%xmm4", "MM4", ModeD)
+Reg(Rxmm5d, "%xmm5", "MM5", ModeD)
+Reg(Rxmm6d, "%xmm6", "MM6", ModeD)
+Reg(Rxmm7d, "%xmm7", "MM7", ModeD)
+Reg(Rxmm8d, "%xmm8", "MM8", ModeD)
+Reg(Rxmm9d, "%xmm9", "MM9", ModeD)
+Reg(Rxmm10d, "%xmm10", "MM10", ModeD)
+Reg(Rxmm11d, "%xmm11", "MM11", ModeD)
+Reg(Rxmm12d, "%xmm12", "MM12", ModeD)
+Reg(Rxmm13d, "%xmm13", "MM13", ModeD)
+Reg(Rxmm14d, "%xmm14", "MM14", ModeD)
+Reg(Rxmm15d, "%xmm15", "MM15", ModeD)
-Reg(Rrip, "%rip", ModeQ)
-Reg(Rrsp, "%rsp", ModeQ)
-Reg(Rrbp, "%rbp", ModeQ)
+Reg(Rrip, "%rip", "PC", ModeQ)
--- a/configure
+++ b/configure
@@ -39,19 +39,19 @@
*Linux*)
echo '#define Asmcmd {"as", "-g", "-o", NULL}' >> config.h
echo '#define Symprefix ""' >> config.h
- echo '#define insnfmt gasinsnfmt' >> config.h
+ echo '#define Defaultasm Gnugas' >> config.h
echo 'export SYS=linux' >> config.mk
;;
*Darwin*)
echo '#define Asmcmd {"as", "-g", "-o", NULL}' >> config.h
echo '#define Symprefix "_"' >> config.h
- echo '#define insnfmt gasinsnfmt' >> config.h
+ echo '#define Defaultasm Gnugas' >> config.h
echo 'export SYS=osx' >> config.mk
;;
*FreeBSD*)
echo '#define Asmcmd {"as", "-g", "-o", NULL}' >> config.h
echo '#define Symprefix ""' >> config.h
- echo '#define insnfmt gasinsnfmt' >> config.h
+ echo '#define Defaultasm Gnugas' >> config.h
echo 'export SYS=freebsd' >> config.mk
;;
*)