diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 474ed556d05..1744c09b98f 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -32,6 +32,24 @@ TEXT errors(SB),$0 ANDS $0x22220000, R2, RSP // ERROR "illegal combination" ADD R1, R2, R3, R4 // ERROR "illegal combination" BICW R7@>33, R5, R16 // ERROR "shift amount out of range 0 to 31" + NEGW R7<<33, R5 // ERROR "shift amount out of range 0 to 31" + NEGSW R7<<33, R5 // ERROR "shift amount out of range 0 to 31" + ADD R7@>2, R5, R16 // ERROR "unsupported shift operator" + ADDW R7@>2, R5, R16 // ERROR "unsupported shift operator" + ADDS R7@>2, R5, R16 // ERROR "unsupported shift operator" + ADDSW R7@>2, R5, R16 // ERROR "unsupported shift operator" + SUB R7@>2, R5, R16 // ERROR "unsupported shift operator" + SUBW R7@>2, R5, R16 // ERROR "unsupported shift operator" + SUBS R7@>2, R5, R16 // ERROR "unsupported shift operator" + SUBSW R7@>2, R5, R16 // ERROR "unsupported shift operator" + CMP R7@>2, R5 // ERROR "unsupported shift operator" + CMPW R7@>2, R5 // ERROR "unsupported shift operator" + CMN R7@>2, R5 // ERROR "unsupported shift operator" + CMNW R7@>2, R5 // ERROR "unsupported shift operator" + NEG R7@>2, R5 // ERROR "unsupported shift operator" + NEGW R7@>2, R5 // ERROR "unsupported shift operator" + NEGS R7@>2, R5 // ERROR "unsupported shift operator" + NEGSW R7@>2, R5 // ERROR "unsupported shift operator" CINC CS, R2, R3, R4 // ERROR "illegal combination" CSEL LT, R1, R2 // ERROR "illegal combination" LDP.P 8(R2), (R2, R3) // ERROR "constrained unpredictable behavior" diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 2dbaea98b60..64067a4a171 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -321,12 +321,12 @@ var optab = []Optab{ {ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0}, {AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0}, {AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, - {AADD, C_SHIFT, C_RSP, C_NONE, C_RSP, 107, 4, 0, 0, 0}, - {AADD, C_SHIFT, C_NONE, C_NONE, C_RSP, 107, 4, 0, 0, 0}, + {AADD, C_SHIFT, C_RSP, C_NONE, C_RSP, 26, 4, 0, 0, 0}, + {AADD, C_SHIFT, C_NONE, C_NONE, C_RSP, 26, 4, 0, 0, 0}, {AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, {ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0}, - {ACMP, C_SHIFT, C_RSP, C_NONE, C_NONE, 107, 4, 0, 0, 0}, - {ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 26, 4, 0, 0, 0}, + {ACMP, C_SHIFT, C_RSP, C_NONE, C_NONE, 26, 4, 0, 0, 0}, + {ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0}, {AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0}, {AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0}, {ACMP, C_REG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0}, @@ -1355,6 +1355,14 @@ func isADDSop(op obj.As) bool { return false } +func isNEGop(op obj.As) bool { + switch op { + case ANEG, ANEGW, ANEGS, ANEGSW: + return true + } + return false +} + func isRegShiftOrExt(a *obj.Addr) bool { return (a.Index-obj.RBaseARM64)®_EXT != 0 || (a.Index-obj.RBaseARM64)®_LSL != 0 } @@ -3251,13 +3259,17 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { if is64bit == 0 && amount >= 32 { c.ctxt.Diag("shift amount out of range 0 to 31: %v", p) } + shift := (p.From.Offset >> 22) & 3 + if (shift > 2 || shift < 0) && (isADDop(p.As) || isADDWop(p.As) || isNEGop(p.As)) { + c.ctxt.Diag("unsupported shift operator: %v", p) + } o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ rt := int(p.To.Reg) if p.To.Type == obj.TYPE_NONE { rt = REGZERO } r := int(p.Reg) - if p.As == AMVN || p.As == AMVNW { + if p.As == AMVN || p.As == AMVNW || isNEGop(p.As) { r = REGZERO } else if r == 0 { r = rt @@ -3665,12 +3677,40 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { rt := int(p.To.Reg) o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) - case 26: /* negX Rm< subX Rm<> 10) & 63 + shift := (p.From.Offset >> 22) & 3 + if shift != 0 { + c.ctxt.Diag("illegal combination: %v", p) + break + } - o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ + if amount > 4 { + c.ctxt.Diag("the left shift amount out of range 0 to 4: %v", p) + break + } + rf := (p.From.Offset >> 16) & 31 rt := int(p.To.Reg) - o1 |= (REGZERO & 31 << 5) | uint32(rt&31) + r := int(p.Reg) + if p.To.Type == obj.TYPE_NONE { + rt = REGZERO + } + if r == 0 { + r = rt + } + + o1 = c.opxrrr(p, p.As, false) + o1 |= uint32(rf)<<16 | uint32(amount&7)<<10 | (uint32(r&31) << 5) | uint32(rt&31) case 27: /* op Rm<> 10) & 63 - shift := (p.From.Offset >> 22) & 3 - if shift != 0 { - c.ctxt.Diag("illegal combination: %v", p) - break - } - - if amount > 4 { - c.ctxt.Diag("the left shift amount out of range 0 to 4: %v", p) - break - } - rf := (p.From.Offset >> 16) & 31 - rt := int(p.To.Reg) - r := int(p.Reg) - if p.To.Type == obj.TYPE_NONE { - rt = REGZERO - } - if r == 0 { - r = rt - } - - o1 = c.opxrrr(p, p.As, false) - o1 |= uint32(rf)<<16 | uint32(amount&7)<<10 | (uint32(r&31) << 5) | uint32(rt&31) } out[0] = o1 out[1] = o2