diff options
author | fanzha02 <fannie.zhang@arm.com> | 2021-08-24 12:46:54 +0800 |
---|---|---|
committer | fannie zhang <Fannie.Zhang@arm.com> | 2021-09-09 01:23:30 +0000 |
commit | 9cbc76bdf90752e21a2b3f05944552e1373ab433 (patch) | |
tree | 9e7409d998fb2eb2f80f7156e0bb5baa3515a753 | |
parent | 42563f89d7093ab22e1ac42351e66c4d03e0c80e (diff) | |
download | go-9cbc76bdf90752e21a2b3f05944552e1373ab433.tar.gz go-9cbc76bdf90752e21a2b3f05944552e1373ab433.zip |
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>
-rw-r--r-- | src/cmd/asm/internal/asm/testdata/arm64error.s | 21 | ||||
-rw-r--r-- | src/cmd/internal/obj/arm64/asm7.go | 21 |
2 files changed, 35 insertions, 7 deletions
diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 8b12b16680..7b006432c0 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -406,12 +406,12 @@ TEXT errors(SB),$0 VBIF V0.D2, V1.D2, V2.D2 // ERROR "invalid arrangement" VUADDW V9.B8, V12.H8, V14.B8 // ERROR "invalid arrangement" VUADDW2 V9.B8, V12.S4, V14.S4 // ERROR "operand mismatch" - VUMAX V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement" - VUMIN 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" VUMAX V1.B8, V2.B8, V3.B16 // ERROR "operand mismatch" VUMIN V1.H4, V2.S4, V3.H4 // ERROR "operand mismatch" 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 (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" @@ -419,8 +419,15 @@ TEXT errors(SB),$0 ADD R1>>2, RSP, R3 // ERROR "illegal combination" ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference" 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.W x-8(SP), R1 // ERROR "illegal combination" - LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination" - LDP.W x+8(SP), (R0, R1) // ERROR "illegal combination" + MOVD.P y+8(FP), R1 // ERROR "illegal combination" + MOVD.W x-8(SP), R1 // ERROR "illegal combination" + LDP.P x+8(FP), (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 diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 8db25cf967..5d6caaed5f 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -3407,6 +3407,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { o4 = os[3] 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) { 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) 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) num := uint8(0) cls := oclass(&p.From) @@ -4354,6 +4360,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { /* reloc ops */ 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) o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 rel := obj.Addrel(c.cursym) @@ -4585,6 +4594,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { // add Rtmp, R, Rtmp // ldp (Rtmp), (R1, R2) r := int(p.From.Reg) + if r == REGTMP { + c.ctxt.Diag("REGTMP used in large offset load: %v", p) + } if r == obj.REG_NONE { r = int(o.param) } @@ -4601,6 +4613,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { case 76: // add $O, R, Rtmp or sub $O, R, 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) if r == obj.REG_NONE { r = int(o.param) @@ -4628,6 +4643,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { // add Rtmp, R, Rtmp // stp (R1, R2), (Rtmp) 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 { 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) 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) o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 rel := obj.Addrel(c.cursym) |