shithub: mc

Download patch

ref: 24a3d753f2ac998c0b10579191984d79cfed0b7d
parent: 008887ccd998a43db6980fa57f1e210ec26c4acf
author: Ori Bernstein <[email protected]>
date: Sat Dec 13 18:21:11 EST 2014

Add plan9 instruction formats.

    Work towards a plan9 port. This commit also fixes a bug with
    strings that contain '\0'. The commits got tangled, and I'm
    too lazy to detangle them.

--- a/6/asm.h
+++ b/6/asm.h
@@ -14,7 +14,7 @@
 typedef struct Asmbb Asmbb;
 
 typedef enum {
-#define Insn(val, fmt, use, def) val,
+#define Insn(val, gasfmt, p9fmt, use, def) val,
 #include "insns.def"
 #undef Insn
 } AsmOp;
--- a/6/gen.c
+++ b/6/gen.c
@@ -15,13 +15,19 @@
 #include "../config.h"
 
 /* string tables */
-char *insnfmts[] = {
-#define Insn(val, fmt, use, def) fmt,
+char *gasinsnfmt[] = {
+#define Insn(val, gasfmt, p9fmt, use, def) gasfmt,
 #include "insns.def"
 #undef Insn
 };
 
-char* modenames[] = {
+char *p9insnfmt[] = {
+#define Insn(val, gasfmt, p9fmt, use, def) p9fmt,
+#include "insns.def"
+#undef Insn
+};
+
+char* gasmodenames[] = {
   [ModeB] = "b",
   [ModeW] = "w",
   [ModeL] = "l",
@@ -30,6 +36,14 @@
   [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);
 
@@ -78,8 +92,42 @@
     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:
@@ -97,7 +145,7 @@
                    spec == 'x' ||
                    spec == 'u');
             if (l->reg.colour == Rnone)
-                fprintf(fd, "%%P.%zd%s", l->reg.id, modenames[l->mode]);
+                fprintf(fd, "%%P.%zd%s", l->reg.id, gasmodenames[l->mode]);
             else
                 fprintf(fd, "%s", regnames[l->reg.colour]);
             break;
@@ -104,27 +152,10 @@
         case Locmem:
         case Locmeml:
             assert(spec == 'm' || spec == 'v' || spec == 'x');
-            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");
-            }
+            if (isp9)
+                p9printmem(fd, l, spec);
+            else
+                gasprintmem(fd, l, spec);
             break;
         case Loclit:
             assert(spec == 'i' || spec == 'x' || spec == 'u');
@@ -184,7 +215,7 @@
         default:
             break;
     }
-    p = insnfmts[insn->op];
+    p = insnfmt[insn->op];
     i = 0;
     modeidx = 0;
     for (; *p; p++) {
@@ -208,7 +239,18 @@
                 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. */
@@ -216,7 +258,9 @@
                     modeidx = strtol(p, &p, 10) - 1;
 
                 if (*p == 't')
-                    fputs(modenames[insn->args[modeidx]->mode], fd);
+                    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;
@@ -280,14 +324,14 @@
                 }
                 break;
         case Lstr:
-           if (hthas(strtab, v->lit.strval)) {
-               lbl = htget(strtab, v->lit.strval);
+           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));
+               htput(strtab, &v->lit.strval, strdup(lbl));
            }
            fprintf(fd, "\t.quad %s\n", lbl);
-           fprintf(fd, "\t.quad %zd\n", strlen(v->lit.strval));
+           fprintf(fd, "\t.quad %zd\n", v->lit.strval.len);
            break;
         case Lfunc:
             die("Generating this shit ain't ready yet ");
@@ -403,12 +447,14 @@
 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, k[i], strlen(k[i]));
+        writebytes(fd, s->buf, s->len);
     }
 }
 
@@ -512,7 +558,7 @@
     if (!fd)
         die("Couldn't open fd %s", out);
 
-    strtab = mkht(strhash, streq);
+    strtab = mkht(strlithash, strliteq);
     fprintf(fd, ".data\n");
     for (i = 0; i < nblob; i++)
         genblob(fd, blob[i], globls, strtab);
--- a/6/insns.def
+++ b/6/insns.def
@@ -13,86 +13,343 @@
                         preceeding it is the operand desired for
                         the mode.
     Currently, there aren't any attrs, because none were needed yet.
-    Eventually, they'll probably include flag setting and so on.
+    Eventually, they'll probably include flag setting and so on. The
+    upper case versions of these indicate Plan9 location formatting.
 
     For technical reasons, the indexing on use and def statments is 1-based,
     instead of 0-based. (0 is the sentinel value).
 */
 #define None .l={0},.r={0}
-Insn(Inone,     "BAD_INSN",                     Use(None), Def(None))
+Insn(Inone,     
+    "BAD_INSN",                     
+    "BAD_INSN",
+    Use(None),
+    Def(None))
 /* 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(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(None))
-Insn(Irepmovsw, "\trep movsw\n",                Use(.r={Rrcx,Rrsi,Rrdi}),       Def(None))
-Insn(Irepmovsl, "\trep movsl\n",                Use(.r={Rrcx,Rrsi,Rrdi}),       Def(None))
-Insn(Irepmovsq, "\trep movsq\n",                Use(.r={Rrcx,Rrsi,Rrdi}),       Def(None))
-Insn(Ilea,      "\tlea%2t %m,%r\n",             Use(.l={1}),                    Def(.l={2}))
+Insn(Imov,      
+    "\tmov%t %x,%x\n",              
+    "\tMOV%t %X,%X\n",
+    Use(.l={1}),
+    Def(.l={2}))
+Insn(Imovt,      
+    "PSEUDO: TRUNCATE\n",          
+    "PSEUDO: TRUNCATE\n",
+    Use(.l={1}),
+    Def(.l={2}))
+Insn(Imovzx,    
+    "\tmovz%1t%2t %x,%x\n",         
+    "\tMOVZ%1t%2t %X,%X\n",
+    Use(.l={1}),
+    Def(.l={2}))
+Insn(Imovsx,    
+    "\tmovs%1t%2t %x,%x\n",         
+    "\tMOVS%1T%2T %X,%X\n",
+    Use(.l={1}),
+    Def(.l={2}))
+Insn(Irepmovsb, 
+    "\trep movsb\n",                
+    "\tREP MOVSB\n",
+    Use(.r={Rrcx,Rrsi,Rrdi}),
+    Def(None))
+Insn(Irepmovsw, 
+    "\trep movsw\n",                
+    "\tREP MOVSW\n",
+    Use(.r={Rrcx,Rrsi,Rrdi}),
+    Def(None))
+Insn(Irepmovsl, 
+    "\trep movsl\n",                
+    "\tREP MOVSL\n",
+    Use(.r={Rrcx,Rrsi,Rrdi}),
+    Def(None))
+Insn(Irepmovsq, 
+    "\trep movsq\n",                
+    "\tREP MOVSQ\n",
+    Use(.r={Rrcx,Rrsi,Rrdi}),
+    Def(None))
+Insn(Ilea,      
+    "\tlea%2t %m,%r\n",             
+    "\tLEA%2T %M,%R\n",
+    Use(.l={1}),
+    Def(.l={2}))
 
-Insn(Iadd,      "\tadd%t %x,%r\n",              Use(.l={1,2}),                  Def(.l={2}))
-Insn(Isub,      "\tsub%t %x,%r\n",              Use(.l={1,2}),                  Def(.l={2}))
-Insn(Iimul,     "\timul%t %x,%r\n",             Use(.l={1,2}),                  Def(.l={2}))
+Insn(Iadd,      
+    "\tadd%t %x,%r\n",              
+    "\tADD%T %X,%R\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Isub,      
+    "\tsub%t %x,%r\n",              
+    "\tSUB%T %X,%R\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Iimul,     
+    "\timul%t %x,%r\n",             
+    "\tIMUL%T %X,%R\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
 /* there is no imul for 8 bit values. */
-Insn(Iimul_r,   "\timul%t %r\n",                Use(.l={1},.r={Ral}),           Def(.r={Rax}))
-Insn(Imul,      "\tmul%t %r\n",                 Use(.l={1},.r={Reax}),          Def(.r={Reax,Redx}))
-Insn(Idiv,      "\tdiv%t %r\n",                 Use(.l={1},.r={Reax,Redx}),     Def(.r={Reax,Redx}))
-Insn(Ineg,      "\tneg%t %r\n",                 Use(.l={1}),                    Def(.l={1}))
-Insn(Iand,      "\tand%t %x,%r\n",              Use(.l={1,2}),                  Def(.l={2}))
-Insn(Ior,       "\tor%t  %x,%r\n",              Use(.l={1,2}),                  Def(.l={2}))
-Insn(Ixor,      "\txor%t %x,%r\n",              Use(.l={1,2}),                  Def(.l={2}))
-Insn(Inot,      "\tnot%t %v\n",                 Use(.l={1}),                    Def(.l={1}))
-Insn(Ishl,      "\tsal%2t %u,%r\n",             Use(.l={1,2}),                  Def(.l={2}))
-Insn(Isar,      "\tsar%2t %u,%r\n",             Use(.l={1,2}),                  Def(.l={2}))
-Insn(Ishr,      "\tshr%2t %u,%r\n",             Use(.l={1,2}),                  Def(.l={2}))
+Insn(Iimul_r,
+    "\timul%t %r\n",                
+    "\tIMUL%T %R\n",
+    Use(.l={1},.r={Ral}),
+    Def(.r={Rax}))
+Insn(Imul,      
+    "\tmul%t %r\n",                 
+    "\tMUL%T %R\n",
+    Use(.l={1},.r={Reax}),
+    Def(.r={Reax,Redx}))
+Insn(Idiv,      
+    "\tdiv%t %r\n",                 
+    "\tDIV%T %R\n",
+    Use(.l={1},.r={Reax,Redx}),
+    Def(.r={Reax,Redx}))
+Insn(Ineg,      
+    "\tneg%t %r\n",                 
+    "\tNEG%T %R\n",
+    Use(.l={1}),
+    Def(.l={1}))
+Insn(Iand,      
+    "\tand%t %x,%r\n",              
+    "\tAND%T %X,%R\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Ior,       
+    "\tor%t  %x,%r\n",              
+    "\tOR%T  %X,%R\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Ixor,      
+    "\txor%t %x,%r\n",              
+    "\tXOR%T %X,%R\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Inot,      
+    "\tnot%t %v\n",                 
+    "\tNOT%T %V\n",
+    Use(.l={1}),
+    Def(.l={1}))
+Insn(Ishl,      
+    "\tsal%2t %u,%r\n",             
+    "\tSAL%2T %U,%R\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Isar,      
+    "\tsar%2t %u,%r\n",             
+    "\tSAR%2T %U,%R\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Ishr,      
+    "\tshr%2t %u,%r\n",             
+    "\tSHR%2T %U,%R\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
 
-Insn(Itest,     "\ttest%t %x,%r\n",             Use(.l={1,2}),                  Def(None))
-Insn(Icmp,      "\tcmp%t  %x,%r\n",             Use(.l={1,2}),                  Def(None))
+Insn(Itest,     
+    "\ttest%t %x,%r\n",             
+    "\tTEST%T %X,%R\n",
+    Use(.l={1,2}),
+    Def(None))
+Insn(Icmp,      
+    "\tcmp%t  %x,%r\n",             
+    "\tCMP%T  %X,%R\n",
+    Use(.l={1,2}),
+    Def(None))
 
-Insn(Ipush,     "\tpush%t %r\n",                Use(.l={1}),                    Def(None))
-Insn(Ipop,      "\tpop%t %r\n",                 Use(.l={1}),                    Def(None))
+Insn(Ipush,     
+    "\tpush%t %r\n",                
+    "\tPUSH%T %R\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ipop,      
+    "\tpop%t %r\n",                 
+    "\tPOP%T %R\n",
+    Use(.l={1}),
+    Def(None))
 
 /* branch instructions */
-Insn(Isetz,     "\tsetz  %v\n",                 Use(None),  Def(.l={1}))
-Insn(Isetnz,    "\tsetnz %v\n",                 Use(None),  Def(.l={1}))
-Insn(Isetl,     "\tsetl  %v\n",                 Use(None),  Def(.l={1}))
-Insn(Isetle,    "\tsetle %v\n",                 Use(None),  Def(.l={1}))
-Insn(Isetg,     "\tsetg %v\n",                  Use(None),  Def(.l={1}))
-Insn(Isetge,    "\tsetge %v\n",                 Use(None),  Def(.l={1}))
-Insn(Isetb,     "\tsetb  %v\n",                 Use(None),  Def(.l={1}))
-Insn(Isetbe,    "\tsetbe %v\n",                 Use(None),  Def(.l={1}))
-Insn(Iseta,     "\tseta %v\n",                  Use(None),  Def(.l={1}))
-Insn(Isetae,    "\tsetae %v\n",                 Use(None),  Def(.l={1}))
+Insn(Isetz,     
+    "\tsetz  %v\n",                 
+    "\tSETZ  %V\n",
+    Use(None),
+    Def(.l={1}))
+Insn(Isetnz,    
+    "\tsetnz %v\n",                 
+    "\tSETNZ %V\n",
+    Use(None),
+    Def(.l={1}))
+Insn(Isetl,     
+    "\tsetl  %v\n",                 
+    "\tSETL  %V\n",
+    Use(None),
+    Def(.l={1}))
+Insn(Isetle,    
+    "\tsetle %v\n",                 
+    "\tSETLE %V\n",
+    Use(None),
+    Def(.l={1}))
+Insn(Isetg,     
+    "\tsetg %v\n",                  
+    "\tSETG %V\n",
+    Use(None),
+    Def(.l={1}))
+Insn(Isetge,    
+    "\tsetge %v\n",                 
+    "\tSETGE %V\n",
+    Use(None),
+    Def(.l={1}))
+Insn(Isetb,     
+    "\tsetb  %v\n",                 
+    "\tSETB  %V\n",
+    Use(None),
+    Def(.l={1}))
+Insn(Isetbe,    
+    "\tsetbe %v\n",                 
+    "\tSETBE %V\n",
+    Use(None),
+    Def(.l={1}))
+Insn(Iseta,     
+    "\tseta %v\n",                  
+    "\tSETA %V\n",
+    Use(None),
+    Def(.l={1}))
+Insn(Isetae,    
+    "\tsetae %v\n",                 
+    "\tSETAE %V\n",
+    Use(None),
+    Def(.l={1}))
 
 /* fp specific instructions */
-Insn(Imovs,      "\tmovs%1t %x,%x\n",           Use(.l={1}),                    Def(.l={2}))
-Insn(Icvttsd2si, "\tcvttsd2si%2t %x,%r\n",      Use(.l={1}),                    Def(.l={2}))
-Insn(Icvttsi2sd, "\tcvttsi2sd%2t %x,%f\n",      Use(.l={1}),                    Def(.l={2}))
-Insn(Icvttsd2ss, "\tcvtsd2ss %x,%f\n",          Use(.l={1}),                    Def(.l={2}))
-Insn(Icvttss2sd, "\tcvtss2sd %x,%f\n",          Use(.l={1}),                    Def(.l={2}))
-Insn(Iadds,      "\tadds%t %x,%f\n",            Use(.l={1,2}),                  Def(.l={2}))
-Insn(Isubs,      "\tsubs%t %x,%f\n",            Use(.l={1,2}),                  Def(.l={2}))
-Insn(Imuls,      "\tmuls%t %x,%f\n",            Use(.l={1,2}),                  Def(.l={2}))
-Insn(Idivs,      "\tdivs%t %x,%f\n",            Use(.l={1,2}),                  Def(.l={2}))
-Insn(Icomis,     "\tcomis%t %x,%f\n",           Use(.l={1,2}),                  Def(None))
-Insn(Ixorp,      "\tmuls%t %x,%f\n",            Use(.l={1,2}),                  Def(.l={2}))
+Insn(Imovs,      
+    "\tmovs%1t %x,%x\n",           
+    "\tMOVS%1T %X,%X\n",
+    Use(.l={1}),
+    Def(.l={2}))
+Insn(Icvttsd2si, 
+    "\tcvttsd2si%2t %x,%r\n",      
+    "\tCVTTSD2SI%2T %X,%R\n",
+    Use(.l={1}),
+    Def(.l={2}))
+Insn(Icvttsi2sd, 
+    "\tcvttsi2sd%2t %x,%f\n",      
+    "\tCVTTSI2SD%2T %X,%F\n",
+    Use(.l={1}),
+    Def(.l={2}))
+Insn(Icvttsd2ss, 
+    "\tcvtsd2ss %x,%f\n",          
+    "\tCVTSD2SS %X,%F\n",
+    Use(.l={1}),
+    Def(.l={2}))
+Insn(Icvttss2sd, 
+    "\tcvtss2sd %x,%f\n",          
+    "\tCVTSS2SD %X,%F\n",
+    Use(.l={1}),
+    Def(.l={2}))
+Insn(Iadds,      
+    "\tadds%t %x,%f\n",            
+    "\tADDS%T %X,%F\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Isubs,      
+    "\tsubs%t %x,%f\n",            
+    "\tSUBS%T %X,%F\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Imuls,      
+    "\tmuls%t %x,%f\n",            
+    "\tMULS%T %X,%F\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Idivs,      
+    "\tdivs%t %x,%f\n",            
+    "\tDIVS%T %X,%F\n",
+    Use(.l={1,2}),
+    Def(.l={2}))
+Insn(Icomis,     
+    "\tcomis%t %x,%f\n",           
+    "\tCOMIS%T %X,%F\n",
+    Use(.l={1,2}),
+    Def(None))
+Insn(Ixorp,      
+    "\tmuls%t %x,%f\n",            
+    "\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,Reax,Rax,Ral,Rah}))
-Insn(Icallind,  "\tcall *%v\n",                 Use(.l={1}), Def(.r={Rrax,Reax,Rax,Ral,Rah}))
-Insn(Ijmp,      "\tjmp %v\n",                   Use(.l={1}), Def(None))
-Insn(Ijz,       "\tjz %v\n",                    Use(.l={1}), Def(None))
-Insn(Ijnz,      "\tjnz %v\n",                   Use(.l={1}), Def(None))
-Insn(Ijl,       "\tjl %v\n",                    Use(.l={1}), Def(None))
-Insn(Ijle,      "\tjle %v\n",                   Use(.l={1}), Def(None))
-Insn(Ijg,       "\tjg %v\n",                    Use(.l={1}), Def(None))
-Insn(Ijge,      "\tjge %v\n",                   Use(.l={1}), Def(None))
-Insn(Ijb,       "\tjb %v\n",                    Use(.l={1}), Def(None))
-Insn(Ijbe,      "\tjbe %v\n",                   Use(.l={1}), Def(None))
-Insn(Ija,       "\tja %v\n",                    Use(.l={1}), Def(None))
-Insn(Ijae,      "\tjae %v\n",                   Use(.l={1}), Def(None))
-Insn(Iret,      "\tret\n",                      Use(.r={Rrax,Rxmm0d}), Def(None))
+Insn(Icall,     
+    "\tcall %v\n",                  
+    "\tCALL %V\n",
+    Use(.l={1}),
+    Def(.r={Rrax,Reax,Rax,Ral,Rah}))
+Insn(Icallind,  
+    "\tcall *%v\n",                 
+    "\tCALL *%V\n",
+    Use(.l={1}),
+    Def(.r={Rrax,Reax,Rax,Ral,Rah}))
+Insn(Ijmp,      
+    "\tjmp %v\n",                   
+    "\tJMP %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ijz,       
+    "\tjz %v\n",                    
+    "\tJZ %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ijnz,      
+    "\tjnz %v\n",                   
+    "\tJNZ %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ijl,       
+    "\tjl %v\n",                    
+    "\tJL %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ijle,      
+    "\tjle %v\n",                   
+    "\tJLE %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ijg,       
+    "\tjg %v\n",                    
+    "\tJG %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ijge,      
+    "\tjge %v\n",                   
+    "\tJGE %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ijb,       
+    "\tjb %v\n",                    
+    "\tJB %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ijbe,      
+    "\tjbe %v\n",                   
+    "\tJBE %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ija,       
+    "\tja %v\n",                    
+    "\tJA %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Ijae,      
+    "\tjae %v\n",                   
+    "\tJAE %V\n",
+    Use(.l={1}),
+    Def(None))
+Insn(Iret,      
+    "\tret\n",                      
+    "\tRET\n",
+    Use(.r={Rrax,Rxmm0d}),
+    Def(None))
 
 /* not really an insn... */
-Insn(Ilbl,      "%v:\n",                        Use(None), Def(None))
+Insn(Ilbl,      
+    "%v:\n",                        
+    "%V:\n",
+    Use(None),
+    Def(None))
--- a/6/main.c
+++ b/6/main.c
@@ -23,6 +23,7 @@
 char debugopt[128];
 int writeasm;
 int extracheck;
+int p9asm;
 char *outfile;
 char **incpaths;
 size_t nincpaths;
--- a/6/ra.c
+++ b/6/ra.c
@@ -26,7 +26,7 @@
 Usemap usetab[] = {
 #define Def(...)
 #define Use(...) {__VA_ARGS__}
-#define Insn(i, fmt, use, def) use,
+#define Insn(i, gasfmt, p9fmt, use, def) use,
 #include "insns.def"
 #undef Insn
 #undef Use
@@ -36,7 +36,7 @@
 Usemap deftab[] = {
 #define Use(...)
 #define Def(...) {__VA_ARGS__}
-#define Insn(i, fmt, use, def) def,
+#define Insn(i, gasfmt, p9fmt, use, def) def,
 #include "insns.def"
 #undef Insn
 #undef Def
--- a/6/simp.c
+++ b/6/simp.c
@@ -567,12 +567,12 @@
             lit = pat->expr.args[0];
             if (exprop(pat) != Olit || lit->lit.littype != Lstr)
                 die("Unsupported pattern");
-            str = lit->lit.strval;
+            str = lit->lit.strval.buf;
+            len = lit->lit.strval.len;
 
             /* load slice length */
             next = genlbl(pat->loc);
             x = slicelen(s, val);
-            len = strlen(str);
             y = mkintlit(lit->loc, len);
             y->expr.type = tyintptr;
             v = mkexpr(pat->loc, Oeq, x, y, NULL);
--- a/configure
+++ b/configure
@@ -39,16 +39,19 @@
     *Linux*)
         echo '#define Asmcmd {"as", "-g", "-o", NULL}' >> config.h
         echo '#define Symprefix ""' >> config.h
+        echo '#define insnfmt gasinsnfmt' >> 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 '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 'export SYS=freebsd' >> config.mk
         ;;
     *)
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -202,7 +202,7 @@
                 case Lbool:     fprintf(fd, " Lbool %s\n", n->lit.boolval ? "true" : "false"); break;
                 case Lint:      fprintf(fd, " Lint %llu\n", n->lit.intval); break;
                 case Lflt:      fprintf(fd, " Lflt %lf\n", n->lit.fltval); break;
-                case Lstr:      fprintf(fd, " Lstr %s\n", n->lit.strval); break;
+                case Lstr:      fprintf(fd, " Lstr %s\n", n->lit.strval.buf); break;
                 case Llbl:      fprintf(fd, " Llbl %s\n", n->lit.lblval); break;
                 case Lfunc:
                     fprintf(fd, " Lfunc\n");
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -253,7 +253,7 @@
 attrs   : /* empty */ {$$.nstr = 0; $$.str = NULL;}
         | Tattr attrs {
                 $$ = $2;
-                lappend(&$$.str, &$$.nstr, strdup($1->str));
+                lappend(&$$.str, &$$.nstr, strdup($1->id));
             }
         ;
 
@@ -267,8 +267,8 @@
             }
         ;
 
-use     : Tuse Tident {$$ = mkuse($1->loc, $2->str, 0);}
-        | Tuse Tstrlit {$$ = mkuse($1->loc, $2->str, 1);}
+use     : Tuse Tident {$$ = mkuse($1->loc, $2->id, 0);}
+        | Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);}
         ;
 
 optident: Tident      {$$ = $1;}
@@ -279,8 +279,8 @@
                 if (file->file.exports->name)
                     lfatal($1->loc, "Package already declared\n");
                 if ($2) {
-                    updatens(file->file.exports, $2->str);
-                    updatens(file->file.globls, $2->str);
+                    updatens(file->file.exports, $2->id);
+                    updatens(file->file.globls, $2->id);
                 }
             }
         ;
@@ -339,8 +339,8 @@
         : name Tcolon type {$$ = mkdecl($1->loc, $1, $3);}
         ;
 
-name    : Tident {$$ = mkname($1->loc, $1->str);}
-        | Tident Tdot name {$$ = $3; setns($3, $1->str);}
+name    : Tident {$$ = mkname($1->loc, $1->id);}
+        | Tident Tdot name {$$ = $3; setns($3, $1->id);}
         ;
 
 implstmt: Timpl name type {
@@ -357,7 +357,7 @@
         | implbody Tident Tasn exprln optendlns {
                 Node *d;
                 $$ = $1;
-                d = mkdecl($2->loc, mkname($2->loc, $2->str), mktyvar($2->loc));
+                d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc));
                 d->decl.init = $4;
                 d->decl.isconst = 1;
                 lappend(&$$.nl, &$$.nn, d);
@@ -365,11 +365,11 @@
         ;
 
 traitdef: Ttrait Tident generictype /* trait prototype */ {
-                $$ = mktrait($1->loc, mkname($2->loc, $2->str), $3, NULL, 0, NULL, 0, 1);
+                $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, NULL, 0, 1);
             }
         | Ttrait Tident generictype Tasn traitbody Tendblk /* trait definition */ {
                 size_t i;
-                $$ = mktrait($1->loc, mkname($2->loc, $2->str), $3, NULL, 0, $5.nl, $5.nn, 0);
+                $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, NULL, 0, $5.nl, $5.nn, 0);
                 for (i = 0; i < $5.nn; i++) {
                     $5.nl[i]->decl.trait = $$;
                     $5.nl[i]->decl.isgeneric = 1;
@@ -382,7 +382,7 @@
         | traitbody Tident Tcolon type optendlns {
                 Node *d;
                 $$ = $1;
-                d = mkdecl($2->loc, mkname($2->loc, $2->str), $4);
+                d = mkdecl($2->loc, mkname($2->loc, $2->id), $4);
                 d->decl.isgeneric = 1;
                 lappend(&$$.nl, &$$.nn, d);
             }
@@ -398,13 +398,13 @@
 
 typeid  : Tident {
                 $$.loc = $1->loc;
-                $$.name = $1->str;
+                $$.name = $1->id;
                 $$.params = NULL;
                 $$.type = NULL;
             }
         | Tident Toparen typarams Tcparen {
                 $$.loc = $1->loc;
-                $$.name = $1->str;
+                $$.name = $1->id;
                 $$.params = $3.types;
                 $$.nparams = $3.ntypes;
                 $$.type = NULL;
@@ -427,14 +427,14 @@
         ;
 
 generictype
-        : Ttyparam {$$ = mktyparam($1->loc, $1->str);}
+        : Ttyparam {$$ = mktyparam($1->loc, $1->id);}
         | Ttyparam Twith name {
-                $$ = mktyparam($1->loc, $1->str);
+                $$ = mktyparam($1->loc, $1->id);
                 addtrait($$, $3->name.name);
             }
         | Ttyparam Twith Toparen typaramlist Tcparen {
                 size_t i;
-                $$ = mktyparam($1->loc, $1->str);
+                $$ = mktyparam($1->loc, $1->id);
                 for (i = 0; i < $4.nn; i++)
                     addtrait($$, $4.nl[i]->name.name);
             }
@@ -453,7 +453,7 @@
         | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
         | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
         | type Tderef {$$ = mktyptr($2->loc, $1);}
-        | Tat Tident {$$ = mktyparam($1->loc, $2->str);}
+        | Tat Tident {$$ = mktyparam($1->loc, $2->id);}
         | name       {$$ = mktyunres($1->loc, $1, NULL, 0);}
         | name Toparen typelist Tcparen {$$ = mktyunres($1->loc, $1, $3.types, $3.ntypes);}
         ;
@@ -539,7 +539,7 @@
         | Tendln {$$ = NULL;}
         ;
 
-goto    : Tgoto Tident {$$ = mkexpr($1->loc, Ojmp, mklbl($2->loc, $2->str), NULL);}
+goto    : Tgoto Tident {$$ = mkexpr($1->loc, Ojmp, mklbl($2->loc, $2->id), NULL);}
         ;
 
 retexpr : Tret expr {$$ = mkexpr($1->loc, Oret, $2, NULL);}
@@ -659,7 +659,7 @@
 
 postfixexpr
         : postfixexpr Tdot Tident
-            {$$ = mkexpr($1->loc, Omemb, $1, mkname($3->loc, $3->str), NULL);}
+            {$$ = mkexpr($1->loc, Omemb, $1, mkname($3->loc, $3->id), NULL);}
         | postfixexpr Tinc
             {$$ = mkexpr($1->loc, Opostinc, $1, NULL);}
         | postfixexpr Tdec
@@ -685,7 +685,7 @@
 
 atomicexpr
         : Tident
-            {$$ = mkexpr($1->loc, Ovar, mkname($1->loc, $1->str), NULL);}
+            {$$ = mkexpr($1->loc, Ovar, mkname($1->loc, $1->id), NULL);}
         | literal
         | Toparen expr Tcparen
             {$$ = $2;}
@@ -719,10 +719,10 @@
 tuplit  : Toparen tupbody Tcparen
             {$$ = mkexprl($1->loc, Otup, $2.nl, $2.nn);}
 
-littok  : Tstrlit       {$$ = mkstr($1->loc, $1->str);}
+littok  : Tstrlit       {$$ = mkstr($1->loc, $1->strval);}
         | Tchrlit       {$$ = mkchar($1->loc, $1->chrval);}
         | Tfloatlit     {$$ = mkfloat($1->loc, $1->fltval);}
-        | Tboollit      {$$ = mkbool($1->loc, !strcmp($1->str, "true"));}
+        | Tboollit      {$$ = mkbool($1->loc, !strcmp($1->id, "true"));}
         | Tintlit {
                 $$ = mkint($1->loc, $1->intval);
                 if ($1->inttype)
@@ -778,7 +778,7 @@
         ;
 
 structelt: optendlns Tdot Tident Tasn expr optendlns
-            {$$ = mkidxinit($2->loc, mkname($3->loc, $3->str), $5);}
+            {$$ = mkidxinit($2->loc, mkname($3->loc, $3->id), $5);}
          ;
 
 optendlns  : /* none */
@@ -882,7 +882,7 @@
         ;
 
 label   : Tcolon Tident
-            {$$ = mklbl($2->loc, $2->str);}
+            {$$ = mklbl($2->loc, $2->id);}
         ;
 
 %%
--- a/parse/htab.c
+++ b/parse/htab.c
@@ -227,6 +227,39 @@
     return !strcmp(a, b);
 }
 
+ulong strlithash(void *_s)
+{
+    Str *s;
+    ulong h, g, i;
+
+    s = _s;
+    h = 0;
+    for (i = 0; i < s->len; i++) {
+        h = ((h << 4) + s->buf[i]);
+
+        if ((g = (h & 0xF0000000)))
+            h ^= (g >> 24);
+
+        h &= ~g;
+    }
+    return h;
+}
+
+int strliteq(void *_a, void *_b)
+{
+    Str *a, *b;
+
+    a = _a;
+    b = _b;
+    if (a == b)
+        return 1;
+    if (a == NULL || b == NULL)
+        return 0;
+    if (a->len != b->len)
+        return 0;
+    return !memcmp(a, b, a->len);
+}
+
 ulong ptrhash(void *key)
 {
     return inthash((intptr_t)key);
--- a/parse/node.c
+++ b/parse/node.c
@@ -214,13 +214,15 @@
     return mkexpr(loc, Olit, n, NULL);
 }
 
-Node *mkstr(Srcloc loc, char *val)
+Node *mkstr(Srcloc loc, Str val)
 {
     Node *n;
 
     n = mknode(loc, Nlit);
     n->lit.littype = Lstr;
-    n->lit.strval = strdup(val);
+    n->lit.strval.len = val.len;
+    n->lit.strval.buf = malloc(val.len);
+    memcpy(n->lit.strval.buf, val.buf, val.len);
 
     return n;
 }
@@ -368,7 +370,8 @@
         case Lflt:
             return a->lit.fltval == b->lit.fltval;
         case Lstr:
-            return !strcmp(a->lit.strval, b->lit.strval);
+            return a->lit.strval.len == b->lit.strval.len &&
+                !memcmp(a->lit.strval.buf, b->lit.strval.buf, a->lit.strval.len);
         case Lfunc:
             return a->lit.fnval == b->lit.fnval;
         case Llbl:
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -15,6 +15,7 @@
 typedef struct Bitset Bitset;
 typedef struct Htab Htab;
 typedef struct Optctx Optctx;
+typedef struct Str Str;
 
 typedef struct Tok Tok;
 typedef struct Node Node;
@@ -64,6 +65,11 @@
     int file;
 };
 
+struct Str {
+    size_t len;
+    char *buf;
+};
+
 typedef enum {
     Visintern,
     Visexport,
@@ -95,7 +101,7 @@
 struct Tok {
     int type;
     Srcloc loc;
-    char *str;
+    char *id;
 
     /* values parsed out */
     vlong intval;
@@ -102,6 +108,7 @@
     Ty inttype; /* for explicitly specified suffixes */
     double fltval;
     uint32_t chrval;
+    Str strval;
 };
 
 struct Stab {
@@ -222,7 +229,7 @@
                 uvlong   intval;
                 double   fltval;
                 uint32_t chrval;
-                char    *strval;
+                Str      strval;
                 char    *lblval;
                 int      boolval;
                 Node    *fnval;
@@ -396,6 +403,8 @@
 int liteq(Node *a, Node *b);
 ulong strhash(void *key);
 int streq(void *a, void *b);
+ulong strlithash(void *key);
+int strliteq(void *a, void *b);
 ulong ptrhash(void *key);
 int ptreq(void *a, void *b);
 ulong inthash(uint64_t key);
@@ -506,7 +515,7 @@
 Node *mkbool(Srcloc l, int val);
 Node *mkint(Srcloc l, uint64_t val);
 Node *mkchar(Srcloc l, uint32_t val);
-Node *mkstr(Srcloc l, char *s);
+Node *mkstr(Srcloc l, Str str);
 Node *mkfloat(Srcloc l, double flt);
 Node *mkfunc(Srcloc l, Node **args, size_t nargs, Type *ret, Node *body);
 Node *mkname(Srcloc l, char *name);
@@ -582,6 +591,8 @@
 long rdint(FILE *fd);
 void wrstr(FILE *fd, char *val);
 char *rdstr(FILE *fd);
+void wrstrbuf(FILE *fd, Str str);
+void rdstrbuf(FILE *fd, Str *str);
 void wrflt(FILE *fd, double val);
 double rdflt(FILE *fd);
 void wrbool(FILE *fd, int val);
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -233,7 +233,7 @@
     if (!identstr(buf, sizeof buf))
         return NULL;
     t = mktok(kwd(buf));
-    t->str = strdup(buf);
+    t->id = strdup(buf);
     return t;
 }
 
@@ -248,7 +248,8 @@
         *buf = realloc(*buf, *sz);
     }
 
-    buf[0][len[0]++] = c;
+    buf[0][*len] = c;
+    (*len)++;
 }
 
 
@@ -408,10 +409,13 @@
         else
             append(&buf, &len, &sz, c);
     };
-    append(&buf, &len, &sz, '\0');
-
     t = mktok(Tstrlit);
-    t->str = buf;
+    t->strval.len = len;
+
+    /* null terminator should not count towards length */
+    append(&buf, &len, &sz, '\0');
+    t->strval.buf = buf;
+    t->id = buf;
     return t;
 }
 
@@ -472,7 +476,7 @@
 
     t = mktok(Tchrlit);
     t->chrval = val;
-    t->str = buf;
+    t->id = buf;
     return t;
 }
 
@@ -656,11 +660,11 @@
     /* we only support base 10 floats */
     if (isfloat && base == 10) {
         t = mktok(Tfloatlit);
-        t->str = strdupn(&fbuf[start], fidx - start);
+        t->id = strdupn(&fbuf[start], fidx - start);
         t->fltval = strtod(buf, NULL);
     } else {
         t = mktok(Tintlit);
-        t->str = strdupn(&fbuf[start], fidx - start);
+        t->id = strdupn(&fbuf[start], fidx - start);
         t->intval = strtoull(buf, NULL, base);
         /* check suffixes:
          *   u -> unsigned
@@ -748,7 +752,7 @@
     if (!identstr(buf, 1024))
         return NULL;
     t = mktok(Ttyparam);
-    t->str = strdup(buf);
+    t->id = strdup(buf);
     return t;
 }
 
@@ -829,8 +833,8 @@
 void yyerror(const char *s)
 {
     fprintf(stderr, "%s:%d: %s", filename, curloc.line, s);
-    if (curtok->str)
-        fprintf(stderr, " near \"%s\"", curtok->str);
+    if (curtok->id)
+        fprintf(stderr, " near \"%s\"", curtok->id);
     fprintf(stderr, "\n");
     exit(1);
 }
--- a/parse/use.c
+++ b/parse/use.c
@@ -453,7 +453,7 @@
                 case Lchr:      wrint(fd, n->lit.chrval);       break;
                 case Lint:      wrint(fd, n->lit.intval);       break;
                 case Lflt:      wrflt(fd, n->lit.fltval);       break;
-                case Lstr:      wrstr(fd, n->lit.strval);       break;
+                case Lstr:      wrstrbuf(fd, n->lit.strval);    break;
                 case Llbl:      wrstr(fd, n->lit.lblval);       break;
                 case Lbool:     wrbool(fd, n->lit.boolval);     break;
                 case Lfunc:     pickle(fd, n->lit.fnval);       break;
@@ -585,10 +585,10 @@
                 case Lchr:      n->lit.chrval = rdint(fd);       break;
                 case Lint:      n->lit.intval = rdint(fd);       break;
                 case Lflt:      n->lit.fltval = rdflt(fd);       break;
-                case Lstr:      n->lit.strval = rdstr(fd);       break;
+                case Lstr:      rdstrbuf(fd, &n->lit.strval);    break;
                 case Llbl:      n->lit.lblval = rdstr(fd);       break;
                 case Lbool:     n->lit.boolval = rdbool(fd);     break;
-                case Lfunc:     n->lit.fnval = unpickle(fd);       break;
+                case Lfunc:     n->lit.fnval = unpickle(fd);     break;
             }
             break;
         case Nloopstmt:
--- a/parse/util.c
+++ b/parse/util.c
@@ -316,6 +316,20 @@
     }
 }
 
+void wrstrbuf(FILE *fd, Str str)
+{
+    wrint(fd, str.len);
+    wrbuf(fd, str.buf, str.len);
+}
+
+void rdstrbuf(FILE *fd, Str *str)
+{
+    str->len = rdint(fd);
+    str->buf = xalloc(str->len + 1);
+    rdbuf(fd, str->buf, str->len);
+    str->buf[str->len] = '\0';
+}
+
 void wrflt(FILE *fd, double val)
 {
     byte buf[8];