Commit 290de1f8 authored by Cherry Zhang's avatar Cherry Zhang

cmd/asm: reject STREX with same source and destination register on ARM

On ARM, STREX does not permit the same register used as both the
source and the destination. Reject the bad instruction.

The assembler also accepted special cases
	STREX R0, (R1)	as STREX R0, (R1), R0
	STREX (R1), R0	as STREX R0, (R1), R0
both are illegal. Remove this special case as well.

For STREXD, check that the destination is not source, and not
source+1. Also check that the source register is even numbered,
as required by the architecture's manual.

Fixes #22268.

Change-Id: I6bfde86ae692d8f1d35bd0bd7aac0f8a11ce8e22
Reviewed-on: https://go-review.googlesource.com/71190
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent fc5841af
......@@ -507,27 +507,6 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
break
}
// Strange special cases.
if arch.IsARMSTREX(op) {
/*
STREX x, (y)
from=(y) reg=x to=x
STREX (x), y
from=(x) reg=y to=y
*/
if a[0].Type == obj.TYPE_REG && a[1].Type != obj.TYPE_REG {
prog.From = a[1]
prog.Reg = a[0].Reg
prog.To = a[0]
break
} else if a[0].Type != obj.TYPE_REG && a[1].Type == obj.TYPE_REG {
prog.From = a[0]
prog.Reg = a[1].Reg
prog.To = a[1]
break
}
p.errorf("unrecognized addressing for %s", op)
return
}
if arch.IsARMFloatCmp(op) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
......
......@@ -156,18 +156,6 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0
// }
STREX R1, (R2), R3 // STREX (R2), R1, R3
// LTYPE9 cond reg ',' ireg
// {
// outcode($1, $2, &$5, int32($3.Reg), &$3);
// }
STREX R1, (R2) // STREX (R2), R1, R1
// LTYPE9 cond comma ireg ',' reg
// {
// outcode($1, $2, &$4, int32($6.Reg), &$6);
// }
STREX (R2), R3 // STREX (R2), R3, R3
//
// word
//
......@@ -771,21 +759,21 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0
B jmp_label_0 // JMP // ffffffea
jmp_label_0:
ADD $0, R0, R0
BEQ jmp_label_0 // BEQ 521 // fdffff0a
BNE jmp_label_0 // BNE 521 // fcffff1a
BCS jmp_label_0 // BCS 521 // fbffff2a
BCC jmp_label_0 // BCC 521 // faffff3a
BMI jmp_label_0 // BMI 521 // f9ffff4a
BPL jmp_label_0 // BPL 521 // f8ffff5a
BVS jmp_label_0 // BVS 521 // f7ffff6a
BVC jmp_label_0 // BVC 521 // f6ffff7a
BHI jmp_label_0 // BHI 521 // f5ffff8a
BLS jmp_label_0 // BLS 521 // f4ffff9a
BGE jmp_label_0 // BGE 521 // f3ffffaa
BLT jmp_label_0 // BLT 521 // f2ffffba
BGT jmp_label_0 // BGT 521 // f1ffffca
BLE jmp_label_0 // BLE 521 // f0ffffda
B jmp_label_0 // JMP 521 // efffffea
BEQ jmp_label_0 // BEQ 519 // fdffff0a
BNE jmp_label_0 // BNE 519 // fcffff1a
BCS jmp_label_0 // BCS 519 // fbffff2a
BCC jmp_label_0 // BCC 519 // faffff3a
BMI jmp_label_0 // BMI 519 // f9ffff4a
BPL jmp_label_0 // BPL 519 // f8ffff5a
BVS jmp_label_0 // BVS 519 // f7ffff6a
BVC jmp_label_0 // BVC 519 // f6ffff7a
BHI jmp_label_0 // BHI 519 // f5ffff8a
BLS jmp_label_0 // BLS 519 // f4ffff9a
BGE jmp_label_0 // BGE 519 // f3ffffaa
BLT jmp_label_0 // BLT 519 // f2ffffba
BGT jmp_label_0 // BGT 519 // f1ffffca
BLE jmp_label_0 // BLE 519 // f0ffffda
B jmp_label_0 // JMP 519 // efffffea
B 0(PC) // JMP 0(PC) // feffffea
jmp_label_1:
B jmp_label_1 // JMP // feffffea
......@@ -816,21 +804,21 @@ jmp_label_1:
BL jmp_label_2 // CALL // ffffffeb
jmp_label_2:
ADD $0, R0, R0
BL.EQ jmp_label_2 // CALL.EQ 562 // fdffff0b
BL.NE jmp_label_2 // CALL.NE 562 // fcffff1b
BL.CS jmp_label_2 // CALL.CS 562 // fbffff2b
BL.CC jmp_label_2 // CALL.CC 562 // faffff3b
BL.MI jmp_label_2 // CALL.MI 562 // f9ffff4b
BL.PL jmp_label_2 // CALL.PL 562 // f8ffff5b
BL.VS jmp_label_2 // CALL.VS 562 // f7ffff6b
BL.VC jmp_label_2 // CALL.VC 562 // f6ffff7b
BL.HI jmp_label_2 // CALL.HI 562 // f5ffff8b
BL.LS jmp_label_2 // CALL.LS 562 // f4ffff9b
BL.GE jmp_label_2 // CALL.GE 562 // f3ffffab
BL.LT jmp_label_2 // CALL.LT 562 // f2ffffbb
BL.GT jmp_label_2 // CALL.GT 562 // f1ffffcb
BL.LE jmp_label_2 // CALL.LE 562 // f0ffffdb
BL jmp_label_2 // CALL 562 // efffffeb
BL.EQ jmp_label_2 // CALL.EQ 560 // fdffff0b
BL.NE jmp_label_2 // CALL.NE 560 // fcffff1b
BL.CS jmp_label_2 // CALL.CS 560 // fbffff2b
BL.CC jmp_label_2 // CALL.CC 560 // faffff3b
BL.MI jmp_label_2 // CALL.MI 560 // f9ffff4b
BL.PL jmp_label_2 // CALL.PL 560 // f8ffff5b
BL.VS jmp_label_2 // CALL.VS 560 // f7ffff6b
BL.VC jmp_label_2 // CALL.VC 560 // f6ffff7b
BL.HI jmp_label_2 // CALL.HI 560 // f5ffff8b
BL.LS jmp_label_2 // CALL.LS 560 // f4ffff9b
BL.GE jmp_label_2 // CALL.GE 560 // f3ffffab
BL.LT jmp_label_2 // CALL.LT 560 // f2ffffbb
BL.GT jmp_label_2 // CALL.GT 560 // f1ffffcb
BL.LE jmp_label_2 // CALL.LE 560 // f0ffffdb
BL jmp_label_2 // CALL 560 // efffffeb
BL 0(PC) // CALL 0(PC) // feffffeb
jmp_label_3:
BL jmp_label_3 // CALL // feffffeb
......
......@@ -162,4 +162,13 @@ TEXT errors(SB),$0
XTABU R0->24, R5, R2 // ERROR "illegal shift"
XTAHU R0@>1, R5, R2 // ERROR "illegal shift"
STREX R1, (R0) // ERROR "illegal combination"
STREX (R1), R0 // ERROR "illegal combination"
STREX R1, (R0), R1 // ERROR "cannot use same register as both source and destination"
STREX R1, (R0), R0 // ERROR "cannot use same register as both source and destination"
STREXD R0, (R2), R0 // ERROR "cannot use same register as both source and destination"
STREXD R0, (R2), R1 // ERROR "cannot use same register as both source and destination"
STREXD R0, (R2), R2 // ERROR "cannot use same register as both source and destination"
STREXD R1, (R4), R7 // ERROR "must be even"
END
......@@ -2611,6 +2611,9 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
if c.instoffset != 0 {
c.ctxt.Diag("offset must be zero in STREX")
}
if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg {
c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
}
o1 = 0x18<<20 | 0xf90
o1 |= (uint32(p.From.Reg) & 15) << 16
o1 |= (uint32(p.Reg) & 15) << 0
......@@ -2725,6 +2728,12 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
if c.instoffset != 0 {
c.ctxt.Diag("offset must be zero in STREX")
}
if p.Reg&1 != 0 {
c.ctxt.Diag("source register must be even in STREXD: %v", p)
}
if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg || p.To.Reg == p.Reg+1 {
c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
}
o1 = 0x1a<<20 | 0xf90
o1 |= (uint32(p.From.Reg) & 15) << 16
o1 |= (uint32(p.Reg) & 15) << 0
......
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