mirror of
https://github.com/golang/go
synced 2024-11-17 14:04:48 -07:00
cmd/internal/obj/arm64: add checks for incorrect use of REGTMP register
The current assembler uses REGTMP as a temporary destination register, when optimizing one instruction into a multi-instruction sequence. But in some cases, when the source register is REGTMP, this behavior is incorrect. For example: ADD $0x1234567, R27, R3 The current assembler encodes it into MOVD $17767, R27 MOVK $(291<<16), R27 ADD R27, R27, R3 It is illegal to overwrite R27. This CL adds the related checks. Add test cases. Change-Id: I0af373d9fd23d8f067c093778dd4cc76748faf38 Reviewed-on: https://go-review.googlesource.com/c/go/+/344689 Reviewed-by: Cherry Mui <cherryyz@google.com> Run-TryBot: Cherry Mui <cherryyz@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: fannie zhang <Fannie.Zhang@arm.com>
This commit is contained in:
parent
42563f89d7
commit
9cbc76bdf9
21
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
21
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
@ -406,12 +406,12 @@ TEXT errors(SB),$0
|
|||||||
VBIF V0.D2, V1.D2, V2.D2 // ERROR "invalid arrangement"
|
VBIF V0.D2, V1.D2, V2.D2 // ERROR "invalid arrangement"
|
||||||
VUADDW V9.B8, V12.H8, V14.B8 // ERROR "invalid arrangement"
|
VUADDW V9.B8, V12.H8, V14.B8 // ERROR "invalid arrangement"
|
||||||
VUADDW2 V9.B8, V12.S4, V14.S4 // ERROR "operand mismatch"
|
VUADDW2 V9.B8, V12.S4, V14.S4 // ERROR "operand mismatch"
|
||||||
VUMAX V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement"
|
VUMAX V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement"
|
||||||
VUMIN V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement"
|
VUMIN V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement"
|
||||||
VUMAX V1.B8, V2.B8, V3.B16 // ERROR "operand mismatch"
|
VUMAX V1.B8, V2.B8, V3.B16 // ERROR "operand mismatch"
|
||||||
VUMIN V1.H4, V2.S4, V3.H4 // ERROR "operand mismatch"
|
VUMIN V1.H4, V2.S4, V3.H4 // ERROR "operand mismatch"
|
||||||
VSLI $64, V7.D2, V8.D2 // ERROR "shift out of range"
|
VSLI $64, V7.D2, V8.D2 // ERROR "shift out of range"
|
||||||
VUSRA $0, V7.D2, V8.D2 // ERROR "shift out of range"
|
VUSRA $0, V7.D2, V8.D2 // ERROR "shift out of range"
|
||||||
CASPD (R3, R4), (R2), (R8, R9) // ERROR "source register pair must start from even register"
|
CASPD (R3, R4), (R2), (R8, R9) // ERROR "source register pair must start from even register"
|
||||||
CASPD (R2, R3), (R2), (R9, R10) // ERROR "destination register pair must start from even register"
|
CASPD (R2, R3), (R2), (R9, R10) // ERROR "destination register pair must start from even register"
|
||||||
CASPD (R2, R4), (R2), (R8, R9) // ERROR "source register pair must be contiguous"
|
CASPD (R2, R4), (R2), (R8, R9) // ERROR "source register pair must be contiguous"
|
||||||
@ -419,8 +419,15 @@ TEXT errors(SB),$0
|
|||||||
ADD R1>>2, RSP, R3 // ERROR "illegal combination"
|
ADD R1>>2, RSP, R3 // ERROR "illegal combination"
|
||||||
ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference"
|
ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference"
|
||||||
CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4"
|
CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4"
|
||||||
MOVD.P y+8(FP), R1 // ERROR "illegal combination"
|
MOVD.P y+8(FP), R1 // ERROR "illegal combination"
|
||||||
MOVD.W x-8(SP), R1 // ERROR "illegal combination"
|
MOVD.W x-8(SP), R1 // ERROR "illegal combination"
|
||||||
LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination"
|
LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination"
|
||||||
LDP.W x+8(SP), (R0, R1) // ERROR "illegal combination"
|
LDP.W x+8(SP), (R0, R1) // ERROR "illegal combination"
|
||||||
|
ADD $0x1234567, R27, R3 // ERROR "cannot use REGTMP as source"
|
||||||
|
ADD $0x3fffffffc000, R27, R5 // ERROR "cannot use REGTMP as source"
|
||||||
|
AND $0x22220000, R27, R4 // ERROR "cannot use REGTMP as source"
|
||||||
|
ANDW $0x6006000060060, R27, R5 // ERROR "cannot use REGTMP as source"
|
||||||
|
STP (R3, R4), 0x1234567(R27) // ERROR "REGTMP used in large offset store"
|
||||||
|
LDP 0x1234567(R27), (R3, R4) // ERROR "REGTMP used in large offset load"
|
||||||
|
STP (R26, R27), 700(R2) // ERROR "cannot use REGTMP as source"
|
||||||
RET
|
RET
|
||||||
|
@ -3407,6 +3407,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
o4 = os[3]
|
o4 = os[3]
|
||||||
|
|
||||||
case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
|
case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
|
||||||
|
if p.Reg == REGTMP {
|
||||||
|
c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
|
||||||
|
}
|
||||||
if p.To.Reg == REG_RSP && isADDSop(p.As) {
|
if p.To.Reg == REG_RSP && isADDSop(p.As) {
|
||||||
c.ctxt.Diag("illegal destination register: %v\n", p)
|
c.ctxt.Diag("illegal destination register: %v\n", p)
|
||||||
}
|
}
|
||||||
@ -3724,6 +3727,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
o1 |= (uint32(r&31) << 5) | uint32(rt&31)
|
o1 |= (uint32(r&31) << 5) | uint32(rt&31)
|
||||||
|
|
||||||
case 28: /* logop $vcon, [R], R (64 bit literal) */
|
case 28: /* logop $vcon, [R], R (64 bit literal) */
|
||||||
|
if p.Reg == REGTMP {
|
||||||
|
c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
|
||||||
|
}
|
||||||
o := uint32(0)
|
o := uint32(0)
|
||||||
num := uint8(0)
|
num := uint8(0)
|
||||||
cls := oclass(&p.From)
|
cls := oclass(&p.From)
|
||||||
@ -4354,6 +4360,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
|
|
||||||
/* reloc ops */
|
/* reloc ops */
|
||||||
case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
|
case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
|
||||||
|
if p.From.Reg == REGTMP {
|
||||||
|
c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
|
||||||
|
}
|
||||||
o1 = ADR(1, 0, REGTMP)
|
o1 = ADR(1, 0, REGTMP)
|
||||||
o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
|
o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
|
||||||
rel := obj.Addrel(c.cursym)
|
rel := obj.Addrel(c.cursym)
|
||||||
@ -4585,6 +4594,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
// add Rtmp, R, Rtmp
|
// add Rtmp, R, Rtmp
|
||||||
// ldp (Rtmp), (R1, R2)
|
// ldp (Rtmp), (R1, R2)
|
||||||
r := int(p.From.Reg)
|
r := int(p.From.Reg)
|
||||||
|
if r == REGTMP {
|
||||||
|
c.ctxt.Diag("REGTMP used in large offset load: %v", p)
|
||||||
|
}
|
||||||
if r == obj.REG_NONE {
|
if r == obj.REG_NONE {
|
||||||
r = int(o.param)
|
r = int(o.param)
|
||||||
}
|
}
|
||||||
@ -4601,6 +4613,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
case 76:
|
case 76:
|
||||||
// add $O, R, Rtmp or sub $O, R, Rtmp
|
// add $O, R, Rtmp or sub $O, R, Rtmp
|
||||||
// stp (R1, R2), (Rtmp)
|
// stp (R1, R2), (Rtmp)
|
||||||
|
if p.From.Reg == REGTMP || p.From.Offset == REGTMP {
|
||||||
|
c.ctxt.Diag("cannot use REGTMP as source: %v", p)
|
||||||
|
}
|
||||||
r := int(p.To.Reg)
|
r := int(p.To.Reg)
|
||||||
if r == obj.REG_NONE {
|
if r == obj.REG_NONE {
|
||||||
r = int(o.param)
|
r = int(o.param)
|
||||||
@ -4628,6 +4643,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
// add Rtmp, R, Rtmp
|
// add Rtmp, R, Rtmp
|
||||||
// stp (R1, R2), (Rtmp)
|
// stp (R1, R2), (Rtmp)
|
||||||
r := int(p.To.Reg)
|
r := int(p.To.Reg)
|
||||||
|
if r == REGTMP || p.From.Reg == REGTMP || p.From.Offset == REGTMP {
|
||||||
|
c.ctxt.Diag("REGTMP used in large offset store: %v", p)
|
||||||
|
}
|
||||||
if r == obj.REG_NONE {
|
if r == obj.REG_NONE {
|
||||||
r = int(o.param)
|
r = int(o.param)
|
||||||
}
|
}
|
||||||
@ -4933,6 +4951,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
|
o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
|
||||||
|
|
||||||
case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
|
case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
|
||||||
|
if p.From.Reg == REGTMP || p.From.Offset == REGTMP {
|
||||||
|
c.ctxt.Diag("cannot use REGTMP as source: %v", p)
|
||||||
|
}
|
||||||
o1 = ADR(1, 0, REGTMP)
|
o1 = ADR(1, 0, REGTMP)
|
||||||
o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
|
o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
|
||||||
rel := obj.Addrel(c.cursym)
|
rel := obj.Addrel(c.cursym)
|
||||||
|
Loading…
Reference in New Issue
Block a user