]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cc, cmd/gc: update compilers, assemblers for liblink changes
authorRuss Cox <rsc@golang.org>
Mon, 16 Dec 2013 17:51:38 +0000 (12:51 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 16 Dec 2013 17:51:38 +0000 (12:51 -0500)
- add buffered stdout to all tools and provide to link ctxt.
- avoid extra \n before ! in .6 files written by assemblers
  (makes them match the C compilers).
- use linkwriteobj instead of linkouthist+linkwritefuncs.
- in assemblers and C compilers, record pc explicitly in Prog,
  for use by liblink.
- in C compilers, preserve jump target links.
- in Go compilers (gsubr.c) attach gotype directly to
  corresponding LSym* instead of rederiving from instruction stream.
- in Go compilers, emit just one definition for runtime.zerovalue
  from each compilation.

This CL consists entirely of small adjustments.
The heavy lifting is in CL 39680043.
Each depends on the other.

R=golang-dev, dave, iant
CC=golang-dev
https://golang.org/cl/37030045

32 files changed:
src/cmd/5a/a.h
src/cmd/5a/lex.c
src/cmd/5c/list.c
src/cmd/5c/reg.c
src/cmd/5c/swt.c
src/cmd/5g/gsubr.c
src/cmd/6a/a.h
src/cmd/6a/lex.c
src/cmd/6c/list.c
src/cmd/6c/reg.c
src/cmd/6c/swt.c
src/cmd/6c/txt.c
src/cmd/6g/gsubr.c
src/cmd/8a/a.h
src/cmd/8a/lex.c
src/cmd/8c/list.c
src/cmd/8c/reg.c
src/cmd/8c/swt.c
src/cmd/8c/txt.c
src/cmd/8g/gsubr.c
src/cmd/cc/cc.h
src/cmd/cc/lex.c
src/cmd/cc/lexbody
src/cmd/gc/go.h
src/cmd/gc/lex.c
src/cmd/gc/obj.c
src/cmd/gc/reflect.c
src/cmd/gc/subr.c
src/cmd/gc/walk.c
src/liblink/list5.c [new file with mode: 0644]
src/liblink/list6.c [new file with mode: 0644]
src/liblink/list8.c [new file with mode: 0644]

index 0f2348a19796f13138ce2c1e4701d376232737a5..4300dd8621fa9dda58547f33a4d0e0d9c8ae6cc6 100644 (file)
@@ -125,6 +125,7 @@ EXTERN      char*   thestring;
 EXTERN int32   thunk;
 EXTERN Biobuf  obuf;
 EXTERN Link*   ctxt;
+EXTERN Biobuf  bstdout;
 
 void*  alloc(int32);
 void*  allocn(void*, int32, int32);
@@ -165,3 +166,4 @@ void        yyerror(char*, ...);
 int    yyparse(void);
 void   setinclude(char*);
 int    assemble(char*);
+void   listinit(void);
index b5abb3cdbbc3a0504a8ffe76834ed810604f7c05..df5ecc6489299cf4231283ff504deaa2ce8a35ef 100644 (file)
@@ -59,8 +59,12 @@ main(int argc, char *argv[])
 
        thechar = '5';
        thestring = "arm";
+
        ctxt = linknew(&linkarm);
        ctxt->diag = yyerror;
+       ctxt->bso = &bstdout;
+       Binit(&bstdout, 1, OWRITE);
+       listinit5();
 
        ensuresymb(NSYMB);
        memset(debug, 0, sizeof(debug));
@@ -112,6 +116,7 @@ main(int argc, char *argv[])
        }
        if(assemble(argv[0]))
                errorexit();
+       Bflush(&bstdout);
        exits(0);
 }
 
@@ -151,7 +156,7 @@ assemble(char *file)
        }
        Binit(&obuf, of, OWRITE);
        Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
-       Bprint(&obuf, "\n!\n");
+       Bprint(&obuf, "!\n");
 
        for(pass = 1; pass <= 2; pass++) {
                pinit(file);
@@ -163,8 +168,7 @@ assemble(char *file)
                        return nerrors;
        }
 
-       linkouthist(ctxt, &obuf);
-       linkwritefuncs(ctxt, &obuf);
+       linkwriteobj(ctxt, &obuf);
        Bflush(&obuf);
        return 0;
 }
@@ -511,6 +515,7 @@ outcode(int a, int scond, Addr *g1, int reg, Addr *g2)
        p->from = *g1;
        p->reg = reg;
        p->to = *g2;
+       p->pc = pc;
 
        if(lastpc == nil) {
                pl = linknewplist(ctxt);
index 6f2545ff77b6c8de1d94d62073379009258c2a64..8b3ddf249bc1a868e221231379f148a9aee9a95a 100644 (file)
 void
 listinit(void)
 {
-
-       fmtinstall('A', Aconv);
-       fmtinstall('P', Pconv);
-       fmtinstall('S', Sconv);
-       fmtinstall('N', Nconv);
        fmtinstall('B', Bconv);
-       fmtinstall('D', Dconv);
-       fmtinstall('R', Rconv);
+       listinit5();
 }
 
 int
@@ -70,271 +64,3 @@ Bconv(Fmt *fp)
        }
        return fmtstrcpy(fp, str);
 }
-
-char *extra [] = {
-       ".EQ", ".NE", ".CS", ".CC",
-       ".MI", ".PL", ".VS", ".VC",
-       ".HI", ".LS", ".GE", ".LT",
-       ".GT", ".LE", "", ".NV",
-};
-
-int
-Pconv(Fmt *fp)
-{
-       char str[STRINGSZ], sc[20];
-       Prog *p;
-       int a, s;
-
-       p = va_arg(fp->args, Prog*);
-       a = p->as;
-       s = p->scond;
-       strcpy(sc, extra[s & C_SCOND]);
-       if(s & C_SBIT)
-               strcat(sc, ".S");
-       if(s & C_PBIT)
-               strcat(sc, ".P");
-       if(s & C_WBIT)
-               strcat(sc, ".W");
-       if(s & C_UBIT)          /* ambiguous with FBIT */
-               strcat(sc, ".U");
-       if(a == AMOVM) {
-               if(p->from.type == D_CONST)
-                       sprint(str, "   %A%s    %R,%D", a, sc, &p->from, &p->to);
-               else
-               if(p->to.type == D_CONST)
-                       sprint(str, "   %A%s    %D,%R", a, sc, &p->from, &p->to);
-               else
-                       sprint(str, "   %A%s    %D,%D", a, sc, &p->from, &p->to);
-       } else
-       if(a == ADATA)
-               sprint(str, "   %A      %D/%d,%D", a, &p->from, p->reg, &p->to);
-       else
-       if(p->as == ATEXT)
-               sprint(str, "   %A      %D,%d,%D", a, &p->from, p->reg, &p->to);
-       else
-       if(p->reg == NREG)
-               sprint(str, "   %A%s    %D,%D", a, sc, &p->from, &p->to);
-       else
-       if(p->from.type != D_FREG)
-               sprint(str, "   %A%s    %D,R%d,%D", a, sc, &p->from, p->reg, &p->to);
-       else
-               sprint(str, "   %A%s    %D,F%d,%D", a, sc, &p->from, p->reg, &p->to);
-       return fmtstrcpy(fp, str);
-}
-
-int
-Aconv(Fmt *fp)
-{
-       char *s;
-       int a;
-
-       a = va_arg(fp->args, int);
-       s = "???";
-       if(a >= AXXX && a < ALAST)
-               s = anames5[a];
-       return fmtstrcpy(fp, s);
-}
-
-int
-Dconv(Fmt *fp)
-{
-       char str[STRINGSZ];
-       Addr *a;
-       const char *op;
-       int v;
-
-       a = va_arg(fp->args, Addr*);
-       switch(a->type) {
-
-       default:
-               sprint(str, "GOK-type(%d)", a->type);
-               break;
-
-       case D_NONE:
-               str[0] = 0;
-               if(a->name != D_NONE || a->reg != NREG || a->sym != nil)
-                       sprint(str, "%N(R%d)(NONE)", a, a->reg);
-               break;
-
-       case D_CONST:
-               if(a->reg != NREG)
-                       sprint(str, "$%N(R%d)", a, a->reg);
-               else
-                       sprint(str, "$%N", a);
-               break;
-
-       case D_CONST2:
-               sprint(str, "$%d-%d", a->offset, a->offset2);
-               break;
-
-       case D_SHIFT:
-               v = a->offset;
-               op = &"<<>>->@>"[(((v>>5) & 3) << 1)];
-               if(v & (1<<4))
-                       sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
-               else
-                       sprint(str, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31);
-               if(a->reg != NREG)
-                       sprint(str+strlen(str), "(R%d)", a->reg);
-               break;
-
-       case D_OREG:
-               if(a->reg != NREG)
-                       sprint(str, "%N(R%d)", a, a->reg);
-               else
-                       sprint(str, "%N", a);
-               break;
-
-       case D_REG:
-               sprint(str, "R%d", a->reg);
-               if(a->name != D_NONE || a->sym != nil)
-                       sprint(str, "%N(R%d)(REG)", a, a->reg);
-               break;
-
-       case D_FREG:
-               sprint(str, "F%d", a->reg);
-               if(a->name != D_NONE || a->sym != nil)
-                       sprint(str, "%N(R%d)(REG)", a, a->reg);
-               break;
-
-       case D_PSR:
-               sprint(str, "PSR");
-               if(a->name != D_NONE || a->sym != nil)
-                       sprint(str, "%N(PSR)(REG)", a);
-               break;
-
-       case D_BRANCH:
-               sprint(str, "%d(PC)", a->offset-pc);
-               break;
-
-       case D_FCONST:
-               sprint(str, "$%.17g", a->u.dval);
-               break;
-
-       case D_SCONST:
-               sprint(str, "$\"%S\"", a->u.sval);
-               break;
-       }
-       return fmtstrcpy(fp, str);
-}
-
-int
-Rconv(Fmt *fp)
-{
-       char str[STRINGSZ];
-       Addr *a;
-       int i, v;
-
-       a = va_arg(fp->args, Addr*);
-       sprint(str, "GOK-reglist");
-       switch(a->type) {
-       case D_CONST:
-       case D_CONST2:
-               if(a->reg != NREG)
-                       break;
-               if(a->sym != nil)
-                       break;
-               v = a->offset;
-               strcpy(str, "");
-               for(i=0; i<NREG; i++) {
-                       if(v & (1<<i)) {
-                               if(str[0] == 0)
-                                       strcat(str, "[R");
-                               else
-                                       strcat(str, ",R");
-                               sprint(strchr(str, 0), "%d", i);
-                       }
-               }
-               strcat(str, "]");
-       }
-       return fmtstrcpy(fp, str);
-}
-
-int
-Sconv(Fmt *fp)
-{
-       int i, c;
-       char str[STRINGSZ], *p, *a;
-
-       a = va_arg(fp->args, char*);
-       p = str;
-       for(i=0; i<NSNAME; i++) {
-               c = a[i] & 0xff;
-               if(c >= 'a' && c <= 'z' ||
-                  c >= 'A' && c <= 'Z' ||
-                  c >= '0' && c <= '9' ||
-                  c == ' ' || c == '%') {
-                       *p++ = c;
-                       continue;
-               }
-               *p++ = '\\';
-               switch(c) {
-               case 0:
-                       *p++ = 'z';
-                       continue;
-               case '\\':
-               case '"':
-                       *p++ = c;
-                       continue;
-               case '\n':
-                       *p++ = 'n';
-                       continue;
-               case '\t':
-                       *p++ = 't';
-                       continue;
-               case '\r':
-                       *p++ = 'r';
-                       continue;
-               case '\f':
-                       *p++ = 'f';
-                       continue;
-               }
-               *p++ = (c>>6) + '0';
-               *p++ = ((c>>3) & 7) + '0';
-               *p++ = (c & 7) + '0';
-       }
-       *p = 0;
-       return fmtstrcpy(fp, str);
-}
-
-int
-Nconv(Fmt *fp)
-{
-       char str[STRINGSZ];
-       Addr *a;
-       LSym *s;
-
-       a = va_arg(fp->args, Addr*);
-       s = a->sym;
-       if(s == nil) {
-               sprint(str, "%d", a->offset);
-               goto out;
-       }
-       switch(a->name) {
-       default:
-               sprint(str, "GOK-name(%d)", a->name);
-               break;
-
-       case D_NONE:
-               sprint(str, "%d", a->offset);
-               break;
-
-       case D_EXTERN:
-               sprint(str, "%s+%d(SB)", s->name, a->offset);
-               break;
-
-       case D_STATIC:
-               sprint(str, "%s<>+%d(SB)", s->name, a->offset);
-               break;
-
-       case D_AUTO:
-               sprint(str, "%s-%d(SP)", s->name, -a->offset);
-               break;
-
-       case D_PARAM:
-               sprint(str, "%s+%d(FP)", s->name, a->offset);
-               break;
-       }
-out:
-       return fmtstrcpy(fp, str);
-}
index 4d27e3f5c73b8a8b0cf34a95ed5b928333d28cc2..b9ac21abdd88bdb995e56781dc0e01db06bef56b 100644 (file)
@@ -480,8 +480,10 @@ brk:
        r1 = 0; /* set */
        for(r = firstr; r != R; r = r->link) {
                p = r->prog;
-               if(p->to.type == D_BRANCH)
+               if(p->to.type == D_BRANCH) {
                        p->to.offset = r->s2->pc;
+                       p->to.u.branch = r->s2->prog;
+               }
                r1 = r;
        }
 
index 9e2e72f8e2abfcd2e2a13dbbf4627d204b71d570..b7332a27ad34ccf532c521e44534d39086a168ce 100644 (file)
@@ -365,8 +365,7 @@ outcode(void)
        }
        Bprint(&outbuf, "!\n");
 
-       linkouthist(ctxt, &outbuf);
-       linkwritefuncs(ctxt, &outbuf);
+       linkwriteobj(ctxt, &outbuf);
        lastp = P;
 }
 
index 4ce7d1fc392f267c9a71922a23a7245266c260b8..15206d59efcb3c00f28dbfa1425f80503de63749 100644 (file)
@@ -195,7 +195,7 @@ ggloblnod(Node *nam)
 
        p = gins(AGLOBL, nam, N);
        p->lineno = nam->lineno;
-       p->from.gotype = linksym(ngotype(nam));
+       p->from.sym->gotype = linksym(ngotype(nam));
        p->to.sym = nil;
        p->to.type = D_CONST;
        p->to.offset = nam->type->width;
index db72accd7f67573c7adaba38a717eb7386bc6320..da12b32986a173049fb2c77c858ac8f981cc8eef 100644 (file)
@@ -137,6 +137,7 @@ EXTERN      char*   thestring;
 EXTERN int32   thunk;
 EXTERN Biobuf  obuf;
 EXTERN Link*   ctxt;
+EXTERN Biobuf  bstdout;
 
 void*  alloc(int32);
 void*  allocn(void*, int32, int32);
index 97c78d16162032e8b246f412cb51654eb25fb28b..e69069e41a9a932b16425ae8d048feb1f933ff13 100644 (file)
@@ -65,8 +65,12 @@ main(int argc, char *argv[])
 
        thechar = '6';
        thestring = "amd64";
+
        ctxt = linknew(&linkamd64);
        ctxt->diag = yyerror;
+       ctxt->bso = &bstdout;
+       Binit(&bstdout, 1, OWRITE);
+       listinit6();
 
        ensuresymb(NSYMB);
        memset(debug, 0, sizeof(debug));
@@ -103,6 +107,7 @@ main(int argc, char *argv[])
                ctxt->debugasm++;
                break;
        } ARGEND
+
        if(*argv == 0) {
                print("usage: %ca [-options] file.s\n", thechar);
                errorexit();
@@ -113,6 +118,7 @@ main(int argc, char *argv[])
        }
        if(assemble(argv[0]))
                errorexit();
+       Bflush(&bstdout);
        exits(0);
 }
 
@@ -152,7 +158,7 @@ assemble(char *file)
        }
        Binit(&obuf, of, OWRITE);
        Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
-       Bprint(&obuf, "\n!\n");
+       Bprint(&obuf, "!\n");
 
        for(pass = 1; pass <= 2; pass++) {
                pinit(file);
@@ -164,8 +170,7 @@ assemble(char *file)
                        return nerrors;
        }
 
-       linkouthist(ctxt, &obuf);
-       linkwritefuncs(ctxt, &obuf);
+       linkwriteobj(ctxt, &obuf);
        Bflush(&obuf);
        return 0;
 }
@@ -1098,6 +1103,7 @@ outcode(int a, Addr2 *g2)
        p->lineno = stmtline;
        p->from = g2->from;
        p->to = g2->to;
+       p->pc = pc;
 
        if(lastpc == nil) {
                pl = linknewplist(ctxt);
index 5bb2bf2c7731fb45020acb48ddde0b767631ba03..79cfb1f00fb9a77dcd042515e45067e065269901 100644 (file)
 void
 listinit(void)
 {
-
-       fmtinstall('A', Aconv);
        fmtinstall('B', Bconv);
-       fmtinstall('P', Pconv);
-       fmtinstall('S', Sconv);
-       fmtinstall('D', Dconv);
-       fmtinstall('R', Rconv);
+       listinit6();
 }
 
 int
@@ -68,324 +63,3 @@ Bconv(Fmt *fp)
        }
        return fmtstrcpy(fp, str);
 }
-
-int
-Pconv(Fmt *fp)
-{
-       char str[STRINGSZ];
-       Prog *p;
-
-       p = va_arg(fp->args, Prog*);
-       switch(p->as) {
-       case ADATA:
-               sprint(str, "(%L)       %A      %D/%d,%D",
-                       p->lineno, p->as, &p->from, p->from.scale, &p->to);
-               break;
-
-       case ATEXT:
-               if(p->from.scale) {
-                       sprint(str, "(%L)       %A      %D,%d,%lD",
-                               p->lineno, p->as, &p->from, p->from.scale, &p->to);
-                       break;
-               }
-               sprint(str, "(%L)       %A      %D,%lD",
-                       p->lineno, p->as, &p->from, &p->to);
-               break;
-
-       default:
-               sprint(str, "(%L)       %A      %D,%D",
-                       p->lineno, p->as, &p->from, &p->to);
-               break;
-       }
-       return fmtstrcpy(fp, str);
-}
-
-int
-Aconv(Fmt *fp)
-{
-       int i;
-
-       i = va_arg(fp->args, int);
-       return fmtstrcpy(fp, anames6[i]);
-}
-
-int
-Dconv(Fmt *fp)
-{
-       char str[STRINGSZ], s[STRINGSZ];
-       Addr *a;
-       int i;
-
-       a = va_arg(fp->args, Addr*);
-       i = a->type;
-
-       if(fp->flags & FmtLong) {
-               if(i == D_CONST)
-                       sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
-               else {
-                       // ATEXT dst is not constant
-                       sprint(str, "!!%D", a);
-               }
-               goto brk;
-       }
-
-       if(i >= D_INDIR) {
-               if(a->offset)
-                       sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
-               else
-                       sprint(str, "(%R)", i-D_INDIR);
-               goto brk;
-       }
-       switch(i) {
-       default:
-               if(a->offset)
-                       sprint(str, "$%lld,%R", a->offset, i);
-               else
-                       sprint(str, "%R", i);
-               break;
-
-       case D_NONE:
-               str[0] = 0;
-               break;
-
-       case D_BRANCH:
-               sprint(str, "%lld", a->offset);
-               break;
-
-       case D_EXTERN:
-               sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
-               break;
-
-       case D_STATIC:
-               sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
-               break;
-
-       case D_AUTO:
-               if(a->sym)
-                       sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
-               else
-                       sprint(str, "%lld(SP)", a->offset);
-               break;
-
-       case D_PARAM:
-               if(a->sym)
-                       sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
-               else
-                       sprint(str, "%lld(FP)", a->offset);
-               break;
-
-       case D_CONST:
-               sprint(str, "$%lld", a->offset);
-               break;
-
-       case D_FCONST:
-               sprint(str, "$(%.17g)", a->u.dval);
-               break;
-
-       case D_SCONST:
-               sprint(str, "$\"%S\"", a->u.sval);
-               break;
-
-       case D_ADDR:
-               a->type = a->index;
-               a->index = D_NONE;
-               sprint(str, "$%D", a);
-               a->index = a->type;
-               a->type = D_ADDR;
-               goto conv;
-       }
-brk:
-       if(a->index != D_NONE) {
-               sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
-               strcat(str, s);
-       }
-conv:
-       return fmtstrcpy(fp, str);
-}
-
-char*  regstr[] =
-{
-       "AL",   /* [D_AL] */
-       "CL",
-       "DL",
-       "BL",
-       "SPB",
-       "BPB",
-       "SIB",
-       "DIB",
-       "R8B",
-       "R9B",
-       "R10B",
-       "R11B",
-       "R12B",
-       "R13B",
-       "R14B",
-       "R15B",
-
-       "AX",   /* [D_AX] */
-       "CX",
-       "DX",
-       "BX",
-       "SP",
-       "BP",
-       "SI",
-       "DI",
-       "R8",
-       "R9",
-       "R10",
-       "R11",
-       "R12",
-       "R13",
-       "R14",
-       "R15",
-
-       "AH",
-       "CH",
-       "DH",
-       "BH",
-
-       "F0",   /* [D_F0] */
-       "F1",
-       "F2",
-       "F3",
-       "F4",
-       "F5",
-       "F6",
-       "F7",
-
-       "M0",
-       "M1",
-       "M2",
-       "M3",
-       "M4",
-       "M5",
-       "M6",
-       "M7",
-
-       "X0",
-       "X1",
-       "X2",
-       "X3",
-       "X4",
-       "X5",
-       "X6",
-       "X7",
-       "X8",
-       "X9",
-       "X10",
-       "X11",
-       "X12",
-       "X13",
-       "X14",
-       "X15",
-
-       "CS",   /* [D_CS] */
-       "SS",
-       "DS",
-       "ES",
-       "FS",
-       "GS",
-
-       "GDTR", /* [D_GDTR] */
-       "IDTR", /* [D_IDTR] */
-       "LDTR", /* [D_LDTR] */
-       "MSW",  /* [D_MSW] */
-       "TASK", /* [D_TASK] */
-
-       "CR0",  /* [D_CR] */
-       "CR1",
-       "CR2",
-       "CR3",
-       "CR4",
-       "CR5",
-       "CR6",
-       "CR7",
-       "CR8",
-       "CR9",
-       "CR10",
-       "CR11",
-       "CR12",
-       "CR13",
-       "CR14",
-       "CR15",
-
-       "DR0",  /* [D_DR] */
-       "DR1",
-       "DR2",
-       "DR3",
-       "DR4",
-       "DR5",
-       "DR6",
-       "DR7",
-
-       "TR0",  /* [D_TR] */
-       "TR1",
-       "TR2",
-       "TR3",
-       "TR4",
-       "TR5",
-       "TR6",
-       "TR7",
-
-       "NONE", /* [D_NONE] */
-};
-
-int
-Rconv(Fmt *fp)
-{
-       char str[STRINGSZ];
-       int r;
-
-       r = va_arg(fp->args, int);
-       if(r >= D_AL && r <= D_NONE)
-               sprint(str, "%s", regstr[r-D_AL]);
-       else
-               sprint(str, "gok(%d)", r);
-
-       return fmtstrcpy(fp, str);
-}
-
-int
-Sconv(Fmt *fp)
-{
-       int i, c;
-       char str[STRINGSZ], *p, *a;
-
-       a = va_arg(fp->args, char*);
-       p = str;
-       for(i=0; i<sizeof(double); i++) {
-               c = a[i] & 0xff;
-               if(c >= 'a' && c <= 'z' ||
-                  c >= 'A' && c <= 'Z' ||
-                  c >= '0' && c <= '9') {
-                       *p++ = c;
-                       continue;
-               }
-               *p++ = '\\';
-               switch(c) {
-               default:
-                       if(c < 040 || c >= 0177)
-                               break;  /* not portable */
-                       p[-1] = c;
-                       continue;
-               case 0:
-                       *p++ = 'z';
-                       continue;
-               case '\\':
-               case '"':
-                       *p++ = c;
-                       continue;
-               case '\n':
-                       *p++ = 'n';
-                       continue;
-               case '\t':
-                       *p++ = 't';
-                       continue;
-               }
-               *p++ = (c>>6) + '0';
-               *p++ = ((c>>3) & 7) + '0';
-               *p++ = (c & 7) + '0';
-       }
-       *p = 0;
-       return fmtstrcpy(fp, str);
-}
index bf49a4da0dd8dc6b8b546bba280d14b895305786..1f4735684f35d21b98fe8b7986598b4456e28360 100644 (file)
@@ -663,8 +663,10 @@ brk:
        r1 = 0; /* set */
        for(r = firstr; r != R; r = r->link) {
                p = r->prog;
-               if(p->to.type == D_BRANCH)
+               if(p->to.type == D_BRANCH) {
                        p->to.offset = r->s2->pc;
+                       p->to.u.branch = r->s2->prog;
+               }
                r1 = r;
        }
 
@@ -1463,6 +1465,7 @@ fixjmp(Reg *firstr)
                if(p->as != ACALL && p->to.type == D_BRANCH && r->s2 && r->s2->prog->as == AJMP) {
                        r->s2 = chasejmp(r->s2, &jmploop);
                        p->to.offset = r->s2->pc;
+                       p->to.u.branch = r->s2->prog;
                        if(debug['R'] && debug['v'])
                                print("->%P\n", p);
                }
index afa10bf2f6c685fb5e7a4c6d809294745199d2db..d94250aa403838f2c5c98e17d648b779e296c272 100644 (file)
@@ -239,8 +239,7 @@ outcode(void)
        }
        Bprint(&b, "!\n");
 
-       linkouthist(ctxt, &b);
-       linkwritefuncs(ctxt, &b);
+       linkwriteobj(ctxt, &b);
        Bterm(&b);
        close(f);
        lastp = P;
index a129b11f41a084539b94100e692b31c921cc5b4b..e7598e18897c5b3df1a9308ac12dd8c1c5abcd84 100644 (file)
@@ -174,6 +174,7 @@ nextpc(void)
        p = alloc(sizeof(*p));
        *p = zprog;
        p->lineno = nearln;
+       p->pc = pc;
        pc++;
        if(lastp == nil) {
                pl = linknewplist(ctxt);
@@ -1488,9 +1489,10 @@ gbranch(int o)
 void
 patch(Prog *op, int32 pc)
 {
-
        op->to.offset = pc;
        op->to.type = D_BRANCH;
+       op->to.u.branch = nil;
+       op->pcond = nil;
 }
 
 void
index 65a9c6be15d1d77fa1171264106910145a2821b6..df9cc49caeda93a09ff247cb6cf94cb68c236848 100644 (file)
@@ -193,7 +193,7 @@ ggloblnod(Node *nam)
 
        p = gins(AGLOBL, nam, N);
        p->lineno = nam->lineno;
-       p->from.gotype = linksym(ngotype(nam));
+       p->from.sym->gotype = linksym(ngotype(nam));
        p->to.sym = nil;
        p->to.type = D_CONST;
        p->to.offset = nam->type->width;
index 41fe5804830cf8849cd8eb14cfa44ca9e0ba1d77..8c023c3ec61c05d3ba13dfc70be8cf90a75126b1 100644 (file)
@@ -137,6 +137,7 @@ EXTERN      char*   thestring;
 EXTERN int32   thunk;
 EXTERN Biobuf  obuf;
 EXTERN Link*   ctxt;
+EXTERN Biobuf  bstdout;
 
 void*  alloc(int32);
 void*  allocn(void*, int32, int32);
index 12034210f54899fad0a3629e6b8ed8e6b691d72c..96804ac0391aedf4376bdf87f57e37ba220186fe 100644 (file)
@@ -65,8 +65,12 @@ main(int argc, char *argv[])
 
        thechar = '8';
        thestring = "386";
+
        ctxt = linknew(&link386);
        ctxt->diag = yyerror;
+       ctxt->bso = &bstdout;
+       Binit(&bstdout, 1, OWRITE);
+       listinit8();
 
        ensuresymb(NSYMB);
        memset(debug, 0, sizeof(debug));
@@ -113,6 +117,7 @@ main(int argc, char *argv[])
        }
        if(assemble(argv[0]))
                errorexit();
+       Bflush(&bstdout);
        exits(0);
 }
 
@@ -152,7 +157,7 @@ assemble(char *file)
        }
        Binit(&obuf, of, OWRITE);
        Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
-       Bprint(&obuf, "\n!\n");
+       Bprint(&obuf, "!\n");
 
        for(pass = 1; pass <= 2; pass++) {
                pinit(file);
@@ -164,8 +169,7 @@ assemble(char *file)
                        return nerrors;
        }
 
-       linkouthist(ctxt, &obuf);
-       linkwritefuncs(ctxt, &obuf);
+       linkwriteobj(ctxt, &obuf);
        Bflush(&obuf);
        return 0;
 }
@@ -877,6 +881,7 @@ outcode(int a, Addr2 *g2)
        p->lineno = stmtline;
        p->from = g2->from;
        p->to = g2->to;
+       p->pc = pc;
 
        if(lastpc == nil) {
                pl = linknewplist(ctxt);
index 98aebce5311f86d1f17f834e4efe269e02933a6e..160e24ccd053c4d14d2a51cc47b95dbb85fac730 100644 (file)
 void
 listinit(void)
 {
-
-       fmtinstall('A', Aconv);
+       listinit8();
        fmtinstall('B', Bconv);
-       fmtinstall('P', Pconv);
-       fmtinstall('S', Sconv);
-       fmtinstall('D', Dconv);
-       fmtinstall('R', Rconv);
 }
 
 int
@@ -68,285 +63,3 @@ Bconv(Fmt *fp)
        }
        return fmtstrcpy(fp, str);
 }
-
-int
-Pconv(Fmt *fp)
-{
-       char str[STRINGSZ];
-       Prog *p;
-
-       p = va_arg(fp->args, Prog*);
-       switch(p->as) {
-       case ADATA:
-               sprint(str, "(%L)       %A      %D/%d,%D",
-                       p->lineno, p->as, &p->from, p->from.scale, &p->to);
-               break;
-
-       case ATEXT:
-               if(p->from.scale) {
-                       sprint(str, "(%L)       %A      %D,%d,%lD",
-                               p->lineno, p->as, &p->from, p->from.scale, &p->to);
-                       break;
-               }
-               sprint(str, "(%L)       %A      %D,%lD",
-                       p->lineno, p->as, &p->from, &p->to);
-               break;
-
-       default:
-               sprint(str, "(%L)       %A      %D,%D",
-                       p->lineno, p->as, &p->from, &p->to);
-               break;
-       }
-       return fmtstrcpy(fp, str);
-}
-
-int
-Aconv(Fmt *fp)
-{
-       int i;
-
-       i = va_arg(fp->args, int);
-       return fmtstrcpy(fp, anames8[i]);
-}
-
-int
-Dconv(Fmt *fp)
-{
-       char str[STRINGSZ], s[STRINGSZ];
-       Addr *a;
-       int i;
-
-       a = va_arg(fp->args, Addr*);
-       i = a->type;
-
-       if(fp->flags & FmtLong) {
-               if(i == D_CONST2)
-                       sprint(str, "$%lld-%d", a->offset, a->offset2);
-               else {
-                       // ATEXT dst is not constant
-                       sprint(str, "!!%D", a);
-               }
-               goto brk;
-       }
-
-       if(i >= D_INDIR) {
-               if(a->offset)
-                       sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
-               else
-                       sprint(str, "(%R)", i-D_INDIR);
-               goto brk;
-       }
-       switch(i) {
-       default:
-               if(a->offset)
-                       sprint(str, "$%lld,%R", a->offset, i);
-               else
-                       sprint(str, "%R", i);
-               break;
-
-       case D_NONE:
-               str[0] = 0;
-               break;
-
-       case D_BRANCH:
-               sprint(str, "%lld", a->offset);
-               break;
-
-       case D_EXTERN:
-               sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
-               break;
-
-       case D_STATIC:
-               sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
-               break;
-
-       case D_AUTO:
-               if(a->sym)
-                       sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
-               else
-                       sprint(str, "%lld(SP)", a->offset);
-               break;
-
-       case D_PARAM:
-               if(a->sym)
-                       sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
-               else
-                       sprint(str, "%lld(FP)", a->offset);
-               break;
-
-       case D_CONST:
-               sprint(str, "$%lld", a->offset);
-               break;
-
-       case D_CONST2:
-               if(!(fp->flags & FmtLong)) {
-                       // D_CONST2 outside of ATEXT should not happen
-                       sprint(str, "!!$%lld-%d", a->offset, a->offset2);
-               }
-               break;
-
-       case D_FCONST:
-               sprint(str, "$(%.17g)", a->u.dval);
-               break;
-
-       case D_SCONST:
-               sprint(str, "$\"%S\"", a->u.sval);
-               break;
-
-       case D_ADDR:
-               a->type = a->index;
-               a->index = D_NONE;
-               sprint(str, "$%D", a);
-               a->index = a->type;
-               a->type = D_ADDR;
-               goto conv;
-       }
-brk:
-       if(a->index != D_NONE) {
-               sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
-               strcat(str, s);
-       }
-conv:
-       return fmtstrcpy(fp, str);
-}
-
-char*  regstr[] =
-{
-       "AL",   /* [D_AL] */
-       "CL",
-       "DL",
-       "BL",
-       "AH",
-       "CH",
-       "DH",
-       "BH",
-
-       "AX",   /* [D_AX] */
-       "CX",
-       "DX",
-       "BX",
-       "SP",
-       "BP",
-       "SI",
-       "DI",
-
-       "F0",   /* [D_F0] */
-       "F1",
-       "F2",
-       "F3",
-       "F4",
-       "F5",
-       "F6",
-       "F7",
-
-       "CS",   /* [D_CS] */
-       "SS",
-       "DS",
-       "ES",
-       "FS",
-       "GS",
-
-       "GDTR", /* [D_GDTR] */
-       "IDTR", /* [D_IDTR] */
-       "LDTR", /* [D_LDTR] */
-       "MSW",  /* [D_MSW] */
-       "TASK", /* [D_TASK] */
-
-       "CR0",  /* [D_CR] */
-       "CR1",
-       "CR2",
-       "CR3",
-       "CR4",
-       "CR5",
-       "CR6",
-       "CR7",
-
-       "DR0",  /* [D_DR] */
-       "DR1",
-       "DR2",
-       "DR3",
-       "DR4",
-       "DR5",
-       "DR6",
-       "DR7",
-
-       "TR0",  /* [D_TR] */
-       "TR1",
-       "TR2",
-       "TR3",
-       "TR4",
-       "TR5",
-       "TR6",
-       "TR7",
-
-       "X0",   /* [D_X0] */
-       "X1",
-       "X2",
-       "X3",
-       "X4",
-       "X5",
-       "X6",
-       "X7",
-
-       "NONE", /* [D_NONE] */
-};
-
-int
-Rconv(Fmt *fp)
-{
-       char str[STRINGSZ];
-       int r;
-
-       r = va_arg(fp->args, int);
-       if(r >= D_AL && r <= D_NONE)
-               sprint(str, "%s", regstr[r-D_AL]);
-       else
-               sprint(str, "gok(%d)", r);
-
-       return fmtstrcpy(fp, str);
-}
-
-int
-Sconv(Fmt *fp)
-{
-       int i, c;
-       char str[STRINGSZ], *p, *a;
-
-       a = va_arg(fp->args, char*);
-       p = str;
-       for(i=0; i<sizeof(double); i++) {
-               c = a[i] & 0xff;
-               if(c >= 'a' && c <= 'z' ||
-                  c >= 'A' && c <= 'Z' ||
-                  c >= '0' && c <= '9') {
-                       *p++ = c;
-                       continue;
-               }
-               *p++ = '\\';
-               switch(c) {
-               default:
-                       if(c < 040 || c >= 0177)
-                               break;  /* not portable */
-                       p[-1] = c;
-                       continue;
-               case 0:
-                       *p++ = 'z';
-                       continue;
-               case '\\':
-               case '"':
-                       *p++ = c;
-                       continue;
-               case '\n':
-                       *p++ = 'n';
-                       continue;
-               case '\t':
-                       *p++ = 't';
-                       continue;
-               }
-               *p++ = (c>>6) + '0';
-               *p++ = ((c>>3) & 7) + '0';
-               *p++ = (c & 7) + '0';
-       }
-       *p = 0;
-       return fmtstrcpy(fp, str);
-}
index 3e1cd1fb409bbee0647ca68bb2a9a7b6851d5f7a..467796f3f3c6d65f6f26b3c5490841af0c36ce1a 100644 (file)
@@ -602,8 +602,10 @@ brk:
        r1 = 0; /* set */
        for(r = firstr; r != R; r = r->link) {
                p = r->prog;
-               if(p->to.type == D_BRANCH)
+               if(p->to.type == D_BRANCH) {
                        p->to.offset = r->s2->pc;
+                       p->to.u.branch = r->s2->prog;
+               }
                r1 = r;
        }
 
@@ -1377,6 +1379,7 @@ fixjmp(Reg *firstr)
                if(p->as != ACALL && p->to.type == D_BRANCH && r->s2 && r->s2->prog->as == AJMP) {
                        r->s2 = chasejmp(r->s2, &jmploop);
                        p->to.offset = r->s2->pc;
+                       p->to.u.branch = r->s2->prog;
                        if(debug['R'] && debug['v'])
                                print("->%P\n", p);
                }
index 84d1dc5b99a87fe598d9041af5d1d15a0a9310e2..ae4edb810fcae5220c3e24ba879b1f64cc8286f0 100644 (file)
@@ -244,8 +244,7 @@ outcode(void)
        }
        Bprint(&b, "!\n");
 
-       linkouthist(ctxt, &b);
-       linkwritefuncs(ctxt, &b);
+       linkwriteobj(ctxt, &b);
        Bterm(&b);
        close(f);
        lastp = P;
index 925543a66acde648c56a4d4c5a4793e760baa721..4708785c4a7f51a614a4b49e2b03c526def60620 100644 (file)
@@ -162,6 +162,7 @@ nextpc(void)
        p = alloc(sizeof(*p));
        *p = zprog;
        p->lineno = nearln;
+       p->pc = pc;
        pc++;
        if(lastp == nil) {
                pl = linknewplist(ctxt);
@@ -189,7 +190,8 @@ gargs(Node *n, Node *tn1, Node *tn2)
        cursafe = regs;
 }
 
-int nareg(void)
+int
+nareg(void)
 {
        int i, n;
 
@@ -1367,9 +1369,10 @@ gbranch(int o)
 void
 patch(Prog *op, int32 pc)
 {
-
        op->to.offset = pc;
        op->to.type = D_BRANCH;
+       op->to.u.branch = nil;
+       op->pcond = nil;
 }
 
 void
index 7176c766f553cb6b8c4b968f8a9e05e8c47e278b..34dfa2382b80bac02ac423c2650c6d869129a927 100644 (file)
@@ -194,7 +194,7 @@ ggloblnod(Node *nam)
 
        p = gins(AGLOBL, nam, N);
        p->lineno = nam->lineno;
-       p->from.gotype = linksym(ngotype(nam));
+       p->from.sym->gotype = linksym(ngotype(nam));
        p->to.sym = nil;
        p->to.type = D_CONST;
        p->to.offset = nam->type->width;
index ce2aa083b090aabab1ce513df44c6065e244a663..c8100730b80eeafd83551434195c68a02acfde19 100644 (file)
@@ -517,6 +517,7 @@ EXTERN      int     canreach;
 EXTERN int     warnreach;
 EXTERN Bits    zbits;
 EXTERN Fmt     pragcgobuf;
+EXTERN Biobuf  bstdout;
 
 extern char    *onames[], *tnames[], *gnames[];
 extern char    *cnames[], *qnames[], *bnames[];
index 59e540924457c9c5a94168d0ad85766b40833dfc..f5502866ac646984884585443d01f865a2f183cc 100644 (file)
@@ -119,7 +119,12 @@ main(int argc, char *argv[])
        int c;
 
        quotefmtinstall(); // before cinit, which overrides %Q
+
        ctxt = linknew(thelinkarch);
+       ctxt->diag = yyerror;
+       ctxt->bso = &bstdout;
+       Binit(&bstdout, 1, OWRITE);
+
        ensuresymb(NSYMB);
        memset(debug, 0, sizeof(debug));
        tinit();
@@ -182,6 +187,7 @@ main(int argc, char *argv[])
                flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
        
        flagparse(&argc, &argv, usage);
+       ctxt->debugasm = debug['S'];
 
        if(argc < 1 && outfile == 0)
                usage();
@@ -196,6 +202,7 @@ main(int argc, char *argv[])
        else
                c = compile(argv[0], defs, ndef);
 
+       Bflush(&bstdout);
        if(c)
                errorexit();
        exits(0);
@@ -332,6 +339,7 @@ compile(char *file, char **defs, int ndef)
 void
 errorexit(void)
 {
+       Bflush(&bstdout);
        if(outfile)
                remove(outfile);
        exits("error");
index 29ecc5c87c07586a01a98064d60d2870d0b7077c..e24db1bc0b4c957ca053b1ee1dc95ca164161845 100644 (file)
@@ -152,7 +152,7 @@ setinclude(char *p)
 void
 errorexit(void)
 {
-
+       Bflush(&bstdout);
        if(outfile)
                remove(outfile);
        exits("error");
index cc9a5eeaf8fdc3ab5408d039ed58596269623f53..081220db5ae044449338d1d53a60e244208ea650 100644 (file)
@@ -978,6 +978,8 @@ EXTERN      int     nointerface;
 EXTERN int     fieldtrack_enabled;
 EXTERN int     precisestack_enabled;
 
+EXTERN Biobuf  bstdout;
+
 /*
  *     y.tab.c
  */
@@ -1460,6 +1462,7 @@ EXTERN    Prog*   retpc;
 
 EXTERN Node*   nodfp;
 EXTERN int     disable_checknil;
+EXTERN vlong   zerosize;
 
 int    anyregalloc(void);
 void   betypeinit(void);
index 0ca332fac6752ad5cf4f33aac8e6b69bc6f62ac6..0d1fccb10da141961035073785ad677f7b9a1ac5 100644 (file)
@@ -189,6 +189,9 @@ main(int argc, char *argv[])
 #endif
 
        ctxt = linknew(thelinkarch);
+       ctxt->diag = yyerror;
+       ctxt->bso = &bstdout;
+       Binit(&bstdout, 1, OWRITE);
 
        localpkg = mkpkg(strlit(""));
        localpkg->prefix = "\"\"";
@@ -276,6 +279,7 @@ main(int argc, char *argv[])
                flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
 
        flagparse(&argc, &argv, usage);
+       ctxt->debugasm = debug['S'];
 
        if(argc < 1)
                usage();
@@ -706,7 +710,7 @@ importfile(Val *f, int line)
        }
 
        if(!findpkg(path)) {
-               yyerror("can't find import: \"%Z\" [path=%Z]", f->u.sval, path);
+               yyerror("can't find import: \"%Z\"", f->u.sval);
                errorexit();
        }
        importpkg = mkpkg(path);
index c26b6619cf6235d9d08c753a1940e739023bdc70..37d3a0326092e3edcaa5bfa897bc34960fa9d094 100644 (file)
@@ -16,6 +16,7 @@ void
 dumpobj(void)
 {
        NodeList *externs, *tmp;
+       Sym *zero;
 
        bout = Bopen(outfile, OWRITE);
        if(bout == nil) {
@@ -30,8 +31,6 @@ dumpobj(void)
        dumpexport();
        Bprint(bout, "\n!\n");
 
-       linkouthist(ctxt, bout);
-
        externs = nil;
        if(externdcl != nil)
                externs = externdcl->end;
@@ -46,8 +45,11 @@ dumpobj(void)
        dumpglobls();
        externdcl = tmp;
 
+       zero = pkglookup("zerovalue", runtimepkg);
+       ggloblsym(zero, zerosize, 1, 1);
+
        dumpdata();
-       linkwritefuncs(ctxt, bout);
+       linkwriteobj(ctxt, bout);
 
        Bterm(bout);
 }
@@ -74,12 +76,15 @@ dumpglobls(void)
 
                ggloblnod(n);
        }
-
+       
        for(l=funcsyms; l; l=l->next) {
                n = l->n;
                dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0);
                ggloblsym(n->sym, widthptr, 1, 1);
        }
+       
+       // Do not reprocess funcsyms on next dumpglobls call.
+       funcsyms = nil;
 }
 
 void
index 9e4c07252316bf6ac3d9c5ff0f21de9f64cd4488..4dde2176b19f31706ce92cb35c07ec2cb3733134 100644 (file)
@@ -763,7 +763,7 @@ dcommontype(Sym *s, int ot, Type *t)
        // 2-arg type cast) declares the size of the zerovalue it needs.
        // The linker magically takes the max of all the sizes.
        zero = pkglookup("zerovalue", runtimepkg);
-       ggloblsym(zero, 0, 1, 1);
+
        // We use size 0 here so we get the pointer to the zero value,
        // but don't allocate space for the zero value unless we need it.
        // TODO: how do we get this symbol into bss?  We really want
index 750909f32b66e7bd9365f720bec97e77a0e34aaf..a79cf06b750fe15d27bbba0f248cacfca7024d4f 100644 (file)
@@ -88,6 +88,7 @@ flusherrors(void)
 {
        int i;
 
+       Bflush(&bstdout);
        if(nerr == 0)
                return;
        qsort(err, nerr, sizeof err[0], errcmp);
index a3647a5a9ee9d538e4da76bb892194c54268e133..590909f2343dfa549b3ae1141049b35c293e9b66 100644 (file)
@@ -348,7 +348,7 @@ walkexpr(Node **np, NodeList **init)
        int64 v;
        int32 lno;
        Node *n, *fn, *n1, *n2;
-       Sym *sym, *zero;
+       Sym *sym;
        char buf[100], *p;
 
        n = *np;
@@ -713,8 +713,8 @@ walkexpr(Node **np, NodeList **init)
                typecheck(&n, Etop);
                walkexpr(&n, init);
                // mapaccess needs a zero value to be at least this big.
-               zero = pkglookup("zerovalue", runtimepkg);
-               ggloblsym(zero, t->type->width, 1, 1);
+               if(zerosize < t->type->width)
+                       zerosize = t->type->width;
                // TODO: ptr is always non-nil, so disable nil check for this OIND op.
                goto ret;
 
@@ -1130,8 +1130,8 @@ walkexpr(Node **np, NodeList **init)
                n->type = t->type;
                n->typecheck = 1;
                // mapaccess needs a zero value to be at least this big.
-               zero = pkglookup("zerovalue", runtimepkg);
-               ggloblsym(zero, t->type->width, 1, 1);
+               if(zerosize < t->type->width)
+                       zerosize = t->type->width;
                goto ret;
 
        case ORECV:
diff --git a/src/liblink/list5.c b/src/liblink/list5.c
new file mode 100644 (file)
index 0000000..cc6dd43
--- /dev/null
@@ -0,0 +1,331 @@
+// Inferno utils/5c/list.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5c/list.c
+//
+//     Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright © 1997-1999 Vita Nuova Limited
+//     Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright © 2004,2006 Bruce Ellis
+//     Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+#include "../cmd/5l/5.out.h"
+
+enum
+{
+       STRINGSZ = 1000
+};
+
+static int     Aconv(Fmt *fp);
+static int     Dconv(Fmt *fp);
+static int     Nconv(Fmt *fp);
+static int     Pconv(Fmt *fp);
+static int     Rconv(Fmt *fp);
+static int     Sconv(Fmt *fp);
+
+void
+listinit5(void)
+{
+       fmtinstall('A', Aconv);
+       fmtinstall('P', Pconv);
+       fmtinstall('S', Sconv);
+       fmtinstall('N', Nconv);
+       fmtinstall('D', Dconv);
+       fmtinstall('R', Rconv);
+}
+
+static char *extra [] = {
+       ".EQ", ".NE", ".CS", ".CC",
+       ".MI", ".PL", ".VS", ".VC",
+       ".HI", ".LS", ".GE", ".LT",
+       ".GT", ".LE", "", ".NV",
+};
+
+static int
+Pconv(Fmt *fp)
+{
+       char str[STRINGSZ], sc[20];
+       Prog *p;
+       int a, s;
+
+       p = va_arg(fp->args, Prog*);
+       a = p->as;
+       s = p->scond;
+       strcpy(sc, extra[s & C_SCOND]);
+       if(s & C_SBIT)
+               strcat(sc, ".S");
+       if(s & C_PBIT)
+               strcat(sc, ".P");
+       if(s & C_WBIT)
+               strcat(sc, ".W");
+       if(s & C_UBIT)          /* ambiguous with FBIT */
+               strcat(sc, ".U");
+       if(a == AMOVM) {
+               if(p->from.type == D_CONST)
+                       sprint(str, "   %A%s    %R,%D", a, sc, &p->from, &p->to);
+               else
+               if(p->to.type == D_CONST)
+                       sprint(str, "   %A%s    %D,%R", a, sc, &p->from, &p->to);
+               else
+                       sprint(str, "   %A%s    %D,%D", a, sc, &p->from, &p->to);
+       } else
+       if(a == ADATA)
+               sprint(str, "   %A      %D/%d,%D", a, &p->from, p->reg, &p->to);
+       else
+       if(p->as == ATEXT)
+               sprint(str, "   %A      %D,%d,%D", a, &p->from, p->reg, &p->to);
+       else
+       if(p->reg == NREG)
+               sprint(str, "   %A%s    %D,%D", a, sc, &p->from, &p->to);
+       else
+       if(p->from.type != D_FREG)
+               sprint(str, "   %A%s    %D,R%d,%D", a, sc, &p->from, p->reg, &p->to);
+       else
+               sprint(str, "   %A%s    %D,F%d,%D", a, sc, &p->from, p->reg, &p->to);
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Aconv(Fmt *fp)
+{
+       char *s;
+       int a;
+
+       a = va_arg(fp->args, int);
+       s = "???";
+       if(a >= AXXX && a < ALAST)
+               s = anames5[a];
+       return fmtstrcpy(fp, s);
+}
+
+static int
+Dconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       Addr *a;
+       const char *op;
+       int v;
+
+       a = va_arg(fp->args, Addr*);
+       switch(a->type) {
+
+       default:
+               sprint(str, "GOK-type(%d)", a->type);
+               break;
+
+       case D_NONE:
+               str[0] = 0;
+               if(a->name != D_NONE || a->reg != NREG || a->sym != nil)
+                       sprint(str, "%N(R%d)(NONE)", a, a->reg);
+               break;
+
+       case D_CONST:
+               if(a->reg != NREG)
+                       sprint(str, "$%N(R%d)", a, a->reg);
+               else
+                       sprint(str, "$%N", a);
+               break;
+
+       case D_CONST2:
+               sprint(str, "$%d-%d", a->offset, a->offset2);
+               break;
+
+       case D_SHIFT:
+               v = a->offset;
+               op = &"<<>>->@>"[(((v>>5) & 3) << 1)];
+               if(v & (1<<4))
+                       sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
+               else
+                       sprint(str, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31);
+               if(a->reg != NREG)
+                       sprint(str+strlen(str), "(R%d)", a->reg);
+               break;
+
+       case D_OREG:
+               if(a->reg != NREG)
+                       sprint(str, "%N(R%d)", a, a->reg);
+               else
+                       sprint(str, "%N", a);
+               break;
+
+       case D_REG:
+               sprint(str, "R%d", a->reg);
+               if(a->name != D_NONE || a->sym != nil)
+                       sprint(str, "%N(R%d)(REG)", a, a->reg);
+               break;
+
+       case D_FREG:
+               sprint(str, "F%d", a->reg);
+               if(a->name != D_NONE || a->sym != nil)
+                       sprint(str, "%N(R%d)(REG)", a, a->reg);
+               break;
+
+       case D_PSR:
+               sprint(str, "PSR");
+               if(a->name != D_NONE || a->sym != nil)
+                       sprint(str, "%N(PSR)(REG)", a);
+               break;
+
+       case D_BRANCH:
+               if(a->sym != nil)
+                       sprint(str, "%s(SB)", a->sym->name);
+               else if(a->u.branch != nil)
+                       sprint(str, "%#llx", a->u.branch->pc);
+               else
+                       sprint(str, "%d(PC)", (int)(a->offset/*-pc*/));
+               break;
+
+       case D_FCONST:
+               sprint(str, "$%.17g", a->u.dval);
+               break;
+
+       case D_SCONST:
+               sprint(str, "$\"%S\"", a->u.sval);
+               break;
+       }
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Rconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       Addr *a;
+       int i, v;
+
+       a = va_arg(fp->args, Addr*);
+       sprint(str, "GOK-reglist");
+       switch(a->type) {
+       case D_CONST:
+       case D_CONST2:
+               if(a->reg != NREG)
+                       break;
+               if(a->sym != nil)
+                       break;
+               v = a->offset;
+               strcpy(str, "");
+               for(i=0; i<NREG; i++) {
+                       if(v & (1<<i)) {
+                               if(str[0] == 0)
+                                       strcat(str, "[R");
+                               else
+                                       strcat(str, ",R");
+                               sprint(strchr(str, 0), "%d", i);
+                       }
+               }
+               strcat(str, "]");
+       }
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Sconv(Fmt *fp)
+{
+       int i, c;
+       char str[STRINGSZ], *p, *a;
+
+       a = va_arg(fp->args, char*);
+       p = str;
+       for(i=0; i<NSNAME; i++) {
+               c = a[i] & 0xff;
+               if(c >= 'a' && c <= 'z' ||
+                  c >= 'A' && c <= 'Z' ||
+                  c >= '0' && c <= '9' ||
+                  c == ' ' || c == '%') {
+                       *p++ = c;
+                       continue;
+               }
+               *p++ = '\\';
+               switch(c) {
+               case 0:
+                       *p++ = 'z';
+                       continue;
+               case '\\':
+               case '"':
+                       *p++ = c;
+                       continue;
+               case '\n':
+                       *p++ = 'n';
+                       continue;
+               case '\t':
+                       *p++ = 't';
+                       continue;
+               case '\r':
+                       *p++ = 'r';
+                       continue;
+               case '\f':
+                       *p++ = 'f';
+                       continue;
+               }
+               *p++ = (c>>6) + '0';
+               *p++ = ((c>>3) & 7) + '0';
+               *p++ = (c & 7) + '0';
+       }
+       *p = 0;
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Nconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       Addr *a;
+       LSym *s;
+
+       a = va_arg(fp->args, Addr*);
+       s = a->sym;
+       if(s == nil) {
+               sprint(str, "%d", (int)a->offset);
+               goto out;
+       }
+       switch(a->name) {
+       default:
+               sprint(str, "GOK-name(%d)", a->name);
+               break;
+
+       case D_NONE:
+               sprint(str, "%d", a->offset);
+               break;
+
+       case D_EXTERN:
+               sprint(str, "%s+%d(SB)", s->name, (int)a->offset);
+               break;
+
+       case D_STATIC:
+               sprint(str, "%s<>+%d(SB)", s->name, (int)a->offset);
+               break;
+
+       case D_AUTO:
+               sprint(str, "%s-%d(SP)", s->name, (int)-a->offset);
+               break;
+
+       case D_PARAM:
+               sprint(str, "%s+%d(FP)", s->name, (int)a->offset);
+               break;
+       }
+out:
+       return fmtstrcpy(fp, str);
+}
diff --git a/src/liblink/list6.c b/src/liblink/list6.c
new file mode 100644 (file)
index 0000000..c776194
--- /dev/null
@@ -0,0 +1,382 @@
+// Inferno utils/6c/list.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/list.c
+//
+//     Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright © 1997-1999 Vita Nuova Limited
+//     Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright © 2004,2006 Bruce Ellis
+//     Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+#include "../cmd/6l/6.out.h"
+
+static int     Aconv(Fmt *fp);
+static int     Dconv(Fmt *fp);
+static int     Pconv(Fmt *fp);
+static int     Rconv(Fmt *fp);
+static int     Sconv(Fmt *fp);
+
+enum
+{
+       STRINGSZ = 1000
+};
+
+void
+listinit6(void)
+{
+       fmtinstall('A', Aconv);
+       fmtinstall('P', Pconv);
+       fmtinstall('S', Sconv);
+       fmtinstall('D', Dconv);
+       fmtinstall('R', Rconv);
+}
+
+static int
+Pconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       Prog *p;
+
+       p = va_arg(fp->args, Prog*);
+       switch(p->as) {
+       case ADATA:
+               sprint(str, "(%L)       %A      %D/%d,%D",
+                       p->lineno, p->as, &p->from, p->from.scale, &p->to);
+               break;
+
+       case ATEXT:
+               if(p->from.scale) {
+                       sprint(str, "(%L)       %A      %D,%d,%lD",
+                               p->lineno, p->as, &p->from, p->from.scale, &p->to);
+                       break;
+               }
+               sprint(str, "(%L)       %A      %D,%lD",
+                       p->lineno, p->as, &p->from, &p->to);
+               break;
+
+       default:
+               sprint(str, "(%L)       %A      %D,%D",
+                       p->lineno, p->as, &p->from, &p->to);
+               break;
+       }
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Aconv(Fmt *fp)
+{
+       int i;
+
+       i = va_arg(fp->args, int);
+       return fmtstrcpy(fp, anames6[i]);
+}
+
+static int
+Dconv(Fmt *fp)
+{
+       char str[STRINGSZ], s[STRINGSZ];
+       Addr *a;
+       int i;
+
+       a = va_arg(fp->args, Addr*);
+       i = a->type;
+
+       if(fp->flags & FmtLong) {
+               if(i == D_CONST)
+                       sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
+               else {
+                       // ATEXT dst is not constant
+                       sprint(str, "!!%D", a);
+               }
+               goto brk;
+       }
+
+       if(i >= D_INDIR) {
+               if(a->offset)
+                       sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
+               else
+                       sprint(str, "(%R)", i-D_INDIR);
+               goto brk;
+       }
+       switch(i) {
+       default:
+               if(a->offset)
+                       sprint(str, "$%lld,%R", a->offset, i);
+               else
+                       sprint(str, "%R", i);
+               break;
+
+       case D_NONE:
+               str[0] = 0;
+               break;
+
+       case D_BRANCH:
+               if(a->sym != nil)
+                       sprint(str, "%s(SB)", a->sym->name);
+               else if(a->u.branch != nil)
+                       sprint(str, "%#llx", a->u.branch->pc);
+               else
+                       sprint(str, "%lld", a->offset);
+               break;
+
+       case D_EXTERN:
+               sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
+               break;
+
+       case D_STATIC:
+               sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
+               break;
+
+       case D_AUTO:
+               if(a->sym)
+                       sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
+               else
+                       sprint(str, "%lld(SP)", a->offset);
+               break;
+
+       case D_PARAM:
+               if(a->sym)
+                       sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
+               else
+                       sprint(str, "%lld(FP)", a->offset);
+               break;
+
+       case D_CONST:
+               sprint(str, "$%lld", a->offset);
+               break;
+
+       case D_FCONST:
+               sprint(str, "$(%.17g)", a->u.dval);
+               break;
+
+       case D_SCONST:
+               sprint(str, "$\"%S\"", a->u.sval);
+               break;
+
+       case D_ADDR:
+               a->type = a->index;
+               a->index = D_NONE;
+               sprint(str, "$%D", a);
+               a->index = a->type;
+               a->type = D_ADDR;
+               goto conv;
+       }
+brk:
+       if(a->index != D_NONE) {
+               sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+               strcat(str, s);
+       }
+conv:
+       return fmtstrcpy(fp, str);
+}
+
+char*  regstr[] =
+{
+       "AL",   /* [D_AL] */
+       "CL",
+       "DL",
+       "BL",
+       "SPB",
+       "BPB",
+       "SIB",
+       "DIB",
+       "R8B",
+       "R9B",
+       "R10B",
+       "R11B",
+       "R12B",
+       "R13B",
+       "R14B",
+       "R15B",
+
+       "AX",   /* [D_AX] */
+       "CX",
+       "DX",
+       "BX",
+       "SP",
+       "BP",
+       "SI",
+       "DI",
+       "R8",
+       "R9",
+       "R10",
+       "R11",
+       "R12",
+       "R13",
+       "R14",
+       "R15",
+
+       "AH",
+       "CH",
+       "DH",
+       "BH",
+
+       "F0",   /* [D_F0] */
+       "F1",
+       "F2",
+       "F3",
+       "F4",
+       "F5",
+       "F6",
+       "F7",
+
+       "M0",
+       "M1",
+       "M2",
+       "M3",
+       "M4",
+       "M5",
+       "M6",
+       "M7",
+
+       "X0",
+       "X1",
+       "X2",
+       "X3",
+       "X4",
+       "X5",
+       "X6",
+       "X7",
+       "X8",
+       "X9",
+       "X10",
+       "X11",
+       "X12",
+       "X13",
+       "X14",
+       "X15",
+
+       "CS",   /* [D_CS] */
+       "SS",
+       "DS",
+       "ES",
+       "FS",
+       "GS",
+
+       "GDTR", /* [D_GDTR] */
+       "IDTR", /* [D_IDTR] */
+       "LDTR", /* [D_LDTR] */
+       "MSW",  /* [D_MSW] */
+       "TASK", /* [D_TASK] */
+
+       "CR0",  /* [D_CR] */
+       "CR1",
+       "CR2",
+       "CR3",
+       "CR4",
+       "CR5",
+       "CR6",
+       "CR7",
+       "CR8",
+       "CR9",
+       "CR10",
+       "CR11",
+       "CR12",
+       "CR13",
+       "CR14",
+       "CR15",
+
+       "DR0",  /* [D_DR] */
+       "DR1",
+       "DR2",
+       "DR3",
+       "DR4",
+       "DR5",
+       "DR6",
+       "DR7",
+
+       "TR0",  /* [D_TR] */
+       "TR1",
+       "TR2",
+       "TR3",
+       "TR4",
+       "TR5",
+       "TR6",
+       "TR7",
+
+       "NONE", /* [D_NONE] */
+};
+
+static int
+Rconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       int r;
+
+       r = va_arg(fp->args, int);
+       if(r >= D_AL && r <= D_NONE)
+               sprint(str, "%s", regstr[r-D_AL]);
+       else
+               sprint(str, "gok(%d)", r);
+
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Sconv(Fmt *fp)
+{
+       int i, c;
+       char str[STRINGSZ], *p, *a;
+
+       a = va_arg(fp->args, char*);
+       p = str;
+       for(i=0; i<sizeof(double); i++) {
+               c = a[i] & 0xff;
+               if(c >= 'a' && c <= 'z' ||
+                  c >= 'A' && c <= 'Z' ||
+                  c >= '0' && c <= '9') {
+                       *p++ = c;
+                       continue;
+               }
+               *p++ = '\\';
+               switch(c) {
+               default:
+                       if(c < 040 || c >= 0177)
+                               break;  /* not portable */
+                       p[-1] = c;
+                       continue;
+               case 0:
+                       *p++ = 'z';
+                       continue;
+               case '\\':
+               case '"':
+                       *p++ = c;
+                       continue;
+               case '\n':
+                       *p++ = 'n';
+                       continue;
+               case '\t':
+                       *p++ = 't';
+                       continue;
+               }
+               *p++ = (c>>6) + '0';
+               *p++ = ((c>>3) & 7) + '0';
+               *p++ = (c & 7) + '0';
+       }
+       *p = 0;
+       return fmtstrcpy(fp, str);
+}
diff --git a/src/liblink/list8.c b/src/liblink/list8.c
new file mode 100644 (file)
index 0000000..cdc9751
--- /dev/null
@@ -0,0 +1,343 @@
+// Inferno utils/8c/list.c
+// http://code.google.com/p/inferno-os/source/browse/utils/8c/list.c
+//
+//     Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright © 1997-1999 Vita Nuova Limited
+//     Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright © 2004,2006 Bruce Ellis
+//     Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+#include "../cmd/8l/8.out.h"
+
+static int     Aconv(Fmt *fp);
+static int     Dconv(Fmt *fp);
+static int     Pconv(Fmt *fp);
+static int     Rconv(Fmt *fp);
+static int     Sconv(Fmt *fp);
+
+enum
+{
+       STRINGSZ = 1000
+};
+
+void
+listinit8(void)
+{
+       fmtinstall('A', Aconv);
+       fmtinstall('P', Pconv);
+       fmtinstall('S', Sconv);
+       fmtinstall('D', Dconv);
+       fmtinstall('R', Rconv);
+}
+
+static int
+Pconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       Prog *p;
+
+       p = va_arg(fp->args, Prog*);
+       switch(p->as) {
+       case ADATA:
+               sprint(str, "(%L)       %A      %D/%d,%D",
+                       p->lineno, p->as, &p->from, p->from.scale, &p->to);
+               break;
+
+       case ATEXT:
+               if(p->from.scale) {
+                       sprint(str, "(%L)       %A      %D,%d,%lD",
+                               p->lineno, p->as, &p->from, p->from.scale, &p->to);
+                       break;
+               }
+               sprint(str, "(%L)       %A      %D,%lD",
+                       p->lineno, p->as, &p->from, &p->to);
+               break;
+
+       default:
+               sprint(str, "(%L)       %A      %D,%D",
+                       p->lineno, p->as, &p->from, &p->to);
+               break;
+       }
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Aconv(Fmt *fp)
+{
+       int i;
+
+       i = va_arg(fp->args, int);
+       return fmtstrcpy(fp, anames8[i]);
+}
+
+static int
+Dconv(Fmt *fp)
+{
+       char str[STRINGSZ], s[STRINGSZ];
+       Addr *a;
+       int i;
+
+       a = va_arg(fp->args, Addr*);
+       i = a->type;
+
+       if(fp->flags & FmtLong) {
+               if(i == D_CONST2)
+                       sprint(str, "$%lld-%d", a->offset, a->offset2);
+               else {
+                       // ATEXT dst is not constant
+                       sprint(str, "!!%D", a);
+               }
+               goto brk;
+       }
+
+       if(i >= D_INDIR) {
+               if(a->offset)
+                       sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
+               else
+                       sprint(str, "(%R)", i-D_INDIR);
+               goto brk;
+       }
+       switch(i) {
+       default:
+               if(a->offset)
+                       sprint(str, "$%lld,%R", a->offset, i);
+               else
+                       sprint(str, "%R", i);
+               break;
+
+       case D_NONE:
+               str[0] = 0;
+               break;
+
+       case D_BRANCH:
+               if(a->sym != nil)
+                       sprint(str, "%s(SB)", a->sym->name);
+               else if(a->u.branch != nil)
+                       sprint(str, "%#llx", a->u.branch->pc);
+               else
+                       sprint(str, "%lld", a->offset);
+               break;
+
+       case D_EXTERN:
+               sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
+               break;
+
+       case D_STATIC:
+               sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
+               break;
+
+       case D_AUTO:
+               if(a->sym)
+                       sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
+               else
+                       sprint(str, "%lld(SP)", a->offset);
+               break;
+
+       case D_PARAM:
+               if(a->sym)
+                       sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
+               else
+                       sprint(str, "%lld(FP)", a->offset);
+               break;
+
+       case D_CONST:
+               sprint(str, "$%lld", a->offset);
+               break;
+
+       case D_CONST2:
+               if(!(fp->flags & FmtLong)) {
+                       // D_CONST2 outside of ATEXT should not happen
+                       sprint(str, "!!$%lld-%d", a->offset, a->offset2);
+               }
+               break;
+
+       case D_FCONST:
+               sprint(str, "$(%.17g)", a->u.dval);
+               break;
+
+       case D_SCONST:
+               sprint(str, "$\"%S\"", a->u.sval);
+               break;
+
+       case D_ADDR:
+               a->type = a->index;
+               a->index = D_NONE;
+               sprint(str, "$%D", a);
+               a->index = a->type;
+               a->type = D_ADDR;
+               goto conv;
+       }
+brk:
+       if(a->index != D_NONE) {
+               sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+               strcat(str, s);
+       }
+conv:
+       return fmtstrcpy(fp, str);
+}
+
+char*  regstr[] =
+{
+       "AL",   /* [D_AL] */
+       "CL",
+       "DL",
+       "BL",
+       "AH",
+       "CH",
+       "DH",
+       "BH",
+
+       "AX",   /* [D_AX] */
+       "CX",
+       "DX",
+       "BX",
+       "SP",
+       "BP",
+       "SI",
+       "DI",
+
+       "F0",   /* [D_F0] */
+       "F1",
+       "F2",
+       "F3",
+       "F4",
+       "F5",
+       "F6",
+       "F7",
+
+       "CS",   /* [D_CS] */
+       "SS",
+       "DS",
+       "ES",
+       "FS",
+       "GS",
+
+       "GDTR", /* [D_GDTR] */
+       "IDTR", /* [D_IDTR] */
+       "LDTR", /* [D_LDTR] */
+       "MSW",  /* [D_MSW] */
+       "TASK", /* [D_TASK] */
+
+       "CR0",  /* [D_CR] */
+       "CR1",
+       "CR2",
+       "CR3",
+       "CR4",
+       "CR5",
+       "CR6",
+       "CR7",
+
+       "DR0",  /* [D_DR] */
+       "DR1",
+       "DR2",
+       "DR3",
+       "DR4",
+       "DR5",
+       "DR6",
+       "DR7",
+
+       "TR0",  /* [D_TR] */
+       "TR1",
+       "TR2",
+       "TR3",
+       "TR4",
+       "TR5",
+       "TR6",
+       "TR7",
+
+       "X0",   /* [D_X0] */
+       "X1",
+       "X2",
+       "X3",
+       "X4",
+       "X5",
+       "X6",
+       "X7",
+
+       "NONE", /* [D_NONE] */
+};
+
+static int
+Rconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       int r;
+
+       r = va_arg(fp->args, int);
+       if(r >= D_AL && r <= D_NONE)
+               sprint(str, "%s", regstr[r-D_AL]);
+       else
+               sprint(str, "gok(%d)", r);
+
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Sconv(Fmt *fp)
+{
+       int i, c;
+       char str[STRINGSZ], *p, *a;
+
+       a = va_arg(fp->args, char*);
+       p = str;
+       for(i=0; i<sizeof(double); i++) {
+               c = a[i] & 0xff;
+               if(c >= 'a' && c <= 'z' ||
+                  c >= 'A' && c <= 'Z' ||
+                  c >= '0' && c <= '9') {
+                       *p++ = c;
+                       continue;
+               }
+               *p++ = '\\';
+               switch(c) {
+               default:
+                       if(c < 040 || c >= 0177)
+                               break;  /* not portable */
+                       p[-1] = c;
+                       continue;
+               case 0:
+                       *p++ = 'z';
+                       continue;
+               case '\\':
+               case '"':
+                       *p++ = c;
+                       continue;
+               case '\n':
+                       *p++ = 'n';
+                       continue;
+               case '\t':
+                       *p++ = 't';
+                       continue;
+               }
+               *p++ = (c>>6) + '0';
+               *p++ = ((c>>3) & 7) + '0';
+               *p++ = (c & 7) + '0';
+       }
+       *p = 0;
+       return fmtstrcpy(fp, str);
+}