]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm: report invalid .S/.P/.W suffix in ARM instructions
authorBen Shi <powerman1st@163.com>
Wed, 17 May 2017 07:00:27 +0000 (07:00 +0000)
committerCherry Zhang <cherryyz@google.com>
Mon, 22 May 2017 13:44:12 +0000 (13:44 +0000)
Many instructions can not have a .S suffix, such as MULS, SWI, CLZ,
CMP, STREX and others. And so do .P and .W suffixes. Even wrong
assembly code is generated for some instructions with invalid
suffixes.

This patch tries to simplify .S/.W/.P checks. And a wrong assembly
test for arm is added.

fixes #20377

Change-Id: Iba1c99d9e6b7b16a749b4d93ca2102e17c5822fe
Reviewed-on: https://go-review.googlesource.com/43561
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/asm/internal/asm/endtoend_test.go
src/cmd/asm/internal/asm/testdata/arm.s
src/cmd/asm/internal/asm/testdata/armerror.s [new file with mode: 0644]
src/cmd/internal/obj/arm/asm5.go

index 36aa4aedd836a24267b56e447b36146e53e88f2a..7554a30b541e3bf070f05e60aaa860c668f3d3df 100644 (file)
@@ -371,6 +371,10 @@ func TestARMEndToEnd(t *testing.T) {
        }
 }
 
+func TestARMErrors(t *testing.T) {
+       testErrors(t, "arm", "armerror")
+}
+
 func TestARM64EndToEnd(t *testing.T) {
        testEndToEnd(t, "arm64", "arm64")
 }
index 66fb207e3e2997e7a24d5d1337c4ab80a7c6913d..1e260756116757ed739a02ec90736d4cc81a9dca 100644 (file)
@@ -47,7 +47,7 @@ TEXT  foo(SB), DUPOK|NOSPLIT, $0
 //     {
 //             outcode($1, $2, &$3, 0, &$5);
 //     }
-       CLZ.S   R1, R2
+       CLZ     R1, R2
 
 //
 // MOVW
@@ -114,9 +114,9 @@ TEXT        foo(SB), DUPOK|NOSPLIT, $0
 //     {
 //             outcode($1, $2, &$3, $5, &nullgen);
 //     }
-       CMP.S   $1, R2
-       CMP.S   R1<<R2, R3
-       CMP.S   R1, R2
+       CMP     $1, R2
+       CMP     R1<<R2, R3
+       CMP     R1, R2
 
 //
 // MOVM
@@ -132,7 +132,7 @@ TEXT        foo(SB), DUPOK|NOSPLIT, $0
 //     }
        MOVM    0(R1), [R2,R5,R8,g] // MOVM     (R1), [R2,R5,R8,g]
        MOVM    (R1), [R2-R5] // MOVM (R1), [R2,R3,R4,R5]
-       MOVM.S  (R1), [R2]
+       MOVM    (R1), [R2]
 
 //     LTYPE8 cond '[' reglist ']' ',' ioreg
 //     {
@@ -145,7 +145,7 @@ TEXT        foo(SB), DUPOK|NOSPLIT, $0
 //     }
        MOVM    [R2,R5,R8,g], 0(R1) // MOVM     [R2,R5,R8,g], (R1)
        MOVM    [R2-R5], (R1) // MOVM [R2,R3,R4,R5], (R1)
-       MOVM.S  [R2], (R1)
+       MOVM    [R2], (R1)
 
 //
 // SWAP
@@ -154,19 +154,19 @@ TEXT      foo(SB), DUPOK|NOSPLIT, $0
 //     {
 //             outcode($1, $2, &$5, int32($3.Reg), &$7);
 //     }
-       STREX.S R1, (R2), R3 // STREX.S (R2), R1, R3
+       STREX   R1, (R2), R3 // STREX (R2), R1, R3
 
 //     LTYPE9 cond reg ',' ireg
 //     {
 //             outcode($1, $2, &$5, int32($3.Reg), &$3);
 //     }
-       STREX.S R1, (R2) // STREX.S (R2), R1, R1
+       STREX   R1, (R2) // STREX (R2), R1, R1
 
 //     LTYPE9 cond comma ireg ',' reg
 //     {
 //             outcode($1, $2, &$4, int32($6.Reg), &$6);
 //     }
-       STREX.S (R2), R3 // STREX.S (R2), R3, R3
+       STREX   (R2), R3 // STREX (R2), R3, R3
 
 //
 // word
@@ -184,26 +184,26 @@ TEXT      foo(SB), DUPOK|NOSPLIT, $0
 //     {
 //             outcode($1, $2, &$3, 0, &$5);
 //     }
-       ABSF.S  F1, F2
+       ABSF    F1, F2
 
 //     LTYPEK cond frcon ',' freg
 //     {
 //             outcode($1, $2, &$3, 0, &$5);
 //     }
-       ADDD.S  F1, F2
+       ADDD    F1, F2
        MOVF    $0.5, F2 // MOVF $(0.5), F2
 
 //     LTYPEK cond frcon ',' LFREG ',' freg
 //     {
 //             outcode($1, $2, &$3, $5, &$7);
 //     }
-       ADDD.S  F1, F2, F3
+       ADDD    F1, F2, F3
 
 //     LTYPEL cond freg ',' freg
 //     {
 //             outcode($1, $2, &$3, int32($5.Reg), &nullgen);
 //     }
-       CMPD.S  F1, F2
+       CMPD    F1, F2
 
 //
 // MCR MRC
diff --git a/src/cmd/asm/internal/asm/testdata/armerror.s b/src/cmd/asm/internal/asm/testdata/armerror.s
new file mode 100644 (file)
index 0000000..9ef276b
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+TEXT errors(SB),$0
+       MULS.S  R1, R2, R3, R4     // ERROR "invalid .S suffix"
+       ADD.P   R1, R2, R3         // ERROR "invalid .P suffix"
+       SUB.W   R2, R3             // ERROR "invalid .W suffix"
+       BL      4(R4)              // ERROR "non-zero offset"
+       END
index 6d8856eed723d487bb682dcf2475152abc1198a2..7bb77b6e19841a13144ada8ec1d5bc0ef482cb63 100644 (file)
@@ -597,6 +597,64 @@ func (c *ctxt5) asmoutnacl(origPC int32, p *obj.Prog, o *Optab, out []uint32) in
        return size
 }
 
+const (
+       T_SBIT = 1 << 0
+       T_PBIT = 1 << 1
+       T_WBIT = 1 << 2
+)
+
+var mayHaveSuffix = map[obj.As]uint8{
+       // bit logic
+       AAND: T_SBIT,
+       AEOR: T_SBIT,
+       AORR: T_SBIT,
+       ABIC: T_SBIT,
+       // arithmatic
+       ASUB: T_SBIT,
+       AADD: T_SBIT,
+       ASBC: T_SBIT,
+       AADC: T_SBIT,
+       ARSB: T_SBIT,
+       ARSC: T_SBIT,
+       // mov
+       AMVN:   T_SBIT,
+       AMOVW:  T_SBIT | T_PBIT | T_WBIT,
+       AMOVB:  T_SBIT | T_PBIT | T_WBIT,
+       AMOVBS: T_SBIT | T_PBIT | T_WBIT,
+       AMOVBU: T_SBIT | T_PBIT | T_WBIT,
+       AMOVH:  T_SBIT | T_PBIT | T_WBIT,
+       AMOVHS: T_SBIT | T_PBIT | T_WBIT,
+       AMOVHU: T_SBIT | T_PBIT | T_WBIT,
+       AMOVM:  T_PBIT | T_WBIT,
+       // shift
+       ASRL: T_SBIT,
+       ASRA: T_SBIT,
+       ASLL: T_SBIT,
+       // mul
+       AMUL:   T_SBIT,
+       AMULU:  T_SBIT,
+       AMULL:  T_SBIT,
+       AMULLU: T_SBIT,
+       // mula
+       AMULA:   T_SBIT,
+       AMULAL:  T_SBIT,
+       AMULALU: T_SBIT,
+       // MRC/MCR
+       AMRC: T_SBIT,
+}
+
+func checkBits(ctxt *obj.Link, p *obj.Prog) {
+       if p.Scond&C_SBIT != 0 && mayHaveSuffix[p.As]&T_SBIT == 0 {
+               ctxt.Diag("invalid .S suffix: %v", p)
+       }
+       if p.Scond&C_PBIT != 0 && mayHaveSuffix[p.As]&T_PBIT == 0 {
+               ctxt.Diag("invalid .P suffix: %v", p)
+       }
+       if p.Scond&C_WBIT != 0 && mayHaveSuffix[p.As]&T_WBIT == 0 {
+               ctxt.Diag("invalid .W suffix: %v", p)
+       }
+}
+
 func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
        var p *obj.Prog
        var op *obj.Prog
@@ -675,6 +733,9 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                if p.As == AMOVW && p.To.Type == obj.TYPE_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE {
                        c.flushpool(p, 0, 0)
                }
+
+               checkBits(ctxt, p)
+
                pc += int32(m)
        }
 
@@ -2032,9 +2093,6 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
                if p.Scond&C_UBIT != 0 {
                        o1 |= 1 << 23
                }
-               if p.Scond&C_SBIT != 0 {
-                       o1 |= 1 << 22
-               }
                if p.Scond&C_WBIT != 0 {
                        o1 |= 1 << 21
                }
@@ -2610,9 +2668,6 @@ func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
        if sc&C_SBIT != 0 {
                o |= 1 << 20
        }
-       if sc&(C_PBIT|C_WBIT) != 0 {
-               c.ctxt.Diag(".nil/.W on dp instruction")
-       }
        switch a {
        case ADIVHW:
                return o | 0x71<<20 | 0xf<<12 | 0x1<<4
@@ -2666,6 +2721,9 @@ func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
                return o | 0xc<<21
 
        case AMOVB, AMOVH, AMOVW:
+               if sc&(C_PBIT|C_WBIT) != 0 {
+                       c.ctxt.Diag("invalid .P/.W suffix: %v", p)
+               }
                return o | 0xd<<21
        case ABIC:
                return o | 0xe<<21
@@ -2799,9 +2857,6 @@ func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
 }
 
 func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 {
-       if sc&(C_SBIT|C_PBIT|C_WBIT) != 0 {
-               c.ctxt.Diag("%v: .nil/.nil/.W on bra instruction", p)
-       }
        sc &= C_SCOND
        sc ^= C_SCOND_XOR
        if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY {
@@ -2939,9 +2994,6 @@ func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 {
 }
 
 func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
-       if sc&C_SBIT != 0 {
-               c.ctxt.Diag(".nil on FLDR/FSTR instruction: %v", p)
-       }
        o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
        if sc&C_PBIT == 0 {
                o |= 1 << 24