]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm64: fix assemble add/adds/sub/subs/cmp/cmn(extended register...
authorfanzha02 <fannie.zhang@arm.com>
Wed, 17 Jan 2018 10:25:26 +0000 (10:25 +0000)
committerCherry Zhang <cherryyz@google.com>
Tue, 6 Feb 2018 00:25:23 +0000 (00:25 +0000)
The current code encodes the wrong option value in the binary.

The fix reconstructs the function opxrrr() that does not encode the option
value into the binary value when arguments is sign or zero-extended register.

Add the relevant test cases and negative tests.

Fixes #23501
Change-Id: Ie5850ead2ad08d9a235a5664869aac5051762f1f
Reviewed-on: https://go-review.googlesource.com/88876
Run-TryBot: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/asm/internal/arch/arm64.go
src/cmd/asm/internal/asm/testdata/arm64.s
src/cmd/asm/internal/asm/testdata/arm64error.s
src/cmd/internal/obj/arm64/asm7.go

index 2fd21b58b8f3e495b22384d2fe1a7e9439a9d744..63664d663c1ce9b44e56dfc7fa02cc8caa6db118 100644 (file)
@@ -123,6 +123,11 @@ func arm64RegisterNumber(name string, n int16) (int16, bool) {
 // ARM64RegisterExtension parses an ARM64 register with extension or arrangment.
 func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
        rm := uint32(reg)
+       if isAmount {
+               if num < 0 || num > 7 {
+                       return errors.New("shift amount out of range")
+               }
+       }
        switch ext {
        case "UXTB":
                if !isAmount {
@@ -134,7 +139,7 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
                if !isAmount {
                        return errors.New("invalid register extension")
                }
-               a.Reg = arm64.REG_UXTH + (num & 31) + int16(num<<5)
+               a.Reg = arm64.REG_UXTH + (reg & 31) + int16(num<<5)
                a.Offset = int64(((rm & 31) << 16) | (1 << 13) | (uint32(num) << 10))
        case "UXTW":
                if !isAmount {
index ab6ad5bcb79796d0d413a6f78b3733f4ce29fe50..cb563bb9961d92914a1c47724cada58c8cdc0234 100644 (file)
@@ -29,8 +29,20 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
        ADD     R1<<22, R2, R3
        ADD     R1->33, R2, R3
        AND     R1@>33, R2, R3
-       ADD     R1.UXTB, R2, R3                 // 4360218b
-       ADD     R1.UXTB<<4, R2, R3              // 4370218b
+       ADD     R1.UXTB, R2, R3                 // 4300218b
+       ADD     R1.UXTB<<4, R2, R3              // 4310218b
+       ADDW    R2.SXTW, R10, R12               // 4cc1220b
+       ADD     R18.UXTX, R14, R17              // d161328b
+       ADDSW   R18.UXTW, R14, R17              // d141322b
+       ADDS    R12.SXTX, R3, R1                // 61e02cab
+       SUB     R19.UXTH<<4, R2, R21            // 553033cb
+       SUBW    R1.UXTX<<1, R3, R2              // 6264214b
+       SUBS    R3.UXTX, R8, R9                 // 096123eb
+       SUBSW   R17.UXTH, R15, R21              // f521316b
+       CMP     R2.SXTH, R13                    // bfa122eb
+       CMN     R1.SXTX<<2, R10                 // 5fe921ab
+       CMPW    R2.UXTH<<3, R11                 // 7f2d226b
+       CMNW    R1.SXTB, R9                     // 3f81212b
        VADDP   V1.B16, V2.B16, V3.B16          // 43bc214e
        VADDP   V1.S4, V2.S4, V3.S4             // 43bca14e
        VADDP   V1.D2, V2.D2, V3.D2             // 43bce14e
index 97af09c4dd6d5e6a510e284948f8d84d81331939..e4fad9c741feaf0a00b45347a6f0d3f8529dddb5 100644 (file)
@@ -10,4 +10,6 @@ TEXT errors(SB),$0
        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"
        RET
index fdf1fb565dc5cb1e5526e57ad61d820f2f16ec12..ca81238c93e93fe81f154bfb1011253a5184d771 100644 (file)
@@ -2362,7 +2362,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
                        r = rt
                }
                if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
-                       o2 = c.opxrrr(p, p.As)
+                       o2 = c.opxrrr(p, p.As, false)
                        o2 |= REGTMP & 31 << 16
                        o2 |= LSL0_64
                } else {
@@ -2591,11 +2591,16 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
                o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
 
        case 27: /* op Rm<<n[,Rn],Rd (extended register) */
-               o1 = c.opxrrr(p, p.As)
 
                if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 {
+                       amount := (p.From.Reg >> 5) & 7
+                       if amount > 4 {
+                               c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
+                       }
+                       o1 = c.opxrrr(p, p.As, true)
                        o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
                } else {
+                       o1 = c.opxrrr(p, p.As, false)
                        o1 |= uint32(p.From.Reg&31) << 16
                }
                rt := int(p.To.Reg)
@@ -2755,7 +2760,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
                if !(o1 != 0) {
                        break
                }
-               o2 = c.opxrrr(p, AADD)
+               o2 = c.opxrrr(p, AADD, false)
                o2 |= REGTMP & 31 << 16
                o2 |= LSL0_64
                r := int(p.From.Reg)
@@ -3122,7 +3127,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
                        r = rt
                }
                if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
-                       o2 = c.opxrrr(p, p.As)
+                       o2 = c.opxrrr(p, p.As, false)
                        o2 |= REGTMP & 31 << 16
                        o2 |= LSL0_64
                } else {
@@ -3373,7 +3378,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
                }
 
                o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
-               o2 = c.opxrrr(p, AADD)
+               o2 = c.opxrrr(p, AADD, false)
                o2 |= (REGTMP & 31) << 16
                o2 |= uint32(r&31) << 5
                o2 |= uint32(REGTMP & 31)
@@ -3426,7 +3431,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
                        o3 |= 2 << 23
                }
                o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
-               o2 = c.opxrrr(p, AADD)
+               o2 = c.opxrrr(p, AADD, false)
                o2 |= REGTMP & 31 << 16
                o2 |= uint32(r&31) << 5
                o2 |= uint32(REGTMP & 31)
@@ -4518,33 +4523,44 @@ func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
 }
 
 /*
- * add/subtract extended register
+ * add/subtract sign or zero-extended register
  */
-func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As) uint32 {
+func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
+       extension := uint32(0)
+       if !extend {
+               switch a {
+               case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS:
+                       extension = LSL0_64
+
+               case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW:
+                       extension = LSL0_32
+               }
+       }
+
        switch a {
        case AADD:
-               return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64
+               return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
 
        case AADDW:
-               return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32
+               return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
 
        case ACMN, AADDS:
-               return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64
+               return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
 
        case ACMNW, AADDSW:
-               return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32
+               return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
 
        case ASUB:
-               return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64
+               return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
 
        case ASUBW:
-               return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32
+               return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
 
        case ACMP, ASUBS:
-               return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64
+               return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
 
        case ACMPW, ASUBSW:
-               return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32
+               return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
        }
 
        c.ctxt.Diag("bad opxrrr %v\n%v", a, p)