Commit 5e797879 authored by Ben Shi's avatar Ben Shi Committed by Cherry Zhang

cmd/internal/obj/arm: report invalid .S/.P/.W suffix in ARM instructions

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/43561Reviewed-by: 's avatarCherry Zhang <cherryyz@google.com>
parent 4bf6c566
...@@ -371,6 +371,10 @@ func TestARMEndToEnd(t *testing.T) { ...@@ -371,6 +371,10 @@ func TestARMEndToEnd(t *testing.T) {
} }
} }
func TestARMErrors(t *testing.T) {
testErrors(t, "arm", "armerror")
}
func TestARM64EndToEnd(t *testing.T) { func TestARM64EndToEnd(t *testing.T) {
testEndToEnd(t, "arm64", "arm64") testEndToEnd(t, "arm64", "arm64")
} }
......
...@@ -47,7 +47,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0 ...@@ -47,7 +47,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0
// { // {
// outcode($1, $2, &$3, 0, &$5); // outcode($1, $2, &$3, 0, &$5);
// } // }
CLZ.S R1, R2 CLZ R1, R2
// //
// MOVW // MOVW
...@@ -114,9 +114,9 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0 ...@@ -114,9 +114,9 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0
// { // {
// outcode($1, $2, &$3, $5, &nullgen); // outcode($1, $2, &$3, $5, &nullgen);
// } // }
CMP.S $1, R2 CMP $1, R2
CMP.S R1<<R2, R3 CMP R1<<R2, R3
CMP.S R1, R2 CMP R1, R2
// //
// MOVM // MOVM
...@@ -132,7 +132,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0 ...@@ -132,7 +132,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0
// } // }
MOVM 0(R1), [R2,R5,R8,g] // MOVM (R1), [R2,R5,R8,g] MOVM 0(R1), [R2,R5,R8,g] // MOVM (R1), [R2,R5,R8,g]
MOVM (R1), [R2-R5] // MOVM (R1), [R2,R3,R4,R5] MOVM (R1), [R2-R5] // MOVM (R1), [R2,R3,R4,R5]
MOVM.S (R1), [R2] MOVM (R1), [R2]
// LTYPE8 cond '[' reglist ']' ',' ioreg // LTYPE8 cond '[' reglist ']' ',' ioreg
// { // {
...@@ -145,7 +145,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0 ...@@ -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,R8,g], 0(R1) // MOVM [R2,R5,R8,g], (R1)
MOVM [R2-R5], (R1) // MOVM [R2,R3,R4,R5], (R1) MOVM [R2-R5], (R1) // MOVM [R2,R3,R4,R5], (R1)
MOVM.S [R2], (R1) MOVM [R2], (R1)
// //
// SWAP // SWAP
...@@ -154,19 +154,19 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0 ...@@ -154,19 +154,19 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0
// { // {
// outcode($1, $2, &$5, int32($3.Reg), &$7); // 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 // LTYPE9 cond reg ',' ireg
// { // {
// outcode($1, $2, &$5, int32($3.Reg), &$3); // 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 // LTYPE9 cond comma ireg ',' reg
// { // {
// outcode($1, $2, &$4, int32($6.Reg), &$6); // 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 // word
...@@ -184,26 +184,26 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0 ...@@ -184,26 +184,26 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0
// { // {
// outcode($1, $2, &$3, 0, &$5); // outcode($1, $2, &$3, 0, &$5);
// } // }
ABSF.S F1, F2 ABSF F1, F2
// LTYPEK cond frcon ',' freg // LTYPEK cond frcon ',' freg
// { // {
// outcode($1, $2, &$3, 0, &$5); // outcode($1, $2, &$3, 0, &$5);
// } // }
ADDD.S F1, F2 ADDD F1, F2
MOVF $0.5, F2 // MOVF $(0.5), F2 MOVF $0.5, F2 // MOVF $(0.5), F2
// LTYPEK cond frcon ',' LFREG ',' freg // LTYPEK cond frcon ',' LFREG ',' freg
// { // {
// outcode($1, $2, &$3, $5, &$7); // outcode($1, $2, &$3, $5, &$7);
// } // }
ADDD.S F1, F2, F3 ADDD F1, F2, F3
// LTYPEL cond freg ',' freg // LTYPEL cond freg ',' freg
// { // {
// outcode($1, $2, &$3, int32($5.Reg), &nullgen); // outcode($1, $2, &$3, int32($5.Reg), &nullgen);
// } // }
CMPD.S F1, F2 CMPD F1, F2
// //
// MCR MRC // MCR MRC
......
// 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
...@@ -597,6 +597,64 @@ func (c *ctxt5) asmoutnacl(origPC int32, p *obj.Prog, o *Optab, out []uint32) in ...@@ -597,6 +597,64 @@ func (c *ctxt5) asmoutnacl(origPC int32, p *obj.Prog, o *Optab, out []uint32) in
return size 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) { func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
var p *obj.Prog var p *obj.Prog
var op *obj.Prog var op *obj.Prog
...@@ -675,6 +733,9 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -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 { 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) c.flushpool(p, 0, 0)
} }
checkBits(ctxt, p)
pc += int32(m) pc += int32(m)
} }
...@@ -2032,9 +2093,6 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) { ...@@ -2032,9 +2093,6 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
if p.Scond&C_UBIT != 0 { if p.Scond&C_UBIT != 0 {
o1 |= 1 << 23 o1 |= 1 << 23
} }
if p.Scond&C_SBIT != 0 {
o1 |= 1 << 22
}
if p.Scond&C_WBIT != 0 { if p.Scond&C_WBIT != 0 {
o1 |= 1 << 21 o1 |= 1 << 21
} }
...@@ -2610,9 +2668,6 @@ func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 { ...@@ -2610,9 +2668,6 @@ func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
if sc&C_SBIT != 0 { if sc&C_SBIT != 0 {
o |= 1 << 20 o |= 1 << 20
} }
if sc&(C_PBIT|C_WBIT) != 0 {
c.ctxt.Diag(".nil/.W on dp instruction")
}
switch a { switch a {
case ADIVHW: case ADIVHW:
return o | 0x71<<20 | 0xf<<12 | 0x1<<4 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 { ...@@ -2666,6 +2721,9 @@ func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
return o | 0xc<<21 return o | 0xc<<21
case AMOVB, AMOVH, AMOVW: case AMOVB, AMOVH, AMOVW:
if sc&(C_PBIT|C_WBIT) != 0 {
c.ctxt.Diag("invalid .P/.W suffix: %v", p)
}
return o | 0xd<<21 return o | 0xd<<21
case ABIC: case ABIC:
return o | 0xe<<21 return o | 0xe<<21
...@@ -2799,9 +2857,6 @@ func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 { ...@@ -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 { 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
sc ^= C_SCOND_XOR sc ^= C_SCOND_XOR
if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY { 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 { ...@@ -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 { 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 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
if sc&C_PBIT == 0 { if sc&C_PBIT == 0 {
o |= 1 << 24 o |= 1 << 24
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment