diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index c97b64ddc8..c53023e630 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -31,6 +31,9 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8 AND R1@>33, R2, R3 ADD R1.UXTB, R2, R3 // 4300218b ADD R1.UXTB<<4, R2, R3 // 4310218b + ADD R2, RSP, RSP // ff63228b + ADD R2.SXTX<<1, RSP, RSP // ffe7228b + ADD ZR.SXTX<<1, R2, R3 // 43e43f8b ADDW R2.SXTW, R10, R12 // 4cc1220b ADD R18.UXTX, R14, R17 // d161328b ADDSW R18.UXTW, R14, R17 // d141322b @@ -39,6 +42,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8 SUBW R1.UXTX<<1, R3, R2 // 6264214b SUBS R3.UXTX, R8, R9 // 096123eb SUBSW R17.UXTH, R15, R21 // f521316b + SUBW ZR<<14, R19, R13 // 6d3a1f4b CMP R2.SXTH, R13 // bfa122eb CMN R1.SXTX<<2, R10 // 5fe921ab CMPW R2.UXTH<<3, R11 // 7f2d226b diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 93c3acdc3b..dcdb4fe175 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -3,54 +3,59 @@ // license that can be found in the LICENSE file. TEXT errors(SB),$0 - MOVD.P 300(R2), R3 // ERROR "offset out of range [-255,254]" - MOVD.P R3, 344(R2) // ERROR "offset out of range [-255,254]" - VLD1 (R8)(R13), [V2.B16] // ERROR "illegal combination" - VLD1 8(R9), [V2.B16] // ERROR "illegal combination" - VST1 [V1.B16], (R8)(R13) // ERROR "illegal combination" - VST1 [V1.B16], 9(R2) // ERROR "illegal combination" - VLD1 8(R8)(R13), [V2.B16] // ERROR "illegal combination" - ADD R1.UXTB<<5, R2, R3 // ERROR "shift amount out of range 0 to 4" - ADDS R1.UXTX<<7, R2, R3 // ERROR "shift amount out of range 0 to 4" - VMOV V8.D[2], V12.D[1] // ERROR "register element index out of range 0 to 1" - VMOV V8.S[4], V12.S[1] // ERROR "register element index out of range 0 to 3" - VMOV V8.H[8], V12.H[1] // ERROR "register element index out of range 0 to 7" - VMOV V8.B[16], V12.B[1] // ERROR "register element index out of range 0 to 15" - VMOV V8.D[0], V12.S[1] // ERROR "operand mismatch" - VMOV V8.D[0], V12.H[1] // ERROR "operand mismatch" - VMOV V8.D[0], V12.B[1] // ERROR "operand mismatch" - VMOV V8.S[0], V12.H[1] // ERROR "operand mismatch" - VMOV V8.S[0], V12.B[1] // ERROR "operand mismatch" - VMOV V8.H[0], V12.B[1] // ERROR "operand mismatch" - VMOV V8.B[16], R3 // ERROR "register element index out of range 0 to 15" - VMOV V8.H[9], R3 // ERROR "register element index out of range 0 to 7" - VMOV V8.S[4], R3 // ERROR "register element index out of range 0 to 3" - VMOV V8.D[2], R3 // ERROR "register element index out of range 0 to 1" - VDUP V8.B[16], R3.B16 // ERROR "register element index out of range 0 to 15" - VDUP V8.B[17], R3.B8 // ERROR "register element index out of range 0 to 15" - VDUP V8.H[9], R3.H4 // ERROR "register element index out of range 0 to 7" - VDUP V8.H[9], R3.H8 // ERROR "register element index out of range 0 to 7" - VDUP V8.S[4], R3.S2 // ERROR "register element index out of range 0 to 3" - VDUP V8.S[4], R3.S4 // ERROR "register element index out of range 0 to 3" - VDUP V8.D[2], R3.D2 // ERROR "register element index out of range 0 to 1" - VFMLA V1.D2, V12.D2, V3.S2 // ERROR "operand mismatch" - VFMLA V1.S2, V12.S2, V3.D2 // ERROR "operand mismatch" - VFMLA V1.S4, V12.S2, V3.D2 // ERROR "operand mismatch" - VFMLA V1.H4, V12.H4, V3.D2 // ERROR "operand mismatch" - VFMLS V1.S2, V12.S2, V3.S4 // ERROR "operand mismatch" - VFMLS V1.S2, V12.D2, V3.S4 // ERROR "operand mismatch" - VFMLS V1.S2, V12.S4, V3.D2 // ERROR "operand mismatch" - VFMLA V1.B8, V12.B8, V3.B8 // ERROR "invalid arrangement" - VFMLA V1.B16, V12.B16, V3.B16 // ERROR "invalid arrangement" - VFMLA V1.H4, V12.H4, V3.H4 // ERROR "invalid arrangement" - VFMLA V1.H8, V12.H8, V3.H8 // ERROR "invalid arrangement" - VFMLA V1.H4, V12.H4, V3.H4 // ERROR "invalid arrangement" - VFMLS V1.B8, V12.B8, V3.B8 // ERROR "invalid arrangement" - VFMLS V1.B16, V12.B16, V3.B16 // ERROR "invalid arrangement" - VFMLS V1.H4, V12.H4, V3.H4 // ERROR "invalid arrangement" - VFMLS V1.H8, V12.H8, V3.H8 // ERROR "invalid arrangement" - VFMLS V1.H4, V12.H4, V3.H4 // ERROR "invalid arrangement" - - AND $1, RSP // ERROR "illegal combination" - ANDS $1, R0, RSP // ERROR "illegal combination" + AND $1, RSP // ERROR "illegal combination" + ANDS $1, R0, RSP // ERROR "illegal combination" + MOVD.P 300(R2), R3 // ERROR "offset out of range [-255,254]" + MOVD.P R3, 344(R2) // ERROR "offset out of range [-255,254]" + ADDSW R7->32, R14, R13 // ERROR "shift amount out of range 0 to 31" + BICW R7@>33, R5, R16 // ERROR "shift amount out of range 0 to 31" + ADD R1.UXTB<<5, R2, R3 // ERROR "shift amount out of range 0 to 4" + ADDS R1.UXTX<<7, R2, R3 // ERROR "shift amount out of range 0 to 4" + VLD1 (R8)(R13), [V2.B16] // ERROR "illegal combination" + VLD1 8(R9), [V2.B16] // ERROR "illegal combination" + VST1 [V1.B16], (R8)(R13) // ERROR "illegal combination" + VST1 [V1.B16], 9(R2) // ERROR "illegal combination" + VLD1 8(R8)(R13), [V2.B16] // ERROR "illegal combination" + VMOV V8.D[2], V12.D[1] // ERROR "register element index out of range 0 to 1" + VMOV V8.S[4], V12.S[1] // ERROR "register element index out of range 0 to 3" + VMOV V8.H[8], V12.H[1] // ERROR "register element index out of range 0 to 7" + VMOV V8.B[16], V12.B[1] // ERROR "register element index out of range 0 to 15" + VMOV V8.D[0], V12.S[1] // ERROR "operand mismatch" + VMOV V8.D[0], V12.H[1] // ERROR "operand mismatch" + VMOV V8.D[0], V12.B[1] // ERROR "operand mismatch" + VMOV V8.S[0], V12.H[1] // ERROR "operand mismatch" + VMOV V8.S[0], V12.B[1] // ERROR "operand mismatch" + VMOV V8.H[0], V12.B[1] // ERROR "operand mismatch" + VMOV V8.B[16], R3 // ERROR "register element index out of range 0 to 15" + VMOV V8.H[9], R3 // ERROR "register element index out of range 0 to 7" + VMOV V8.S[4], R3 // ERROR "register element index out of range 0 to 3" + VMOV V8.D[2], R3 // ERROR "register element index out of range 0 to 1" + VDUP V8.B[16], R3.B16 // ERROR "register element index out of range 0 to 15" + VDUP V8.B[17], R3.B8 // ERROR "register element index out of range 0 to 15" + VDUP V8.H[9], R3.H4 // ERROR "register element index out of range 0 to 7" + VDUP V8.H[9], R3.H8 // ERROR "register element index out of range 0 to 7" + VDUP V8.S[4], R3.S2 // ERROR "register element index out of range 0 to 3" + VDUP V8.S[4], R3.S4 // ERROR "register element index out of range 0 to 3" + VDUP V8.D[2], R3.D2 // ERROR "register element index out of range 0 to 1" + VFMLA V1.D2, V12.D2, V3.S2 // ERROR "operand mismatch" + VFMLA V1.S2, V12.S2, V3.D2 // ERROR "operand mismatch" + VFMLA V1.S4, V12.S2, V3.D2 // ERROR "operand mismatch" + VFMLA V1.H4, V12.H4, V3.D2 // ERROR "operand mismatch" + VFMLS V1.S2, V12.S2, V3.S4 // ERROR "operand mismatch" + VFMLS V1.S2, V12.D2, V3.S4 // ERROR "operand mismatch" + VFMLS V1.S2, V12.S4, V3.D2 // ERROR "operand mismatch" + VFMLA V1.B8, V12.B8, V3.B8 // ERROR "invalid arrangement" + VFMLA V1.B16, V12.B16, V3.B16 // ERROR "invalid arrangement" + VFMLA V1.H4, V12.H4, V3.H4 // ERROR "invalid arrangement" + VFMLA V1.H8, V12.H8, V3.H8 // ERROR "invalid arrangement" + VFMLA V1.H4, V12.H4, V3.H4 // ERROR "invalid arrangement" + VFMLS V1.B8, V12.B8, V3.B8 // ERROR "invalid arrangement" + VFMLS V1.B16, V12.B16, V3.B16 // ERROR "invalid arrangement" + VFMLS V1.H4, V12.H4, V3.H4 // ERROR "invalid arrangement" + VFMLS V1.H8, V12.H8, V3.H8 // ERROR "invalid arrangement" + VFMLS V1.H4, V12.H4, V3.H4 // ERROR "invalid arrangement" + VST1.P [V4.S4,V5.S4], 48(R1) // ERROR "invalid post-increment offset" + VST1.P [V4.S4], 8(R1) // ERROR "invalid post-increment offset" + VLD1.P 32(R1), [V8.S4, V9.S4, V10.S4] // ERROR "invalid post-increment offset" + VLD1.P 48(R1), [V7.S4, V8.S4, V9.S4, V10.S4] // ERROR "invalid post-increment offset" RET diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 3b7ad24493..7b940dd58c 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -2227,6 +2227,41 @@ func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) { } } +/* checkoffset checks whether the immediate offset is valid for VLD1.P and VST1.P*/ +func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) { + var offset, list, n int64 + switch as { + case AVLD1: + offset = p.From.Offset + list = p.To.Offset + case AVST1: + offset = p.To.Offset + list = p.From.Offset + default: + c.ctxt.Diag("invalid operation on op %v", p.As) + } + opcode := (list >> 12) & 15 + q := (list >> 30) & 1 + if offset == 0 { + return + } + switch opcode { + case 0x7: + n = 1 // one register + case 0xa: + n = 2 // two registers + case 0x6: + n = 3 // three registers + case 0x2: + n = 4 // four registers + default: + c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p) + } + if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) { + c.ctxt.Diag("invalid post-increment offset: %v", p) + } +} + func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 := uint32(0) o2 := uint32(0) @@ -2278,6 +2313,11 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { case 3: /* op R<> 10) & 63 + is64bit := o1 & (1 << 31) + if is64bit == 0 && amount >= 32 { + c.ctxt.Diag("shift amount out of range 0 to 31: %v", p) + } o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ rt := int(p.To.Reg) if p.To.Type == obj.TYPE_NONE { @@ -3634,6 +3674,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 |= 1 << 23 if p.From.Index == 0 { // immediate offset variant + c.checkoffset(p, p.As) o1 |= 0x1f << 16 } else { // register offset variant @@ -3722,6 +3763,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 |= 1 << 23 if p.To.Index == 0 { // immediate offset variant + c.checkoffset(p, p.As) o1 |= 0x1f << 16 } else { // register offset variant diff --git a/src/cmd/internal/obj/arm64/list7.go b/src/cmd/internal/obj/arm64/list7.go index 37c61d2255..266e2baaee 100644 --- a/src/cmd/internal/obj/arm64/list7.go +++ b/src/cmd/internal/obj/arm64/list7.go @@ -92,6 +92,7 @@ func arrange(a int) string { } func rconv(r int) string { + ext := (r >> 5) & 7 if r == REGG { return "g" } @@ -173,52 +174,52 @@ func rconv(r int) string { case r == REG_PSTL3STRM: return "PSTL3STRM" case REG_UXTB <= r && r < REG_UXTH: - if (r>>5)&7 != 0 { - return fmt.Sprintf("R%d.UXTB<<%d", r&31, (r>>5)&7) + if ext != 0 { + return fmt.Sprintf("%s.UXTB<<%d", regname(r), ext) } else { - return fmt.Sprintf("R%d.UXTB", r&31) + return fmt.Sprintf("%s.UXTB", regname(r)) } case REG_UXTH <= r && r < REG_UXTW: - if (r>>5)&7 != 0 { - return fmt.Sprintf("R%d.UXTH<<%d", r&31, (r>>5)&7) + if ext != 0 { + return fmt.Sprintf("%s.UXTH<<%d", regname(r), ext) } else { - return fmt.Sprintf("R%d.UXTH", r&31) + return fmt.Sprintf("%s.UXTH", regname(r)) } case REG_UXTW <= r && r < REG_UXTX: - if (r>>5)&7 != 0 { - return fmt.Sprintf("R%d.UXTW<<%d", r&31, (r>>5)&7) + if ext != 0 { + return fmt.Sprintf("%s.UXTW<<%d", regname(r), ext) } else { - return fmt.Sprintf("R%d.UXTW", r&31) + return fmt.Sprintf("%s.UXTW", regname(r)) } case REG_UXTX <= r && r < REG_SXTB: - if (r>>5)&7 != 0 { - return fmt.Sprintf("R%d.UXTX<<%d", r&31, (r>>5)&7) + if ext != 0 { + return fmt.Sprintf("%s.UXTX<<%d", regname(r), ext) } else { - return fmt.Sprintf("R%d.UXTX", r&31) + return fmt.Sprintf("%s.UXTX", regname(r)) } case REG_SXTB <= r && r < REG_SXTH: - if (r>>5)&7 != 0 { - return fmt.Sprintf("R%d.SXTB<<%d", r&31, (r>>5)&7) + if ext != 0 { + return fmt.Sprintf("%s.SXTB<<%d", regname(r), ext) } else { - return fmt.Sprintf("R%d.SXTB", r&31) + return fmt.Sprintf("%s.SXTB", regname(r)) } case REG_SXTH <= r && r < REG_SXTW: - if (r>>5)&7 != 0 { - return fmt.Sprintf("R%d.SXTH<<%d", r&31, (r>>5)&7) + if ext != 0 { + return fmt.Sprintf("%s.SXTH<<%d", regname(r), ext) } else { - return fmt.Sprintf("R%d.SXTH", r&31) + return fmt.Sprintf("%s.SXTH", regname(r)) } case REG_SXTW <= r && r < REG_SXTX: - if (r>>5)&7 != 0 { - return fmt.Sprintf("R%d.SXTW<<%d", r&31, (r>>5)&7) + if ext != 0 { + return fmt.Sprintf("%s.SXTW<<%d", regname(r), ext) } else { - return fmt.Sprintf("R%d.SXTW", r&31) + return fmt.Sprintf("%s.SXTW", regname(r)) } case REG_SXTX <= r && r < REG_SPECIAL: - if (r>>5)&7 != 0 { - return fmt.Sprintf("R%d.SXTX<<%d", r&31, (r>>5)&7) + if ext != 0 { + return fmt.Sprintf("%s.SXTX<<%d", regname(r), ext) } else { - return fmt.Sprintf("R%d.SXTX", r&31) + return fmt.Sprintf("%s.SXTX", regname(r)) } case REG_ARNG <= r && r < REG_ELEM: return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15)) @@ -291,3 +292,10 @@ func rlconv(list int64) string { str += "]" return str } + +func regname(r int) string { + if r&31 == 31 { + return "ZR" + } + return fmt.Sprintf("R%d", r&31) +} diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go index 245e9e9e9b..9b25231bb4 100644 --- a/src/cmd/internal/obj/util.go +++ b/src/cmd/internal/obj/util.go @@ -263,7 +263,8 @@ func Dconv(p *Prog, a *Addr) string { } case "arm64": op := ops[((v>>22)&3)<<1:] - str = fmt.Sprintf("R%d%c%c%d", (v>>16)&31, op[0], op[1], (v>>10)&63) + r := (v >> 16) & 31 + str = fmt.Sprintf("%s%c%c%d", Rconv(r+RBaseARM64), op[0], op[1], (v>>10)&63) default: panic("TYPE_SHIFT is not supported on " + objabi.GOARCH) }