]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/asm: add ARM64 assembler check for incorrect input
authorfanzha02 <fannie.zhang@arm.com>
Thu, 8 Mar 2018 10:33:14 +0000 (10:33 +0000)
committerCherry Zhang <cherryyz@google.com>
Mon, 19 Mar 2018 23:45:50 +0000 (23:45 +0000)
Current ARM64 assembler has no check for the invalid value of both
shift amount and post-index immediate offset of LD1/ST1. This patch
adds the check.

This patch also fixes the printing error of register number equals
to 31, which should be printed as ZR instead of R31. Test cases
are also added.

Change-Id: I476235f3ab3a3fc91fe89c5a3149a4d4529c05c7
Reviewed-on: https://go-review.googlesource.com/100255
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>

src/cmd/asm/internal/asm/testdata/arm64.s
src/cmd/asm/internal/asm/testdata/arm64error.s
src/cmd/internal/obj/arm64/asm7.go
src/cmd/internal/obj/arm64/list7.go
src/cmd/internal/obj/util.go

index c97b64ddc856db09ef83e9976a5537df080b6cb8..c53023e6304b05a072e9e378a27df31ba547beaa 100644 (file)
@@ -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
index 93c3acdc3b4641556badd05ac910f6a7f6382211..dcdb4fe1757c334cf7333070b83d9eb0e8cddcfb 100644 (file)
@@ -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
index 3b7ad244933222608ebb91419e01fc2a98310c68..7b940dd58cef54db4ca84faed5ee9b427294b712 100644 (file)
@@ -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<<n[,R],R (shifted register) */
                o1 = c.oprrr(p, p.As)
 
+               amount := (p.From.Offset >> 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
index 37c61d22555ae66ec9e820d38cca2d5e4ba7dc45..266e2baaeef386431a621010bcb5fa7616378b3c 100644 (file)
@@ -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)
+}
index 245e9e9e9b759f0184d545efdd5a37c387adb312..9b25231bb4102f24b2bff13851d9e440a6ba728a 100644 (file)
@@ -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)
                }