diff options
| author | Russ Cox <rsc@golang.org> | 2015-01-26 15:15:43 -0500 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2015-01-30 03:16:19 +0000 |
| commit | a5b1baeed7d26a3d8aea86bbabe81f59c3d4e9d6 (patch) | |
| tree | 4a0222814771277f93201d329d5cfd3f811f6f79 /src/liblink | |
| parent | 604138e87bb0d992319ed2ccc034f9a2591a8363 (diff) | |
| download | go-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.c | 766 | ||||
| -rw-r--r-- | src/liblink/list8.c | 178 | ||||
| -rw-r--r-- | src/liblink/obj8.c | 248 |
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, |
