EXTERN int32 thunk;
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
+EXTERN Biobuf bstdout;
void* alloc(int32);
void* allocn(void*, int32, int32);
int yyparse(void);
void setinclude(char*);
int assemble(char*);
+void listinit(void);
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));
}
if(assemble(argv[0]))
errorexit();
+ Bflush(&bstdout);
exits(0);
}
}
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);
return nerrors;
}
- linkouthist(ctxt, &obuf);
- linkwritefuncs(ctxt, &obuf);
+ linkwriteobj(ctxt, &obuf);
Bflush(&obuf);
return 0;
}
p->from = *g1;
p->reg = reg;
p->to = *g2;
+ p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
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
}
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);
-}
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;
}
}
Bprint(&outbuf, "!\n");
- linkouthist(ctxt, &outbuf);
- linkwritefuncs(ctxt, &outbuf);
+ linkwriteobj(ctxt, &outbuf);
lastp = P;
}
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;
EXTERN int32 thunk;
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
+EXTERN Biobuf bstdout;
void* alloc(int32);
void* allocn(void*, int32, int32);
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));
ctxt->debugasm++;
break;
} ARGEND
+
if(*argv == 0) {
print("usage: %ca [-options] file.s\n", thechar);
errorexit();
}
if(assemble(argv[0]))
errorexit();
+ Bflush(&bstdout);
exits(0);
}
}
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);
return nerrors;
}
- linkouthist(ctxt, &obuf);
- linkwritefuncs(ctxt, &obuf);
+ linkwriteobj(ctxt, &obuf);
Bflush(&obuf);
return 0;
}
p->lineno = stmtline;
p->from = g2->from;
p->to = g2->to;
+ p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
void
listinit(void)
{
-
- fmtinstall('A', Aconv);
fmtinstall('B', Bconv);
- fmtinstall('P', Pconv);
- fmtinstall('S', Sconv);
- fmtinstall('D', Dconv);
- fmtinstall('R', Rconv);
+ listinit6();
}
int
}
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);
-}
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;
}
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);
}
}
Bprint(&b, "!\n");
- linkouthist(ctxt, &b);
- linkwritefuncs(ctxt, &b);
+ linkwriteobj(ctxt, &b);
Bterm(&b);
close(f);
lastp = P;
p = alloc(sizeof(*p));
*p = zprog;
p->lineno = nearln;
+ p->pc = pc;
pc++;
if(lastp == nil) {
pl = linknewplist(ctxt);
void
patch(Prog *op, int32 pc)
{
-
op->to.offset = pc;
op->to.type = D_BRANCH;
+ op->to.u.branch = nil;
+ op->pcond = nil;
}
void
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;
EXTERN int32 thunk;
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
+EXTERN Biobuf bstdout;
void* alloc(int32);
void* allocn(void*, int32, int32);
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));
}
if(assemble(argv[0]))
errorexit();
+ Bflush(&bstdout);
exits(0);
}
}
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);
return nerrors;
}
- linkouthist(ctxt, &obuf);
- linkwritefuncs(ctxt, &obuf);
+ linkwriteobj(ctxt, &obuf);
Bflush(&obuf);
return 0;
}
p->lineno = stmtline;
p->from = g2->from;
p->to = g2->to;
+ p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
void
listinit(void)
{
-
- fmtinstall('A', Aconv);
+ listinit8();
fmtinstall('B', Bconv);
- fmtinstall('P', Pconv);
- fmtinstall('S', Sconv);
- fmtinstall('D', Dconv);
- fmtinstall('R', Rconv);
}
int
}
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);
-}
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;
}
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);
}
}
Bprint(&b, "!\n");
- linkouthist(ctxt, &b);
- linkwritefuncs(ctxt, &b);
+ linkwriteobj(ctxt, &b);
Bterm(&b);
close(f);
lastp = P;
p = alloc(sizeof(*p));
*p = zprog;
p->lineno = nearln;
+ p->pc = pc;
pc++;
if(lastp == nil) {
pl = linknewplist(ctxt);
cursafe = regs;
}
-int nareg(void)
+int
+nareg(void)
{
int i, n;
void
patch(Prog *op, int32 pc)
{
-
op->to.offset = pc;
op->to.type = D_BRANCH;
+ op->to.u.branch = nil;
+ op->pcond = nil;
}
void
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;
EXTERN int warnreach;
EXTERN Bits zbits;
EXTERN Fmt pragcgobuf;
+EXTERN Biobuf bstdout;
extern char *onames[], *tnames[], *gnames[];
extern char *cnames[], *qnames[], *bnames[];
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();
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();
else
c = compile(argv[0], defs, ndef);
+ Bflush(&bstdout);
if(c)
errorexit();
exits(0);
void
errorexit(void)
{
+ Bflush(&bstdout);
if(outfile)
remove(outfile);
exits("error");
void
errorexit(void)
{
-
+ Bflush(&bstdout);
if(outfile)
remove(outfile);
exits("error");
EXTERN int fieldtrack_enabled;
EXTERN int precisestack_enabled;
+EXTERN Biobuf bstdout;
+
/*
* y.tab.c
*/
EXTERN Node* nodfp;
EXTERN int disable_checknil;
+EXTERN vlong zerosize;
int anyregalloc(void);
void betypeinit(void);
#endif
ctxt = linknew(thelinkarch);
+ ctxt->diag = yyerror;
+ ctxt->bso = &bstdout;
+ Binit(&bstdout, 1, OWRITE);
localpkg = mkpkg(strlit(""));
localpkg->prefix = "\"\"";
flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
flagparse(&argc, &argv, usage);
+ ctxt->debugasm = debug['S'];
if(argc < 1)
usage();
}
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);
dumpobj(void)
{
NodeList *externs, *tmp;
+ Sym *zero;
bout = Bopen(outfile, OWRITE);
if(bout == nil) {
dumpexport();
Bprint(bout, "\n!\n");
- linkouthist(ctxt, bout);
-
externs = nil;
if(externdcl != nil)
externs = externdcl->end;
dumpglobls();
externdcl = tmp;
+ zero = pkglookup("zerovalue", runtimepkg);
+ ggloblsym(zero, zerosize, 1, 1);
+
dumpdata();
- linkwritefuncs(ctxt, bout);
+ linkwriteobj(ctxt, bout);
Bterm(bout);
}
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
// 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
{
int i;
+ Bflush(&bstdout);
if(nerr == 0)
return;
qsort(err, nerr, sizeof err[0], errcmp);
int64 v;
int32 lno;
Node *n, *fn, *n1, *n2;
- Sym *sym, *zero;
+ Sym *sym;
char buf[100], *p;
n = *np;
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;
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:
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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);
+}