aboutsummaryrefslogtreecommitdiff
path: root/src/liblink
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2015-01-26 15:15:43 -0500
committerRuss Cox <rsc@golang.org>2015-01-30 03:16:19 +0000
commita5b1baeed7d26a3d8aea86bbabe81f59c3d4e9d6 (patch)
tree4a0222814771277f93201d329d5cfd3f811f6f79 /src/liblink
parent604138e87bb0d992319ed2ccc034f9a2591a8363 (diff)
downloadgo-a5b1baeed7d26a3d8aea86bbabe81f59c3d4e9d6.tar.xz
cmd/8a, cmd/8g, cmd/8l, liblink: update for portable Prog, Addr
Change-Id: I19ed283962aa0221cf806307bde9ea0773a1bfd4 Reviewed-on: https://go-review.googlesource.com/3518 Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/liblink')
-rw-r--r--src/liblink/asm8.c766
-rw-r--r--src/liblink/list8.c178
-rw-r--r--src/liblink/obj8.c248
3 files changed, 618 insertions, 574 deletions
diff --git a/src/liblink/asm8.c b/src/liblink/asm8.c
index 3bb761b9ae..fa20d14b1b 100644
--- a/src/liblink/asm8.c
+++ b/src/liblink/asm8.c
@@ -140,7 +140,7 @@ enum
};
static uchar ycover[Ymax*Ymax];
-static int reg[D_NONE];
+static int reg[MAXREG];
static void asmins(Link *ctxt, Prog *p);
static uchar ynone[] =
@@ -750,12 +750,12 @@ static Optab optab[] =
{ AMULW, ydivl, Pe, {0xf7,(04)} },
{ ANAME },
{ ANEGB, yscond, Px, {0xf6,(03)} },
- { ANEGL, yscond, Px, {0xf7,(03)} },
- { ANEGW, yscond, Pe, {0xf7,(03)} },
+ { ANEGL, yscond, Px, {0xf7,(03)} }, // TODO(rsc): yscond is wrong here.
+ { ANEGW, yscond, Pe, {0xf7,(03)} }, // TODO(rsc): yscond is wrong here.
{ ANOP, ynop, Px, {0,0} },
{ ANOTB, yscond, Px, {0xf6,(02)} },
- { ANOTL, yscond, Px, {0xf7,(02)} },
- { ANOTW, yscond, Pe, {0xf7,(02)} },
+ { ANOTL, yscond, Px, {0xf7,(02)} }, // TODO(rsc): yscond is wrong here.
+ { ANOTW, yscond, Pe, {0xf7,(02)} }, // TODO(rsc): yscond is wrong here.
{ AORB, yxorb, Pb, {0x0c,0x80,(01),0x08,0x0a} },
{ AORL, yxorl, Px, {0x83,(01),0x0d,0x81,(01),0x09,0x0b} },
{ AORW, yxorl, Pe, {0x83,(01),0x0d,0x81,(01),0x09,0x0b} },
@@ -973,7 +973,7 @@ static Optab optab[] =
{ ACMPXCHGB, yrb_mb, Pm, {0xb0} },
{ ACMPXCHGL, yrl_ml, Pm, {0xb1} },
{ ACMPXCHGW, yrl_ml, Pm, {0xb1} },
- { ACMPXCHG8B, yscond, Pm, {0xc7,(01)} },
+ { ACMPXCHG8B, yscond, Pm, {0xc7,(01)} }, // TODO(rsc): yscond is wrong here.
{ ACPUID, ynone, Pm, {0xa2} },
{ ARDTSC, ynone, Pm, {0x31} },
@@ -1231,7 +1231,7 @@ span8(Link *ctxt, LSym *s)
for(p = s->text; p != nil; p = p->link) {
n = 0;
- if(p->to.type == D_BRANCH)
+ if(p->to.type == TYPE_BRANCH)
if(p->pcond == nil)
p->pcond = p;
if((q = p->pcond) != nil)
@@ -1239,7 +1239,8 @@ span8(Link *ctxt, LSym *s)
n = 1;
p->back = n;
if(p->as == AADJSP) {
- p->to.type = D_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SP;
v = -p->from.offset;
p->from.offset = v;
p->as = AADDL;
@@ -1259,7 +1260,8 @@ span8(Link *ctxt, LSym *s)
p->back |= 1; // backward jump
if(p->as == AADJSP) {
- p->to.type = D_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SP;
v = -p->from.offset;
p->from.offset = v;
p->as = AADDL;
@@ -1437,196 +1439,216 @@ instinit(void)
ycover[Ym*Ymax + Yxm] = 1;
ycover[Yxr*Ymax + Yxm] = 1;
- for(i=0; i<D_NONE; i++) {
+ for(i=0; i<MAXREG; i++) {
reg[i] = -1;
- if(i >= D_AL && i <= D_BH)
- reg[i] = (i-D_AL) & 7;
- if(i >= D_AX && i <= D_DI)
- reg[i] = (i-D_AX) & 7;
- if(i >= D_F0 && i <= D_F0+7)
- reg[i] = (i-D_F0) & 7;
- if(i >= D_X0 && i <= D_X0+7)
- reg[i] = (i-D_X0) & 7;
+ if(i >= REG_AL && i <= REG_BH)
+ reg[i] = (i-REG_AL) & 7;
+ if(i >= REG_AX && i <= REG_DI)
+ reg[i] = (i-REG_AX) & 7;
+ if(i >= REG_F0 && i <= REG_F0+7)
+ reg[i] = (i-REG_F0) & 7;
+ if(i >= REG_X0 && i <= REG_X0+7)
+ reg[i] = (i-REG_X0) & 7;
}
}
static int
prefixof(Link *ctxt, Addr *a)
{
- switch(a->type) {
- case D_INDIR+D_CS:
- return 0x2e;
- case D_INDIR+D_DS:
- return 0x3e;
- case D_INDIR+D_ES:
- return 0x26;
- case D_INDIR+D_FS:
- return 0x64;
- case D_INDIR+D_GS:
- return 0x65;
- case D_INDIR+D_TLS:
- // NOTE: Systems listed here should be only systems that
- // support direct TLS references like 8(TLS) implemented as
- // direct references from FS or GS. Systems that require
- // the initial-exec model, where you load the TLS base into
- // a register and then index from that register, do not reach
- // this code and should not be listed.
- switch(ctxt->headtype) {
- default:
- sysfatal("unknown TLS base register for %s", headstr(ctxt->headtype));
- case Hdarwin:
- case Hdragonfly:
- case Hfreebsd:
- case Hnetbsd:
- case Hopenbsd:
- return 0x65; // GS
+ if(a->type == TYPE_MEM && a->name == NAME_NONE) {
+ switch(a->reg) {
+ case REG_CS:
+ return 0x2e;
+ case REG_DS:
+ return 0x3e;
+ case REG_ES:
+ return 0x26;
+ case REG_FS:
+ return 0x64;
+ case REG_GS:
+ return 0x65;
+ case REG_TLS:
+ // NOTE: Systems listed here should be only systems that
+ // support direct TLS references like 8(TLS) implemented as
+ // direct references from FS or GS. Systems that require
+ // the initial-exec model, where you load the TLS base into
+ // a register and then index from that register, do not reach
+ // this code and should not be listed.
+ switch(ctxt->headtype) {
+ default:
+ sysfatal("unknown TLS base register for %s", headstr(ctxt->headtype));
+ case Hdarwin:
+ case Hdragonfly:
+ case Hfreebsd:
+ case Hnetbsd:
+ case Hopenbsd:
+ return 0x65; // GS
+ }
}
}
return 0;
}
static int
-oclass(Addr *a)
+oclass(Link *ctxt, Addr *a)
{
int32 v;
- if((a->type >= D_INDIR && a->type < 2*D_INDIR) || a->index != D_NONE) {
- if(a->index != D_NONE && a->scale == 0) {
- if(a->type == D_ADDR) {
- switch(a->index) {
- case D_EXTERN:
- case D_STATIC:
- return Yi32;
- case D_AUTO:
- case D_PARAM:
- return Yiauto;
- }
- return Yxxx;
- }
- //if(a->type == D_INDIR+D_ADDR)
- // print("*Ycol\n");
+ // TODO(rsc): This special case is for SHRQ $3, AX:DX,
+ // which encodes as SHRQ $32(DX*0), AX.
+ // Similarly SHRQ CX, AX:DX is really SHRQ CX(DX*0), AX.
+ // Change encoding and remove.
+ if((a->type == TYPE_CONST || a->type == TYPE_REG) && a->index != REG_NONE && a->scale == 0)
+ return Ycol;
+
+ switch(a->type) {
+ case TYPE_NONE:
+ return Ynone;
+
+ case TYPE_BRANCH:
+ return Ybr;
+
+ case TYPE_INDIR:
+ // TODO(rsc): Why this is also Ycol is a mystery. Should split the two meanings.
+ if(a->name != NAME_NONE && a->reg == REG_NONE && a->index == REG_NONE && a->scale == 0)
return Ycol;
- }
+ return Yxxx;
+
+ case TYPE_MEM:
return Ym;
+
+ case TYPE_ADDR:
+ switch(a->name) {
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ return Yi32;
+ case NAME_AUTO:
+ case NAME_PARAM:
+ return Yiauto;
+ }
+
+ // DUFFZERO/DUFFCOPY encoding forgot to set a->index
+ // and got Yi32 in an earlier version of this code.
+ // Keep doing that until we fix yduff etc.
+ if(a->sym != nil && strncmp(a->sym->name, "runtime.duff", 12) == 0)
+ return Yi32;
+
+ if(a->sym != nil || a->name != NAME_NONE)
+ ctxt->diag("unexpected addr: %D", a);
+ // fall through
+
+ case TYPE_CONST:
+ case TYPE_TEXTSIZE:
+ if(a->sym != nil)
+ ctxt->diag("TYPE_CONST with symbol: %D", a);
+
+ v = a->offset;
+ if(v == 0)
+ return Yi0;
+ if(v == 1)
+ return Yi1;
+ if(v >= -128 && v <= 127)
+ return Yi8;
+ return Yi32;
}
- switch(a->type)
- {
- case D_AL:
+
+ if(a->type != TYPE_REG) {
+ ctxt->diag("unexpected addr1: type=%d %D", a->type, a);
+ return Yxxx;
+ }
+
+ switch(a->reg) {
+ case REG_AL:
return Yal;
- case D_AX:
+ case REG_AX:
return Yax;
- case D_CL:
- case D_DL:
- case D_BL:
- case D_AH:
- case D_CH:
- case D_DH:
- case D_BH:
+ case REG_CL:
+ case REG_DL:
+ case REG_BL:
+ case REG_AH:
+ case REG_CH:
+ case REG_DH:
+ case REG_BH:
return Yrb;
- case D_CX:
+ case REG_CX:
return Ycx;
- case D_DX:
- case D_BX:
+ case REG_DX:
+ case REG_BX:
return Yrx;
- case D_SP:
- case D_BP:
- case D_SI:
- case D_DI:
+ case REG_SP:
+ case REG_BP:
+ case REG_SI:
+ case REG_DI:
return Yrl;
- case D_F0+0:
+ case REG_F0+0:
return Yf0;
- case D_F0+1:
- case D_F0+2:
- case D_F0+3:
- case D_F0+4:
- case D_F0+5:
- case D_F0+6:
- case D_F0+7:
+ case REG_F0+1:
+ case REG_F0+2:
+ case REG_F0+3:
+ case REG_F0+4:
+ case REG_F0+5:
+ case REG_F0+6:
+ case REG_F0+7:
return Yrf;
- case D_X0+0:
- case D_X0+1:
- case D_X0+2:
- case D_X0+3:
- case D_X0+4:
- case D_X0+5:
- case D_X0+6:
- case D_X0+7:
+ case REG_X0+0:
+ case REG_X0+1:
+ case REG_X0+2:
+ case REG_X0+3:
+ case REG_X0+4:
+ case REG_X0+5:
+ case REG_X0+6:
+ case REG_X0+7:
return Yxr;
- case D_NONE:
- return Ynone;
-
- case D_CS: return Ycs;
- case D_SS: return Yss;
- case D_DS: return Yds;
- case D_ES: return Yes;
- case D_FS: return Yfs;
- case D_GS: return Ygs;
- case D_TLS: return Ytls;
+ case REG_CS: return Ycs;
+ case REG_SS: return Yss;
+ case REG_DS: return Yds;
+ case REG_ES: return Yes;
+ case REG_FS: return Yfs;
+ case REG_GS: return Ygs;
+ case REG_TLS: return Ytls;
- case D_GDTR: return Ygdtr;
- case D_IDTR: return Yidtr;
- case D_LDTR: return Yldtr;
- case D_MSW: return Ymsw;
- case D_TASK: return Ytask;
+ case REG_GDTR: return Ygdtr;
+ case REG_IDTR: return Yidtr;
+ case REG_LDTR: return Yldtr;
+ case REG_MSW: return Ymsw;
+ case REG_TASK: return Ytask;
- case D_CR+0: return Ycr0;
- case D_CR+1: return Ycr1;
- case D_CR+2: return Ycr2;
- case D_CR+3: return Ycr3;
- case D_CR+4: return Ycr4;
- case D_CR+5: return Ycr5;
- case D_CR+6: return Ycr6;
- case D_CR+7: return Ycr7;
+ case REG_CR+0: return Ycr0;
+ case REG_CR+1: return Ycr1;
+ case REG_CR+2: return Ycr2;
+ case REG_CR+3: return Ycr3;
+ case REG_CR+4: return Ycr4;
+ case REG_CR+5: return Ycr5;
+ case REG_CR+6: return Ycr6;
+ case REG_CR+7: return Ycr7;
- case D_DR+0: return Ydr0;
- case D_DR+1: return Ydr1;
- case D_DR+2: return Ydr2;
- case D_DR+3: return Ydr3;
- case D_DR+4: return Ydr4;
- case D_DR+5: return Ydr5;
- case D_DR+6: return Ydr6;
- case D_DR+7: return Ydr7;
+ case REG_DR+0: return Ydr0;
+ case REG_DR+1: return Ydr1;
+ case REG_DR+2: return Ydr2;
+ case REG_DR+3: return Ydr3;
+ case REG_DR+4: return Ydr4;
+ case REG_DR+5: return Ydr5;
+ case REG_DR+6: return Ydr6;
+ case REG_DR+7: return Ydr7;
- case D_TR+0: return Ytr0;
- case D_TR+1: return Ytr1;
- case D_TR+2: return Ytr2;
- case D_TR+3: return Ytr3;
- case D_TR+4: return Ytr4;
- case D_TR+5: return Ytr5;
- case D_TR+6: return Ytr6;
- case D_TR+7: return Ytr7;
+ case REG_TR+0: return Ytr0;
+ case REG_TR+1: return Ytr1;
+ case REG_TR+2: return Ytr2;
+ case REG_TR+3: return Ytr3;
+ case REG_TR+4: return Ytr4;
+ case REG_TR+5: return Ytr5;
+ case REG_TR+6: return Ytr6;
+ case REG_TR+7: return Ytr7;
- case D_EXTERN:
- case D_STATIC:
- case D_AUTO:
- case D_PARAM:
- return Ym;
-
- case D_CONST:
- case D_CONST2:
- case D_ADDR:
- if(a->sym == nil) {
- v = a->offset;
- if(v == 0)
- return Yi0;
- if(v == 1)
- return Yi1;
- if(v >= -128 && v <= 127)
- return Yi8;
- }
- return Yi32;
-
- case D_BRANCH:
- return Ybr;
}
return Yxxx;
}
@@ -1640,17 +1662,17 @@ asmidx(Link *ctxt, int scale, int index, int base)
default:
goto bad;
- case D_NONE:
+ case TYPE_NONE:
i = 4 << 3;
goto bas;
- case D_AX:
- case D_CX:
- case D_DX:
- case D_BX:
- case D_BP:
- case D_SI:
- case D_DI:
+ case REG_AX:
+ case REG_CX:
+ case REG_DX:
+ case REG_BX:
+ case REG_BP:
+ case REG_SI:
+ case REG_DI:
i = reg[index] << 3;
break;
}
@@ -1673,17 +1695,17 @@ bas:
switch(base) {
default:
goto bad;
- case D_NONE: /* must be mod=00 */
+ case REG_NONE: /* must be mod=00 */
i |= 5;
break;
- case D_AX:
- case D_CX:
- case D_DX:
- case D_BX:
- case D_SP:
- case D_BP:
- case D_SI:
- case D_DI:
+ case REG_AX:
+ case REG_CX:
+ case REG_DX:
+ case REG_BX:
+ case REG_SP:
+ case REG_BP:
+ case REG_SI:
+ case REG_DI:
i |= reg[base];
break;
}
@@ -1725,8 +1747,6 @@ relput4(Link *ctxt, Prog *p, Addr *a)
static int32
vaddr(Link *ctxt, Prog *p, Addr *a, Reloc *r)
{
- int t;
- int32 v;
LSym *s;
USED(p);
@@ -1734,13 +1754,9 @@ vaddr(Link *ctxt, Prog *p, Addr *a, Reloc *r)
if(r != nil)
memset(r, 0, sizeof *r);
- t = a->type;
- v = a->offset;
- if(t == D_ADDR)
- t = a->index;
- switch(t) {
- case D_STATIC:
- case D_EXTERN:
+ switch(a->name) {
+ case NAME_STATIC:
+ case NAME_EXTERN:
s = a->sym;
if(s != nil) {
if(r == nil) {
@@ -1751,12 +1767,13 @@ vaddr(Link *ctxt, Prog *p, Addr *a, Reloc *r)
r->siz = 4;
r->off = -1;
r->sym = s;
- r->add = v;
- v = 0;
+ r->add = a->offset;
+ return 0;
}
- break;
+ return a->offset;
+ }
- case D_INDIR+D_TLS:
+ if((a->type == TYPE_MEM || a->type == TYPE_ADDR) && a->reg == REG_TLS) {
if(r == nil) {
ctxt->diag("need reloc for %D", a);
sysfatal("bad code");
@@ -1764,113 +1781,120 @@ vaddr(Link *ctxt, Prog *p, Addr *a, Reloc *r)
r->type = R_TLS_LE;
r->siz = 4;
r->off = -1; // caller must fill in
- r->add = v;
- v = 0;
- break;
+ r->add = a->offset;
+ return 0;
}
- return v;
+
+ return a->offset;
}
static void
asmand(Link *ctxt, Prog *p, Addr *a, int r)
{
int32 v;
- int t, scale;
+ int base;
Reloc rel;
USED(p);
v = a->offset;
- t = a->type;
rel.siz = 0;
- if(a->index != D_NONE && a->index != D_TLS) {
- if(t < D_INDIR || t >= 2*D_INDIR) {
- switch(t) {
- default:
- goto bad;
- case D_STATIC:
- case D_EXTERN:
- t = D_NONE;
- v = vaddr(ctxt, p, a, &rel);
- break;
- case D_AUTO:
- case D_PARAM:
- t = D_SP;
- break;
- }
- } else
- t -= D_INDIR;
- if(t == D_NONE) {
+ switch(a->type) {
+ case TYPE_ADDR:
+ if(a->name == NAME_NONE)
+ ctxt->diag("unexpected TYPE_ADDR with NAME_NONE");
+ if(a->index == REG_TLS)
+ ctxt->diag("unexpected TYPE_ADDR with index==REG_TLS");
+ goto bad;
+
+ case TYPE_REG:
+ if((a->reg < REG_AL || REG_F7 < a->reg) && (a->reg < REG_X0 || REG_X0+7 < a->reg))
+ goto bad;
+ if(v)
+ goto bad;
+ *ctxt->andptr++ = (3 << 6) | (reg[a->reg] << 0) | (r << 3);
+ return;
+ }
+
+ if(a->type != TYPE_MEM)
+ goto bad;
+
+ if(a->index != REG_NONE && a->index != REG_TLS) {
+ base = a->reg;
+ switch(a->name) {
+ case NAME_EXTERN:
+ case NAME_STATIC:
+ base = REG_NONE;
+ v = vaddr(ctxt, p, a, &rel);
+ break;
+ case NAME_AUTO:
+ case NAME_PARAM:
+ base = REG_SP;
+ break;
+ }
+
+ if(base == REG_NONE) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
goto putrelv;
}
- if(v == 0 && rel.siz == 0 && t != D_BP) {
+ if(v == 0 && rel.siz == 0 && base != REG_BP) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
*ctxt->andptr++ = (1 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
*ctxt->andptr++ = v;
return;
}
*ctxt->andptr++ = (2 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, a->scale, a->index, t);
+ asmidx(ctxt, a->scale, a->index, base);
goto putrelv;
}
- if(t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7) {
- if(v)
- goto bad;
- *ctxt->andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
- return;
+
+ base = a->reg;
+ switch(a->name) {
+ case NAME_STATIC:
+ case NAME_EXTERN:
+ base = REG_NONE;
+ v = vaddr(ctxt, p, a, &rel);
+ break;
+ case NAME_AUTO:
+ case NAME_PARAM:
+ base = REG_SP;
+ break;
}
- scale = a->scale;
- if(t < D_INDIR || t >= 2*D_INDIR) {
- switch(a->type) {
- default:
- goto bad;
- case D_STATIC:
- case D_EXTERN:
- t = D_NONE;
- v = vaddr(ctxt, p, a, &rel);
- break;
- case D_AUTO:
- case D_PARAM:
- t = D_SP;
- break;
- }
- scale = 1;
- } else
- t -= D_INDIR;
- if(t == D_TLS)
+ if(base == REG_TLS)
v = vaddr(ctxt, p, a, &rel);
-
- if(t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS) {
+
+ if(base == REG_NONE || (REG_CS <= base && base <= REG_GS) || base == REG_TLS) {
*ctxt->andptr++ = (0 << 6) | (5 << 0) | (r << 3);
goto putrelv;
}
- if(t == D_SP) {
+
+ if(base == REG_SP) {
if(v == 0 && rel.siz == 0) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, scale, D_NONE, t);
+ asmidx(ctxt, a->scale, REG_NONE, base);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
*ctxt->andptr++ = (1 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, scale, D_NONE, t);
+ asmidx(ctxt, a->scale, REG_NONE, base);
*ctxt->andptr++ = v;
return;
}
*ctxt->andptr++ = (2 << 6) | (4 << 0) | (r << 3);
- asmidx(ctxt, scale, D_NONE, t);
+ asmidx(ctxt, a->scale, REG_NONE, base);
goto putrelv;
}
- if(t >= D_AX && t <= D_DI) {
- if(a->index == D_TLS) {
+
+ if(REG_AX <= base && base <= REG_DI) {
+ if(a->index == REG_TLS) {
memset(&rel, 0, sizeof rel);
rel.type = R_TLS_IE;
rel.siz = 4;
@@ -1878,17 +1902,17 @@ asmand(Link *ctxt, Prog *p, Addr *a, int r)
rel.add = v;
v = 0;
}
- if(v == 0 && rel.siz == 0 && t != D_BP) {
- *ctxt->andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
+ if(v == 0 && rel.siz == 0 && base != REG_BP) {
+ *ctxt->andptr++ = (0 << 6) | (reg[base] << 0) | (r << 3);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
- ctxt->andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
+ ctxt->andptr[0] = (1 << 6) | (reg[base] << 0) | (r << 3);
ctxt->andptr[1] = v;
ctxt->andptr += 2;
return;
}
- *ctxt->andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
+ *ctxt->andptr++ = (2 << 6) | (reg[base] << 0) | (r << 3);
goto putrelv;
}
goto bad;
@@ -2028,7 +2052,7 @@ static uchar ymovtab[] =
};
// byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
-// which is not referenced in a->type.
+// which is not referenced in a.
// If a is empty, it returns BX to account for MULB-like instructions
// that might use DX and AX.
static int
@@ -2038,57 +2062,60 @@ byteswapreg(Link *ctxt, Addr *a)
cana = canb = canc = cand = 1;
- switch(a->type) {
- case D_NONE:
+ if(a->type == TYPE_NONE)
cana = cand = 0;
- break;
- case D_AX:
- case D_AL:
- case D_AH:
- case D_INDIR+D_AX:
- cana = 0;
- break;
- case D_BX:
- case D_BL:
- case D_BH:
- case D_INDIR+D_BX:
- canb = 0;
- break;
- case D_CX:
- case D_CL:
- case D_CH:
- case D_INDIR+D_CX:
- canc = 0;
- break;
- case D_DX:
- case D_DL:
- case D_DH:
- case D_INDIR+D_DX:
- cand = 0;
- break;
+
+ if(a->type == TYPE_REG || ((a->type == TYPE_MEM || a->type == TYPE_ADDR) && a->name == NAME_NONE)) {
+ switch(a->reg) {
+ case REG_NONE:
+ cana = cand = 0;
+ break;
+ case REG_AX:
+ case REG_AL:
+ case REG_AH:
+ cana = 0;
+ break;
+ case REG_BX:
+ case REG_BL:
+ case REG_BH:
+ canb = 0;
+ break;
+ case REG_CX:
+ case REG_CL:
+ case REG_CH:
+ canc = 0;
+ break;
+ case REG_DX:
+ case REG_DL:
+ case REG_DH:
+ cand = 0;
+ break;
+ }
}
- switch(a->index) {
- case D_AX:
- cana = 0;
- break;
- case D_BX:
- canb = 0;
- break;
- case D_CX:
- canc = 0;
- break;
- case D_DX:
- cand = 0;
- break;
+ if(a->type == TYPE_MEM || a->type == TYPE_ADDR) {
+ switch(a->index) {
+ case REG_AX:
+ cana = 0;
+ break;
+ case REG_BX:
+ canb = 0;
+ break;
+ case REG_CX:
+ canc = 0;
+ break;
+ case REG_DX:
+ cand = 0;
+ break;
+ }
}
if(cana)
- return D_AX;
+ return REG_AX;
if(canb)
- return D_BX;
+ return REG_BX;
if(canc)
- return D_CX;
+ return REG_CX;
if(cand)
- return D_DX;
+ return REG_DX;
ctxt->diag("impossible byte register");
sysfatal("bad code");
@@ -2098,16 +2125,15 @@ byteswapreg(Link *ctxt, Addr *a)
static void
subreg(Prog *p, int from, int to)
{
-
if(0 /* debug['Q'] */)
print("\n%P s/%R/%R/\n", p, from, to);
- if(p->from.type == from) {
- p->from.type = to;
+ if(p->from.reg == from) {
+ p->from.reg = to;
p->ft = 0;
}
- if(p->to.type == from) {
- p->to.type = to;
+ if(p->to.reg == from) {
+ p->to.reg = to;
p->tt = 0;
}
@@ -2120,16 +2146,6 @@ subreg(Prog *p, int from, int to)
p->tt = 0;
}
- from += D_INDIR;
- if(p->from.type == from) {
- p->from.type = to+D_INDIR;
- p->ft = 0;
- }
- if(p->to.type == from) {
- p->to.type = to+D_INDIR;
- p->tt = 0;
- }
-
if(0 /* debug['Q'] */)
print("%P\n", p);
}
@@ -2179,9 +2195,9 @@ doasm(Link *ctxt, Prog *p)
*ctxt->andptr++ = pre;
if(p->ft == 0)
- p->ft = oclass(&p->from);
+ p->ft = oclass(ctxt, &p->from);
if(p->tt == 0)
- p->tt = oclass(&p->to);
+ p->tt = oclass(ctxt, &p->to);
ft = p->ft * Ymax;
tt = p->tt * Ymax;
@@ -2239,48 +2255,46 @@ found:
case Zlitm_r:
for(; op = o->op[z]; z++)
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case Zm_r:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case Zm2_r:
*ctxt->andptr++ = op;
*ctxt->andptr++ = o->op[z+1];
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case Zm_r_xm:
mediaop(ctxt, o, op, t[3], z);
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case Zm_r_i_xm:
mediaop(ctxt, o, op, t[3], z);
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
*ctxt->andptr++ = p->to.offset;
break;
case Zibm_r:
while ((op = o->op[z++]) != 0)
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
*ctxt->andptr++ = p->to.offset;
break;
case Zaut_r:
*ctxt->andptr++ = 0x8d; /* leal */
- if(p->from.type != D_ADDR)
+ if(p->from.type != TYPE_ADDR)
ctxt->diag("asmins: Zaut sb type ADDR");
- p->from.type = p->from.index;
- p->from.index = D_NONE;
+ p->from.type = TYPE_MEM;
p->ft = 0;
- asmand(ctxt, p, &p->from, reg[p->to.type]);
- p->from.index = p->from.type;
- p->from.type = D_ADDR;
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
+ p->from.type = TYPE_ADDR;
p->ft = 0;
break;
@@ -2291,17 +2305,17 @@ found:
case Zr_m:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->to, reg[p->from.type]);
+ asmand(ctxt, p, &p->to, reg[p->from.reg]);
break;
case Zr_m_xm:
mediaop(ctxt, o, op, t[3], z);
- asmand(ctxt, p, &p->to, reg[p->from.type]);
+ asmand(ctxt, p, &p->to, reg[p->from.reg]);
break;
case Zr_m_i_xm:
mediaop(ctxt, o, op, t[3], z);
- asmand(ctxt, p, &p->to, reg[p->from.type]);
+ asmand(ctxt, p, &p->to, reg[p->from.reg]);
*ctxt->andptr++ = p->from.offset;
break;
@@ -2340,12 +2354,12 @@ found:
break;
case Zib_rp:
- *ctxt->andptr++ = op + reg[p->to.type];
+ *ctxt->andptr++ = op + reg[p->to.reg];
*ctxt->andptr++ = vaddr(ctxt, p, &p->from, nil);
break;
case Zil_rp:
- *ctxt->andptr++ = op + reg[p->to.type];
+ *ctxt->andptr++ = op + reg[p->to.reg];
if(o->prefix == Pe) {
v = vaddr(ctxt, p, &p->from, nil);
*ctxt->andptr++ = v;
@@ -2357,7 +2371,7 @@ found:
case Zib_rr:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->to, reg[p->to.type]);
+ asmand(ctxt, p, &p->to, reg[p->to.reg]);
*ctxt->andptr++ = vaddr(ctxt, p, &p->from, nil);
break;
@@ -2398,7 +2412,7 @@ found:
case Zil_rr:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->to, reg[p->to.type]);
+ asmand(ctxt, p, &p->to, reg[p->to.reg]);
if(o->prefix == Pe) {
v = vaddr(ctxt, p, &p->from, nil);
*ctxt->andptr++ = v;
@@ -2409,16 +2423,16 @@ found:
break;
case Z_rp:
- *ctxt->andptr++ = op + reg[p->to.type];
+ *ctxt->andptr++ = op + reg[p->to.reg];
break;
case Zrp_:
- *ctxt->andptr++ = op + reg[p->from.type];
+ *ctxt->andptr++ = op + reg[p->from.reg];
break;
case Zclr:
*ctxt->andptr++ = op;
- asmand(ctxt, p, &p->to, reg[p->to.type]);
+ asmand(ctxt, p, &p->to, reg[p->to.reg]);
break;
case Zcall:
@@ -2570,9 +2584,9 @@ bad:
* instruction with the operands renamed.
*/
pp = *p;
- z = p->from.type;
- if(z >= D_BP && z <= D_DI) {
- if((breg = byteswapreg(ctxt, &p->to)) != D_AX) {
+ z = p->from.reg;
+ if(p->from.type == TYPE_REG && z >= REG_BP && z <= REG_DI) {
+ if((breg = byteswapreg(ctxt, &p->to)) != REG_AX) {
*ctxt->andptr++ = 0x87; /* xchg lhs,bx */
asmand(ctxt, p, &p->from, reg[breg]);
subreg(&pp, z, breg);
@@ -2581,15 +2595,15 @@ bad:
asmand(ctxt, p, &p->from, reg[breg]);
} else {
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
- subreg(&pp, z, D_AX);
+ subreg(&pp, z, REG_AX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
}
return;
}
- z = p->to.type;
- if(z >= D_BP && z <= D_DI) {
- if((breg = byteswapreg(ctxt, &p->from)) != D_AX) {
+ z = p->to.reg;
+ if(p->to.type == TYPE_REG && z >= REG_BP && z <= REG_DI) {
+ if((breg = byteswapreg(ctxt, &p->from)) != REG_AX) {
*ctxt->andptr++ = 0x87; /* xchg rhs,bx */
asmand(ctxt, p, &p->to, reg[breg]);
subreg(&pp, z, breg);
@@ -2598,13 +2612,13 @@ bad:
asmand(ctxt, p, &p->to, reg[breg]);
} else {
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
- subreg(&pp, z, D_AX);
+ subreg(&pp, z, REG_AX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
}
return;
}
- ctxt->diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
+ ctxt->diag("doasm: notfound t2=%d from=%d to=%d %P", t[2], p->ft, p->tt, p);
return;
mfound:
@@ -2646,44 +2660,51 @@ mfound:
switch(p->to.index) {
default:
goto bad;
- case D_DS:
+ case REG_DS:
*ctxt->andptr++ = 0xc5;
break;
- case D_SS:
+ case REG_SS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb2;
break;
- case D_ES:
+ case REG_ES:
*ctxt->andptr++ = 0xc4;
break;
- case D_FS:
+ case REG_FS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb4;
break;
- case D_GS:
+ case REG_GS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb5;
break;
}
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case 6: /* double shift */
- z = p->from.type;
- switch(z) {
+ switch(p->from.type) {
default:
goto bad;
- case D_CONST:
+
+ case TYPE_CONST:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = t[4];
asmand(ctxt, p, &p->to, reg[p->from.index]);
*ctxt->andptr++ = p->from.offset;
break;
- case D_CL:
- case D_CX:
- *ctxt->andptr++ = 0x0f;
- *ctxt->andptr++ = t[5];
- asmand(ctxt, p, &p->to, reg[p->from.index]);
+
+ case TYPE_REG:
+ switch(p->from.reg) {
+ default:
+ goto bad;
+ case REG_CL:
+ case REG_CX:
+ *ctxt->andptr++ = 0x0f;
+ *ctxt->andptr++ = t[5];
+ asmand(ctxt, p, &p->to, reg[p->from.index]);
+ break;
+ }
break;
}
break;
@@ -2695,7 +2716,7 @@ mfound:
} else
*ctxt->andptr++ = t[4];
*ctxt->andptr++ = t[5];
- asmand(ctxt, p, &p->from, reg[p->to.type]);
+ asmand(ctxt, p, &p->from, reg[p->to.reg]);
break;
case 8: /* mov tls, r */
@@ -2711,37 +2732,40 @@ mfound:
case Hnacl:
// ELF TLS base is 0(GS).
pp.from = p->from;
- pp.from.type = D_INDIR+D_GS;
+ pp.from.type = TYPE_MEM;
+ pp.from.reg = REG_GS;
pp.from.offset = 0;
- pp.from.index = D_NONE;
+ pp.from.index = REG_NONE;
pp.from.scale = 0;
*ctxt->andptr++ = 0x65; // GS
*ctxt->andptr++ = 0x8B;
- asmand(ctxt, p, &pp.from, reg[p->to.type]);
+ asmand(ctxt, p, &pp.from, reg[p->to.reg]);
break;
case Hplan9:
if(ctxt->plan9privates == nil)
ctxt->plan9privates = linklookup(ctxt, "_privates", 0);
memset(&pp.from, 0, sizeof pp.from);
- pp.from.type = D_EXTERN;
+ pp.from.type = TYPE_MEM;
+ pp.from.name = NAME_EXTERN;
pp.from.sym = ctxt->plan9privates;
pp.from.offset = 0;
- pp.from.index = D_NONE;
+ pp.from.index = REG_NONE;
*ctxt->andptr++ = 0x8B;
- asmand(ctxt, p, &pp.from, reg[p->to.type]);
+ asmand(ctxt, p, &pp.from, reg[p->to.reg]);
break;
case Hwindows:
// Windows TLS base is always 0x14(FS).
pp.from = p->from;
- pp.from.type = D_INDIR+D_FS;
+ pp.from.type = TYPE_MEM;
+ pp.from.reg = REG_FS;
pp.from.offset = 0x14;
- pp.from.index = D_NONE;
+ pp.from.index = REG_NONE;
pp.from.scale = 0;
*ctxt->andptr++ = 0x64; // FS
*ctxt->andptr++ = 0x8B;
- asmand(ctxt, p, &pp.from, reg[p->to.type]);
+ asmand(ctxt, p, &pp.from, reg[p->to.reg]);
break;
}
break;
@@ -2779,9 +2803,9 @@ asmins(Link *ctxt, Prog *p)
return;
case ACALL:
case AJMP:
- if(D_AX <= p->to.type && p->to.type <= D_DI) {
+ if(p->to.type == TYPE_REG && REG_AX <= p->to.reg && p->to.reg <= REG_DI) {
*ctxt->andptr++ = 0x83;
- *ctxt->andptr++ = 0xe0 | (p->to.type - D_AX);
+ *ctxt->andptr++ = 0xe0 | (p->to.reg - REG_AX);
*ctxt->andptr++ = 0xe0;
}
break;
diff --git a/src/liblink/list8.c b/src/liblink/list8.c
index 63d96b9f97..60f03206bd 100644
--- a/src/liblink/list8.c
+++ b/src/liblink/list8.c
@@ -108,41 +108,38 @@ 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) {
+
+ switch(a->type) {
default:
- if(a->offset)
- sprint(str, "$%lld,%R", a->offset, i);
- else
- sprint(str, "%R", i);
+ sprint(str, "type=%d", a->type);
break;
- case D_NONE:
+ case TYPE_NONE:
str[0] = 0;
break;
+
+ case TYPE_REG:
+ // TODO(rsc): This special case is for instructions like
+ // PINSRQ CX,$1,X6
+ // where the $1 is included in the p->to Addr.
+ // Move into a new field.
+ if(a->offset != 0) {
+ sprint(str, "$%lld,%R", a->offset, a->reg);
+ break;
+ }
+ sprint(str, "%R", a->reg);
+ // TODO(rsc): This special case is for SHRQ $32, AX:DX, which encodes as
+ // SHRQ $32(DX*0), AX
+ // Remove.
+ if(a->index != REG_NONE) {
+ sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+ strcat(str, s);
+ }
+ break;
- case D_BRANCH:
+ case TYPE_BRANCH:
if(a->sym != nil)
sprint(str, "%s(SB)", a->sym->name);
else if(bigP != nil && bigP->pcond != nil)
@@ -153,67 +150,78 @@ Dconv(Fmt *fp)
sprint(str, "%lld(PC)", 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);
+ case TYPE_MEM:
+ switch(a->name) {
+ default:
+ sprint(str, "name=%d", a->name);
+ break;
+ case NAME_NONE:
+ if(a->offset)
+ sprint(str, "%lld(%R)", a->offset, a->reg);
+ else
+ sprint(str, "(%R)", a->reg);
+ break;
+ case NAME_EXTERN:
+ sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
+ break;
+ case NAME_STATIC:
+ sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
+ break;
+ case NAME_AUTO:
+ if(a->sym)
+ sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
+ else
+ sprint(str, "%lld(SP)", a->offset);
+ break;
+ case NAME_PARAM:
+ if(a->sym)
+ sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
+ else
+ sprint(str, "%lld(FP)", a->offset);
+ break;
+ }
+ if(a->index != REG_NONE) {
+ sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+ strcat(str, s);
+ }
break;
- case D_CONST:
+ case TYPE_CONST:
sprint(str, "$%lld", a->offset);
+ // TODO(rsc): This special case is for SHRQ $32, AX:DX, which encodes as
+ // SHRQ $32(DX*0), AX
+ // Remove.
+ if(a->index != REG_NONE) {
+ sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
+ strcat(str, s);
+ }
break;
- case D_CONST2:
- if(!(fp->flags & FmtLong)) {
- // D_CONST2 outside of ATEXT should not happen
- sprint(str, "!!$%lld-%d", a->offset, a->offset2);
- }
+ case TYPE_TEXTSIZE:
+ sprint(str, "$%lld-%d", a->offset, a->u.argsize);
break;
- case D_FCONST:
+ case TYPE_FCONST:
sprint(str, "$(%.17g)", a->u.dval);
break;
- case D_SCONST:
+ case TYPE_SCONST:
sprint(str, "$\"%$\"", a->u.sval);
break;
- case D_ADDR:
- a->type = a->index;
- a->index = D_NONE;
+ case TYPE_ADDR:
+ a->type = TYPE_MEM;
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);
+ a->type = TYPE_ADDR;
+ break;
}
-conv:
+
return fmtstrcpy(fp, str);
}
static char* regstr[] =
{
- "AL", /* [D_AL] */
+ "AL", /* [REG_AL] */
"CL",
"DL",
"BL",
@@ -222,7 +230,7 @@ static char* regstr[] =
"DH",
"BH",
- "AX", /* [D_AX] */
+ "AX", /* [REG_AX] */
"CX",
"DX",
"BX",
@@ -231,7 +239,7 @@ static char* regstr[] =
"SI",
"DI",
- "F0", /* [D_F0] */
+ "F0", /* [REG_F0] */
"F1",
"F2",
"F3",
@@ -240,20 +248,20 @@ static char* regstr[] =
"F6",
"F7",
- "CS", /* [D_CS] */
+ "CS", /* [REG_CS] */
"SS",
"DS",
"ES",
"FS",
"GS",
- "GDTR", /* [D_GDTR] */
- "IDTR", /* [D_IDTR] */
- "LDTR", /* [D_LDTR] */
- "MSW", /* [D_MSW] */
- "TASK", /* [D_TASK] */
+ "GDTR", /* [REG_GDTR] */
+ "IDTR", /* [REG_IDTR] */
+ "LDTR", /* [REG_LDTR] */
+ "MSW", /* [REG_MSW] */
+ "TASK", /* [REG_TASK] */
- "CR0", /* [D_CR] */
+ "CR0", /* [REG_CR] */
"CR1",
"CR2",
"CR3",
@@ -262,7 +270,7 @@ static char* regstr[] =
"CR6",
"CR7",
- "DR0", /* [D_DR] */
+ "DR0", /* [REG_DR] */
"DR1",
"DR2",
"DR3",
@@ -271,7 +279,7 @@ static char* regstr[] =
"DR6",
"DR7",
- "TR0", /* [D_TR] */
+ "TR0", /* [REG_TR] */
"TR1",
"TR2",
"TR3",
@@ -280,7 +288,7 @@ static char* regstr[] =
"TR6",
"TR7",
- "X0", /* [D_X0] */
+ "X0", /* [REG_X0] */
"X1",
"X2",
"X3",
@@ -289,8 +297,8 @@ static char* regstr[] =
"X6",
"X7",
- "TLS", /* [D_TLS] */
- "NONE", /* [D_NONE] */
+ "TLS", /* [REG_TLS] */
+ "MAXREG", /* [MAXREG] */
};
static int
@@ -300,8 +308,10 @@ Rconv(Fmt *fp)
int r;
r = va_arg(fp->args, int);
- if(r >= D_AL && r <= D_NONE)
- sprint(str, "%s", regstr[r-D_AL]);
+ if(r == REG_NONE)
+ return fmtstrcpy(fp, "NONE");
+ if(r >= REG_AL && r-REG_AL < nelem(regstr))
+ sprint(str, "%s", regstr[r-REG_AL]);
else
sprint(str, "gok(%d)", r);
diff --git a/src/liblink/obj8.c b/src/liblink/obj8.c
index 4e28709b81..cceeeb1b87 100644
--- a/src/liblink/obj8.c
+++ b/src/liblink/obj8.c
@@ -39,29 +39,18 @@ static Prog zprg = {
.back = 2,
.as = AGOK,
.from = {
- .type = D_NONE,
- .index = D_NONE,
+ .type = TYPE_NONE,
+ .index = REG_NONE,
.scale = 1,
},
.to = {
- .type = D_NONE,
- .index = D_NONE,
+ .type = TYPE_NONE,
+ .index = REG_NONE,
.scale = 1,
},
};
static int
-symtype(Addr *a)
-{
- int t;
-
- t = a->type;
- if(t == D_ADDR)
- t = a->index;
- return t;
-}
-
-static int
isdata(Prog *p)
{
return p->as == ADATA || p->as == AGLOBL;
@@ -120,20 +109,22 @@ progedit(Link *ctxt, Prog *p)
// become
// NOP
// ... off(TLS) ...
- if(p->as == AMOVL && p->from.type == D_TLS && D_AX <= p->to.type && p->to.type <= D_DI) {
+ if(p->as == AMOVL && p->from.type == TYPE_REG && p->from.reg == REG_TLS && p->to.type == TYPE_REG && REG_AX <= p->to.reg && p->to.reg <= REG_DI) {
p->as = ANOP;
- p->from.type = D_NONE;
- p->to.type = D_NONE;
+ p->from.type = TYPE_NONE;
+ p->to.type = TYPE_NONE;
}
- if(p->from.index == D_TLS && D_INDIR+D_AX <= p->from.type && p->from.type <= D_INDIR+D_DI) {
- p->from.type = D_INDIR+D_TLS;
+ if(p->from.type == TYPE_MEM && p->from.index == REG_TLS && REG_AX <= p->from.reg && p->from.reg <= REG_DI) {
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_TLS;
p->from.scale = 0;
- p->from.index = D_NONE;
+ p->from.index = REG_NONE;
}
- if(p->to.index == D_TLS && D_INDIR+D_AX <= p->to.type && p->to.type <= D_INDIR+D_DI) {
- p->to.type = D_INDIR+D_TLS;
+ if(p->to.type == TYPE_MEM && p->to.index == REG_TLS && REG_AX <= p->to.reg && p->to.reg <= REG_DI) {
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_TLS;
p->to.scale = 0;
- p->to.index = D_NONE;
+ p->to.index = REG_NONE;
}
} else {
// As a courtesy to the C compilers, rewrite TLS local exec load as TLS initial exec load.
@@ -143,35 +134,36 @@ progedit(Link *ctxt, Prog *p)
// MOVL TLS, BX
// MOVL off(BX)(TLS*1), BX
// This allows the C compilers to emit references to m and g using the direct off(TLS) form.
- if(p->as == AMOVL && p->from.type == D_INDIR+D_TLS && D_AX <= p->to.type && p->to.type <= D_DI) {
+ if(p->as == AMOVL && p->from.type == TYPE_MEM && p->from.reg == REG_TLS && p->to.type == TYPE_REG && REG_AX <= p->to.reg && p->to.reg <= REG_DI) {
q = appendp(ctxt, p);
q->as = p->as;
- q->from = p->from;
- q->from.type = D_INDIR + p->to.type;
- q->from.index = D_TLS;
+ q->from.type = TYPE_MEM;
+ q->from.reg = p->to.reg;
+ q->from.index = REG_TLS;
q->from.scale = 2; // TODO: use 1
q->to = p->to;
- p->from.type = D_TLS;
- p->from.index = D_NONE;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_TLS;
+ p->from.index = REG_NONE;
p->from.offset = 0;
}
}
// TODO: Remove.
if(ctxt->headtype == Hplan9) {
- if(p->from.scale == 1 && p->from.index == D_TLS)
+ if(p->from.scale == 1 && p->from.index == REG_TLS)
p->from.scale = 2;
- if(p->to.scale == 1 && p->to.index == D_TLS)
+ if(p->to.scale == 1 && p->to.index == REG_TLS)
p->to.scale = 2;
}
- // Rewrite CALL/JMP/RET to symbol as D_BRANCH.
+ // Rewrite CALL/JMP/RET to symbol as TYPE_BRANCH.
switch(p->as) {
case ACALL:
case AJMP:
case ARET:
- if((p->to.type == D_EXTERN || p->to.type == D_STATIC) && p->to.sym != nil)
- p->to.type = D_BRANCH;
+ if(p->to.type == TYPE_MEM && (p->to.name == NAME_EXTERN || p->to.name == NAME_STATIC) && p->to.sym != nil)
+ p->to.type = TYPE_BRANCH;
break;
}
@@ -179,13 +171,11 @@ progedit(Link *ctxt, Prog *p)
switch(p->as) {
case AMOVSS:
// Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
- if(p->from.type == D_FCONST)
+ if(p->from.type == TYPE_FCONST)
if(p->from.u.dval == 0)
- if(p->to.type >= D_X0)
- if(p->to.type <= D_X7) {
+ if(p->to.type == TYPE_REG && REG_X0 <= p->to.reg && p->to.reg <= REG_X7) {
p->as = AXORPS;
- p->from.type = p->to.type;
- p->from.index = p->to.index;
+ p->from = p->to;
break;
}
// fallthrough
@@ -205,7 +195,7 @@ progedit(Link *ctxt, Prog *p)
case ADIVSS:
case ACOMISS:
case AUCOMISS:
- if(p->from.type == D_FCONST) {
+ if(p->from.type == TYPE_FCONST) {
uint32 i32;
float32 f32;
f32 = p->from.u.dval;
@@ -217,7 +207,8 @@ progedit(Link *ctxt, Prog *p)
adduint32(ctxt, s, i32);
s->reachable = 0;
}
- p->from.type = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
@@ -225,13 +216,11 @@ progedit(Link *ctxt, Prog *p)
case AMOVSD:
// Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
- if(p->from.type == D_FCONST)
+ if(p->from.type == TYPE_FCONST)
if(p->from.u.dval == 0)
- if(p->to.type >= D_X0)
- if(p->to.type <= D_X7) {
+ if(p->to.type == TYPE_REG && REG_X0 <= p->to.reg && p->to.reg <= REG_X7) {
p->as = AXORPS;
- p->from.type = p->to.type;
- p->from.index = p->to.index;
+ p->from = p->to;
break;
}
// fallthrough
@@ -251,7 +240,7 @@ progedit(Link *ctxt, Prog *p)
case ADIVSD:
case ACOMISD:
case AUCOMISD:
- if(p->from.type == D_FCONST) {
+ if(p->from.type == TYPE_FCONST) {
uint64 i64;
memmove(&i64, &p->from.u.dval, 8);
sprint(literal, "$f64.%016llux", i64);
@@ -261,7 +250,8 @@ progedit(Link *ctxt, Prog *p)
adduint64(ctxt, s, i64);
s->reachable = 0;
}
- p->from.type = D_EXTERN;
+ p->from.type = TYPE_MEM;
+ p->from.name = NAME_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
@@ -283,7 +273,7 @@ static Prog* load_g_cx(Link*, Prog*);
static Prog* stacksplit(Link*, Prog*, int32, int, Prog**);
static void
-addstacksplit(Link *ctxt, LSym *cursym)
+preprocess(Link *ctxt, LSym *cursym)
{
Prog *p, *q, *p1, *p2;
int32 autoffset, deltasp;
@@ -308,7 +298,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
autoffset = 0;
cursym->locals = autoffset;
- cursym->args = p->to.offset2;
+ cursym->args = p->to.u.argsize;
q = nil;
@@ -322,7 +312,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
if(autoffset) {
p = appendp(ctxt, p);
p->as = AADJSP;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = autoffset;
p->spadj = autoffset;
} else {
@@ -358,41 +348,51 @@ addstacksplit(Link *ctxt, LSym *cursym)
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_INDIR+D_CX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_CX;
p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
- p->to.type = D_BX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_BX;
p = appendp(ctxt, p);
p->as = ATESTL;
- p->from.type = D_BX;
- p->to.type = D_BX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_BX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_BX;
p = appendp(ctxt, p);
p->as = AJEQ;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p1 = p;
p = appendp(ctxt, p);
p->as = ALEAL;
- p->from.type = D_INDIR+D_SP;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
p->from.offset = autoffset+4;
- p->to.type = D_DI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_DI;
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_INDIR+D_BX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_BX;
p->from.offset = 0; // Panic.argp
- p->to.type = D_DI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_DI;
p = appendp(ctxt, p);
p->as = AJNE;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p2 = p;
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_SP;
- p->to.type = D_INDIR+D_BX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SP;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_BX;
p->to.offset = 0; // Panic.argp
p = appendp(ctxt, p);
@@ -407,20 +407,24 @@ addstacksplit(Link *ctxt, LSym *cursym)
// false positives in garbage collection.
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_SP;
- p->to.type = D_DI;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_DI;
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = autoffset/4;
- p->to.type = D_CX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_CX;
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 0;
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = AREP;
@@ -430,15 +434,15 @@ addstacksplit(Link *ctxt, LSym *cursym)
}
for(; p != nil; p = p->link) {
- a = p->from.type;
- if(a == D_AUTO)
+ a = p->from.name;
+ if(a == NAME_AUTO)
p->from.offset += deltasp;
- if(a == D_PARAM)
+ if(a == NAME_PARAM)
p->from.offset += deltasp + 4;
- a = p->to.type;
- if(a == D_AUTO)
+ a = p->to.name;
+ if(a == NAME_AUTO)
p->to.offset += deltasp;
- if(a == D_PARAM)
+ if(a == NAME_PARAM)
p->to.offset += deltasp + 4;
switch(p->as) {
@@ -473,7 +477,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
if(autoffset) {
p->as = AADJSP;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = -autoffset;
p->spadj = -autoffset;
p = appendp(ctxt, p);
@@ -500,16 +504,18 @@ load_g_cx(Link *ctxt, Prog *p)
Prog *next;
p->as = AMOVL;
- p->from.type = D_INDIR+D_TLS;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_TLS;
p->from.offset = 0;
- p->to.type = D_CX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_CX;
next = p->link;
progedit(ctxt, p);
while(p->link != next)
p = p->link;
- if(p->from.index == D_TLS)
+ if(p->from.index == REG_TLS)
p->from.scale = 2;
return p;
@@ -534,19 +540,21 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
// catches out-of-sync stack guard info.
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_INDIR+D_CX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_CX;
p->from.offset = 4;
- p->to.type = D_SP;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SP;
p = appendp(ctxt, p);
p->as = AJCC;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.offset = 4;
q1 = p;
p = appendp(ctxt, p);
p->as = AINT;
- p->from.type = D_CONST;
+ p->from.type = TYPE_CONST;
p->from.offset = 3;
p = appendp(ctxt, p);
@@ -560,8 +568,10 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
// CMPL SP, stackguard
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_SP;
- p->to.type = D_INDIR+D_CX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SP;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_CX;
p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
@@ -571,14 +581,18 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
// CMPL AX, stackguard
p = appendp(ctxt, p);
p->as = ALEAL;
- p->from.type = D_INDIR+D_SP;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
p->from.offset = -(framesize-StackSmall);
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_AX;
- p->to.type = D_INDIR+D_CX;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_AX;
+ p->to.type = TYPE_MEM;
+ p->to.reg = REG_CX;
p->to.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->to.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
@@ -599,53 +613,61 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
// CMPL AX, $(framesize+(StackGuard-StackSmall))
p = appendp(ctxt, p);
p->as = AMOVL;
- p->from.type = D_INDIR+D_CX;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_CX;
p->from.offset = 0;
p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
- p->to.type = D_SI;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_SI;
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_SI;
- p->to.type = D_CONST;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SI;
+ p->to.type = TYPE_CONST;
p->to.offset = (uint32)StackPreempt;
p = appendp(ctxt, p);
p->as = AJEQ;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
q1 = p;
p = appendp(ctxt, p);
p->as = ALEAL;
- p->from.type = D_INDIR+D_SP;
+ p->from.type = TYPE_MEM;
+ p->from.reg = REG_SP;
p->from.offset = StackGuard;
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = ASUBL;
- p->from.type = D_SI;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_SI;
p->from.offset = 0;
- p->to.type = D_AX;
+ p->to.type = TYPE_REG;
+ p->to.reg = REG_AX;
p = appendp(ctxt, p);
p->as = ACMPL;
- p->from.type = D_AX;
- p->to.type = D_CONST;
+ p->from.type = TYPE_REG;
+ p->from.reg = REG_AX;
+ p->to.type = TYPE_CONST;
p->to.offset = framesize+(StackGuard-StackSmall);
}
// common
p = appendp(ctxt, p);
p->as = AJHI;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->to.offset = 4;
q = p;
p = appendp(ctxt, p);
p->as = ACALL;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
if(ctxt->cursym->cfunc)
p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
else
@@ -653,7 +675,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
p = appendp(ctxt, p);
p->as = AJMP;
- p->to.type = D_BRANCH;
+ p->to.type = TYPE_BRANCH;
p->pcond = ctxt->cursym->text->link;
if(q != nil)
@@ -804,7 +826,7 @@ loop:
q = ctxt->arch->prg();
q->as = AJMP;
q->lineno = p->lineno;
- q->to.type = D_BRANCH;
+ q->to.type = TYPE_BRANCH;
q->to.offset = p->pc;
q->pcond = p;
p = q;
@@ -829,7 +851,7 @@ loop:
p->pcond = q;
if((q = brchain(ctxt, p->link)) != nil)
p->link = q;
- if(p->from.type == D_CONST) {
+ if(p->from.type == TYPE_CONST) {
if(p->from.offset == 1) {
/*
* expect conditional jump to be taken.
@@ -864,7 +886,7 @@ LinkArch link386 = {
.thechar = '8',
.endian = LittleEndian,
- .addstacksplit = addstacksplit,
+ .preprocess = preprocess,
.assemble = span8,
.datasize = datasize,
.follow = follow,
@@ -873,24 +895,12 @@ LinkArch link386 = {
.prg = prg,
.progedit = progedit,
.settextflag = settextflag,
- .symtype = symtype,
.textflag = textflag,
.minlc = 1,
.ptrsize = 4,
.regsize = 4,
- .D_ADDR = D_ADDR,
- .D_AUTO = D_AUTO,
- .D_BRANCH = D_BRANCH,
- .D_CONST = D_CONST,
- .D_EXTERN = D_EXTERN,
- .D_FCONST = D_FCONST,
- .D_NONE = D_NONE,
- .D_PARAM = D_PARAM,
- .D_SCONST = D_SCONST,
- .D_STATIC = D_STATIC,
-
.ACALL = ACALL,
.ADATA = ADATA,
.AEND = AEND,