Commit e8531316 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/internal/obj: stop using as+ALAST as an opcode

Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture.  E.g., mips64 has [6<<12, 7<<12).

However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.

More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692.  (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)

As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.

Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.

Updates #14692.

Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 399f0f5f
...@@ -2276,13 +2276,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2276,13 +2276,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= (uint32(p.From.Reg) & 15) << 0 o1 |= (uint32(p.From.Reg) & 15) << 0
o1 |= (FREGTMP & 15) << 12 o1 |= (FREGTMP & 15) << 12
o2 = oprrr(ctxt, AMOVFW+ALAST, int(p.Scond)) o2 = oprrr(ctxt, -AMOVFW, int(p.Scond))
o2 |= (FREGTMP & 15) << 16 o2 |= (FREGTMP & 15) << 16
o2 |= (uint32(p.To.Reg) & 15) << 12 o2 |= (uint32(p.To.Reg) & 15) << 12
// macro for movw reg,FTMP; movwf FTMP,freg // macro for movw reg,FTMP; movwf FTMP,freg
case 87: /* movwf reg,freg - fix-to-float */ case 87: /* movwf reg,freg - fix-to-float */
o1 = oprrr(ctxt, AMOVWF+ALAST, int(p.Scond)) o1 = oprrr(ctxt, -AMOVWF, int(p.Scond))
o1 |= (uint32(p.From.Reg) & 15) << 12 o1 |= (uint32(p.From.Reg) & 15) << 12
o1 |= (FREGTMP & 15) << 16 o1 |= (FREGTMP & 15) << 16
...@@ -2291,19 +2291,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2291,19 +2291,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o2 |= (uint32(p.To.Reg) & 15) << 12 o2 |= (uint32(p.To.Reg) & 15) << 12
case 88: /* movw reg,freg */ case 88: /* movw reg,freg */
o1 = oprrr(ctxt, AMOVWF+ALAST, int(p.Scond)) o1 = oprrr(ctxt, -AMOVWF, int(p.Scond))
o1 |= (uint32(p.From.Reg) & 15) << 12 o1 |= (uint32(p.From.Reg) & 15) << 12
o1 |= (uint32(p.To.Reg) & 15) << 16 o1 |= (uint32(p.To.Reg) & 15) << 16
case 89: /* movw freg,reg */ case 89: /* movw freg,reg */
o1 = oprrr(ctxt, AMOVFW+ALAST, int(p.Scond)) o1 = oprrr(ctxt, -AMOVFW, int(p.Scond))
o1 |= (uint32(p.From.Reg) & 15) << 16 o1 |= (uint32(p.From.Reg) & 15) << 16
o1 |= (uint32(p.To.Reg) & 15) << 12 o1 |= (uint32(p.To.Reg) & 15) << 12
case 90: /* tst reg */ case 90: /* tst reg */
o1 = oprrr(ctxt, ACMP+ALAST, int(p.Scond)) o1 = oprrr(ctxt, -ACMP, int(p.Scond))
o1 |= (uint32(p.From.Reg) & 15) << 16 o1 |= (uint32(p.From.Reg) & 15) << 16
...@@ -2560,13 +2560,13 @@ func oprrr(ctxt *obj.Link, a int, sc int) uint32 { ...@@ -2560,13 +2560,13 @@ func oprrr(ctxt *obj.Link, a int, sc int) uint32 {
} }
return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc
case AMOVWF + ALAST: // copy WtoF case -AMOVWF: // copy WtoF
return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4 return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
case AMOVFW + ALAST: // copy FtoW case -AMOVFW: // copy FtoW
return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4 return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
case ACMP + ALAST: // cmp imm case -ACMP: // cmp imm
return o | 0x3<<24 | 0x5<<20 return o | 0x3<<24 | 0x5<<20
// CLZ doesn't support .nil // CLZ doesn't support .nil
......
...@@ -1072,7 +1072,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1072,7 +1072,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
r = int(o.param) r = int(o.param)
} }
v := regoff(ctxt, &p.From) v := regoff(ctxt, &p.From)
o1 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(v), uint32(r), uint32(p.To.Reg)) o1 = OP_IRR(opirr(ctxt, -int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg))
case 9: /* sll r1,[r2],r3 */ case 9: /* sll r1,[r2],r3 */
r := int(p.Reg) r := int(p.Reg)
...@@ -1147,11 +1147,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1147,11 +1147,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} }
case 14: /* movwu r,r */ case 14: /* movwu r,r */
o1 = OP_SRR(opirr(ctxt, ASLLV+ALAST), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg)) o1 = OP_SRR(opirr(ctxt, -ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
if p.As == AMOVWU { if p.As == AMOVWU {
o2 = OP_SRR(opirr(ctxt, ASRLV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) o2 = OP_SRR(opirr(ctxt, -ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
} else { } else {
o2 = OP_SRR(opirr(ctxt, ASRAV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) o2 = OP_SRR(opirr(ctxt, -ASRAV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
} }
case 16: /* sll $c,[r1],r2 */ case 16: /* sll $c,[r1],r2 */
...@@ -1163,7 +1163,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1163,7 +1163,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
/* OP_SRR will use only the low 5 bits of the shift value */ /* OP_SRR will use only the low 5 bits of the shift value */
if v >= 32 && vshift(p.As) { if v >= 32 && vshift(p.As) {
o1 = OP_SRR(opirr(ctxt, int(p.As)+ALAST), uint32(v-32), uint32(r), uint32(p.To.Reg)) o1 = OP_SRR(opirr(ctxt, -int(p.As)), uint32(v-32), uint32(r), uint32(p.To.Reg))
} else { } else {
o1 = OP_SRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg)) o1 = OP_SRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg))
} }
...@@ -1248,9 +1248,9 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1248,9 +1248,9 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
if r == 0 { if r == 0 {
r = int(o.param) r = int(o.param)
} }
a := AMOVF + ALAST a := -AMOVF
if p.As == AMOVD { if p.As == AMOVD {
a = AMOVD + ALAST a = -AMOVD
} }
switch o.size { switch o.size {
case 16: case 16:
...@@ -1331,7 +1331,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1331,7 +1331,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP)) o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
o4 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), uint32(p.To.Reg)) o4 = OP_IRR(opirr(ctxt, -int(p.As)), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
case 37: /* movw r,mr */ case 37: /* movw r,mr */
a := SP(2, 0) | (4 << 21) /* mtc0 */ a := SP(2, 0) | (4 << 21) /* mtc0 */
...@@ -1389,7 +1389,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1389,7 +1389,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
rel.Sym = p.From.Sym rel.Sym = p.From.Sym
rel.Add = p.From.Offset rel.Add = p.From.Offset
rel.Type = obj.R_ADDRMIPS rel.Type = obj.R_ADDRMIPS
o3 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), uint32(p.To.Reg)) o3 = OP_IRR(opirr(ctxt, -int(p.As)), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
} }
out[0] = o1 out[0] = o1
...@@ -1562,8 +1562,8 @@ func oprrr(ctxt *obj.Link, a int) uint32 { ...@@ -1562,8 +1562,8 @@ func oprrr(ctxt *obj.Link, a int) uint32 {
return FPD(7, 6) return FPD(7, 6)
} }
if a >= ALAST { if a < 0 {
ctxt.Diag("bad rrr opcode %v+ALAST", obj.Aconv(a-ALAST)) ctxt.Diag("bad rrr opcode -%v", obj.Aconv(-a))
} else { } else {
ctxt.Diag("bad rrr opcode %v", obj.Aconv(a)) ctxt.Diag("bad rrr opcode %v", obj.Aconv(a))
} }
...@@ -1607,43 +1607,43 @@ func opirr(ctxt *obj.Link, a int) uint32 { ...@@ -1607,43 +1607,43 @@ func opirr(ctxt *obj.Link, a int) uint32 {
return SP(0, 3) return SP(0, 3)
case ABEQ: case ABEQ:
return SP(0, 4) return SP(0, 4)
case ABEQ + ALAST: case -ABEQ:
return SP(2, 4) /* likely */ return SP(2, 4) /* likely */
case ABNE: case ABNE:
return SP(0, 5) return SP(0, 5)
case ABNE + ALAST: case -ABNE:
return SP(2, 5) /* likely */ return SP(2, 5) /* likely */
case ABGEZ: case ABGEZ:
return SP(0, 1) | BCOND(0, 1) return SP(0, 1) | BCOND(0, 1)
case ABGEZ + ALAST: case -ABGEZ:
return SP(0, 1) | BCOND(0, 3) /* likely */ return SP(0, 1) | BCOND(0, 3) /* likely */
case ABGEZAL: case ABGEZAL:
return SP(0, 1) | BCOND(2, 1) return SP(0, 1) | BCOND(2, 1)
case ABGEZAL + ALAST: case -ABGEZAL:
return SP(0, 1) | BCOND(2, 3) /* likely */ return SP(0, 1) | BCOND(2, 3) /* likely */
case ABGTZ: case ABGTZ:
return SP(0, 7) return SP(0, 7)
case ABGTZ + ALAST: case -ABGTZ:
return SP(2, 7) /* likely */ return SP(2, 7) /* likely */
case ABLEZ: case ABLEZ:
return SP(0, 6) return SP(0, 6)
case ABLEZ + ALAST: case -ABLEZ:
return SP(2, 6) /* likely */ return SP(2, 6) /* likely */
case ABLTZ: case ABLTZ:
return SP(0, 1) | BCOND(0, 0) return SP(0, 1) | BCOND(0, 0)
case ABLTZ + ALAST: case -ABLTZ:
return SP(0, 1) | BCOND(0, 2) /* likely */ return SP(0, 1) | BCOND(0, 2) /* likely */
case ABLTZAL: case ABLTZAL:
return SP(0, 1) | BCOND(2, 0) return SP(0, 1) | BCOND(2, 0)
case ABLTZAL + ALAST: case -ABLTZAL:
return SP(0, 1) | BCOND(2, 2) /* likely */ return SP(0, 1) | BCOND(2, 2) /* likely */
case ABFPT: case ABFPT:
return SP(2, 1) | (257 << 16) return SP(2, 1) | (257 << 16)
case ABFPT + ALAST: case -ABFPT:
return SP(2, 1) | (259 << 16) /* likely */ return SP(2, 1) | (259 << 16) /* likely */
case ABFPF: case ABFPF:
return SP(2, 1) | (256 << 16) return SP(2, 1) | (256 << 16)
case ABFPF + ALAST: case -ABFPF:
return SP(2, 1) | (258 << 16) /* likely */ return SP(2, 1) | (258 << 16) /* likely */
case AMOVB, case AMOVB,
...@@ -1673,31 +1673,31 @@ func opirr(ctxt *obj.Link, a int) uint32 { ...@@ -1673,31 +1673,31 @@ func opirr(ctxt *obj.Link, a int) uint32 {
case ABREAK: case ABREAK:
return SP(5, 7) return SP(5, 7)
case AMOVWL + ALAST: case -AMOVWL:
return SP(4, 2) return SP(4, 2)
case AMOVWR + ALAST: case -AMOVWR:
return SP(4, 6) return SP(4, 6)
case AMOVVL + ALAST: case -AMOVVL:
return SP(3, 2) return SP(3, 2)
case AMOVVR + ALAST: case -AMOVVR:
return SP(3, 3) return SP(3, 3)
case AMOVB + ALAST: case -AMOVB:
return SP(4, 0) return SP(4, 0)
case AMOVBU + ALAST: case -AMOVBU:
return SP(4, 4) return SP(4, 4)
case AMOVH + ALAST: case -AMOVH:
return SP(4, 1) return SP(4, 1)
case AMOVHU + ALAST: case -AMOVHU:
return SP(4, 5) return SP(4, 5)
case AMOVW + ALAST: case -AMOVW:
return SP(4, 3) return SP(4, 3)
case AMOVWU + ALAST: case -AMOVWU:
return SP(4, 7) return SP(4, 7)
case AMOVV + ALAST: case -AMOVV:
return SP(6, 7) return SP(6, 7)
case AMOVF + ALAST: case -AMOVF:
return SP(6, 1) return SP(6, 1)
case AMOVD + ALAST: case -AMOVD:
return SP(6, 5) return SP(6, 5)
case ASLLV: case ASLLV:
...@@ -1706,16 +1706,16 @@ func opirr(ctxt *obj.Link, a int) uint32 { ...@@ -1706,16 +1706,16 @@ func opirr(ctxt *obj.Link, a int) uint32 {
return OP(7, 2) return OP(7, 2)
case ASRAV: case ASRAV:
return OP(7, 3) return OP(7, 3)
case ASLLV + ALAST: case -ASLLV:
return OP(7, 4) return OP(7, 4)
case ASRLV + ALAST: case -ASRLV:
return OP(7, 6) return OP(7, 6)
case ASRAV + ALAST: case -ASRAV:
return OP(7, 7) return OP(7, 7)
} }
if a >= ALAST { if a < 0 {
ctxt.Diag("bad irr opcode %v+ALAST", obj.Aconv(a-ALAST)) ctxt.Diag("bad irr opcode -%v", obj.Aconv(-a))
} else { } else {
ctxt.Diag("bad irr opcode %v", obj.Aconv(a)) ctxt.Diag("bad irr opcode %v", obj.Aconv(a))
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment