1
0
mirror of https://github.com/golang/go synced 2024-11-26 11:58:07 -07:00

cmd/asm: add check for register and shift/extension combination on arm64

The current code lacks a check on whether the register and shift/extension
combination is valid, for example the follow instructions also compiles.
	ADD     F1<<1, R1, R3
	ADD     V1<<1, R1, R3
	MOVW    (R9)(F8.SXTW<<2), R19
	VST1    R4.D[1], (R0)

Actually only general registers can perform shift operations, and element
and arrangement extensions are only applicable to vector registers. This
CL adds a check for the register and shift/extension combination on arm64.

Change-Id: I93dd9343e92a66899cba8eaf4e0ac5430e94692b
Reviewed-on: https://go-review.googlesource.com/c/go/+/312571
Trust: eric fang <eric.fang@arm.com>
Reviewed-by: eric fang <eric.fang@arm.com>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: eric fang <eric.fang@arm.com>
TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
eric fang 2021-04-21 03:12:20 +00:00
parent f439a76253
commit 9726c78539
3 changed files with 175 additions and 153 deletions

View File

@ -147,7 +147,16 @@ func arm64RegisterNumber(name string, n int16) (int16, bool) {
return 0, false
}
// ARM64RegisterExtension parses an ARM64 register with extension or arrangement.
// ARM64RegisterShift constructs an ARM64 register with shift operation.
func ARM64RegisterShift(reg, op, count int16) (int64, error) {
// the base register of shift operations must be general register.
if reg > arm64.REG_R31 || reg < arm64.REG_R0 {
return 0, errors.New("invalid register for shift operation")
}
return int64(reg&31)<<16 | int64(op)<<22 | int64(uint16(count)), nil
}
// ARM64RegisterExtension constructs an ARM64 register with extension or arrangement.
func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
Rnum := (reg & 31) + int16(num<<5)
if isAmount {
@ -155,6 +164,7 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
return errors.New("index shift amount is out of range")
}
}
if reg <= arm64.REG_R31 && reg >= arm64.REG_R0 {
switch ext {
case "UXTB":
if !isAmount {
@ -226,6 +236,12 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
return errors.New("invalid register extension")
}
a.Index = arm64.REG_LSL + Rnum
default:
return errors.New("unsupported general register extension type: " + ext)
}
} else if reg <= arm64.REG_V31 && reg >= arm64.REG_V0 {
switch ext {
case "B8":
if isIndex {
return errors.New("invalid register extension")
@ -296,13 +312,15 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_D & 15) << 5)
a.Index = num
default:
return errors.New("unsupported register extension type: " + ext)
return errors.New("unsupported simd register extension type: " + ext)
}
} else {
return errors.New("invalid register and extension combination")
}
return nil
}
// ARM64RegisterArrangement parses an ARM64 vector register arrangement.
// ARM64RegisterArrangement constructs an ARM64 vector register arrangement.
func ARM64RegisterArrangement(reg int16, name, arng string) (int64, error) {
var curQ, curSize uint16
if name[0] != 'V' {

View File

@ -689,7 +689,11 @@ func (p *Parser) registerShift(name string, prefix rune) int64 {
p.errorf("unexpected %s in register shift", tok.String())
}
if p.arch.Family == sys.ARM64 {
return int64(r1&31)<<16 | int64(op)<<22 | int64(uint16(count))
off, err := arch.ARM64RegisterShift(r1, op, count)
if err != nil {
p.errorf(err.Error())
}
return off
} else {
return int64((r1 & 15) | op<<5 | count)
}

View File

@ -96,13 +96,13 @@ TEXT errors(SB),$0
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"
VDUP V8.B[16], V3.B16 // ERROR "register element index out of range 0 to 15"
VDUP V8.B[17], V3.B8 // ERROR "register element index out of range 0 to 15"
VDUP V8.H[9], V3.H4 // ERROR "register element index out of range 0 to 7"
VDUP V8.H[9], V3.H8 // ERROR "register element index out of range 0 to 7"
VDUP V8.S[4], V3.S2 // ERROR "register element index out of range 0 to 3"
VDUP V8.S[4], V3.S4 // ERROR "register element index out of range 0 to 3"
VDUP V8.D[2], V3.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"