aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Shi <powerman1st@163.com>2018-03-20 08:25:08 +0000
committerCherry Zhang <cherryyz@google.com>2018-04-11 16:06:01 +0000
commite1040d79557de627b18c928a3c498e89f1dcd9da (patch)
tree2ff1d1988014aca06a4caac9575fbe37688642d6 /src
parent9446eaa9443cb4ac5e2dcdc0f7a8d3633d96b3ec (diff)
downloadgo-e1040d79557de627b18c928a3c498e89f1dcd9da.tar.xz
cmd/internal/obj/arm64: support SWPD/SWPW/SWPH/SWPB
SWPD/SWPW/SWPH/SWPB were introduced in ARMv8.1. They swap content of register and memory atomically. And their difference is SWPD: 64-bit double word data SWPW: 32-bit word data (zero extended to 64-bit) SWPH: 16-bit half word data (zero extended to 64-bit) SWPB: 8-bit byte data (zero extended to 64-bit) This CL implements them in the arm64 assembler. Change-Id: I2d9fb2310674bd92693531210e187143e7eed602 Reviewed-on: https://go-review.googlesource.com/101516 Reviewed-by: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/asm/internal/arch/arm64.go11
-rw-r--r--src/cmd/asm/internal/asm/asm.go6
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm64.s10
-rw-r--r--src/cmd/internal/obj/arm64/a.out.go5
-rw-r--r--src/cmd/internal/obj/arm64/anames.go4
-rw-r--r--src/cmd/internal/obj/arm64/anames7.go1
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go64
7 files changed, 88 insertions, 13 deletions
diff --git a/src/cmd/asm/internal/arch/arm64.go b/src/cmd/asm/internal/arch/arm64.go
index 3941e36372..b311f4c738 100644
--- a/src/cmd/asm/internal/arch/arm64.go
+++ b/src/cmd/asm/internal/arch/arm64.go
@@ -78,6 +78,17 @@ func IsARM64STLXR(op obj.As) bool {
return false
}
+// IsARM64SWP reports whether the op (as defined by an arm64.A*
+// constant) is one of the SWP-like instructions that require special
+// handling.
+func IsARM64SWP(op obj.As) bool {
+ switch op {
+ case arm64.ASWPD, arm64.ASWPW, arm64.ASWPH, arm64.ASWPB:
+ return true
+ }
+ return false
+}
+
// ARM64Suffix handles the special suffix for the ARM64.
// It returns a boolean to indicate success; failure means
// cond was unrecognized.
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
index 78ca4f554d..6261aa843b 100644
--- a/src/cmd/asm/internal/asm/asm.go
+++ b/src/cmd/asm/internal/asm/asm.go
@@ -570,6 +570,12 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.RegTo2 = a[2].Reg
break
}
+ if arch.IsARM64SWP(op) {
+ prog.From = a[1]
+ prog.Reg = p.getRegister(prog, op, &a[0])
+ prog.To = a[2]
+ break
+ }
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2]
diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s
index 2eeaa971f5..ec32e0ff34 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64.s
@@ -607,6 +607,16 @@ again:
STPW (R3, R4), x(SB)
STPW (R3, R4), x+8(SB)
+// SWPD/SWPW/SWPH/SWPB
+ SWPD R5, (R6), R7 // SWPD (R6), R5, R7 // c78025f8
+ SWPD R5, (RSP), R7 // SWPD (RSP), R5, R7 // e78325f8
+ SWPW R5, (R6), R7 // SWPW (R6), R5, R7 // c78025b8
+ SWPW R5, (RSP), R7 // SWPW (RSP), R5, R7 // e78325b8
+ SWPH R5, (R6), R7 // SWPH (R6), R5, R7 // c7802578
+ SWPH R5, (RSP), R7 // SWPH (RSP), R5, R7 // e7832578
+ SWPB R5, (R6), R7 // SWPB (R6), R5, R7 // c7802538
+ SWPB R5, (RSP), R7 // SWPB (RSP), R5, R7 // e7832538
+
// END
//
// LTYPEE comma
diff --git a/src/cmd/internal/obj/arm64/a.out.go b/src/cmd/internal/obj/arm64/a.out.go
index 0f03b05930..3010204109 100644
--- a/src/cmd/internal/obj/arm64/a.out.go
+++ b/src/cmd/internal/obj/arm64/a.out.go
@@ -424,6 +424,7 @@ const (
C_SBRA // for TYPE_BRANCH
C_LBRA
+ C_ZAUTO // 0(RSP)
C_NPAUTO // -512 <= x < 0, 0 mod 8
C_NSAUTO // -256 <= x < 0
C_PSAUTO_8 // 0 to 255, 0 mod 8
@@ -748,6 +749,10 @@ const (
AMOVPS
AMOVPSW
AMOVPW
+ ASWPD
+ ASWPW
+ ASWPH
+ ASWPB
ABEQ
ABNE
ABCS
diff --git a/src/cmd/internal/obj/arm64/anames.go b/src/cmd/internal/obj/arm64/anames.go
index 64348d7534..cc92d86a4a 100644
--- a/src/cmd/internal/obj/arm64/anames.go
+++ b/src/cmd/internal/obj/arm64/anames.go
@@ -257,6 +257,10 @@ var Anames = []string{
"MOVPS",
"MOVPSW",
"MOVPW",
+ "SWPD",
+ "SWPW",
+ "SWPH",
+ "SWPB",
"BEQ",
"BNE",
"BCS",
diff --git a/src/cmd/internal/obj/arm64/anames7.go b/src/cmd/internal/obj/arm64/anames7.go
index ef4f30c2d7..a0ff54024a 100644
--- a/src/cmd/internal/obj/arm64/anames7.go
+++ b/src/cmd/internal/obj/arm64/anames7.go
@@ -36,6 +36,7 @@ var cnames7 = []string{
"AECON",
"SBRA",
"LBRA",
+ "ZAUTO",
"NPAUTO",
"NSAUTO",
"PSAUTO_8",
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index b8def184de..def589faf4 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -458,6 +458,10 @@ var optab = []Optab{
{AMOVH, C_REG, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
{AMOVB, C_REG, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
+ /* SWPD/SWPW/SWPH/SWPB */
+ {ASWPD, C_ZAUTO, C_REG, C_REG, 47, 4, REGSP, 0, 0},
+ {ASWPD, C_ZOREG, C_REG, C_REG, 47, 4, 0, 0, 0},
+
/* pre/post-indexed/signed-offset load/store register pair
(unscaled, signed 10-bit quad-aligned and long offset) */
{ALDP, C_NPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
@@ -966,7 +970,8 @@ func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
case C_ADDCON:
fallthrough
- case C_PSAUTO,
+ case C_ZAUTO,
+ C_PSAUTO,
C_PSAUTO_8,
C_PSAUTO_4,
C_PPAUTO,
@@ -1200,6 +1205,10 @@ func log2(x uint64) uint32 {
}
func autoclass(l int64) int {
+ if l == 0 {
+ return C_ZAUTO
+ }
+
if l < 0 {
if l >= -256 {
return C_NSAUTO
@@ -1260,10 +1269,7 @@ func autoclass(l int64) int {
}
func oregclass(l int64) int {
- if l == 0 {
- return C_ZOREG
- }
- return autoclass(l) - C_NPAUTO + C_NPOREG
+ return autoclass(l) - C_ZAUTO + C_ZOREG
}
/*
@@ -1632,42 +1638,47 @@ func cmp(a int, b int) bool {
return true
}
+ case C_PSAUTO_8:
+ if b == C_ZAUTO {
+ return true
+ }
+
case C_PSAUTO_4:
- if b == C_PSAUTO_8 {
+ if b == C_ZAUTO || b == C_PSAUTO_8 {
return true
}
case C_PSAUTO:
- if b == C_PSAUTO_8 || b == C_PSAUTO_4 {
+ if b == C_ZAUTO || b == C_PSAUTO_8 || b == C_PSAUTO_4 {
return true
}
case C_PPAUTO:
- if b == C_PSAUTO_8 {
+ if b == C_ZAUTO || b == C_PSAUTO_8 {
return true
}
case C_UAUTO4K:
switch b {
- case C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8:
+ case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8:
return true
}
case C_UAUTO8K:
switch b {
- case C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8:
+ case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8:
return true
}
case C_UAUTO16K:
switch b {
- case C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8:
+ case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8:
return true
}
case C_UAUTO32K:
switch b {
- case C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8:
+ case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8:
return true
}
@@ -1676,7 +1687,7 @@ func cmp(a int, b int) bool {
case C_LAUTO:
switch b {
- case C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
+ case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8,
C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8,
C_UAUTO16K, C_UAUTO16K_8,
@@ -1886,6 +1897,11 @@ func buildop(ctxt *obj.Link) {
oprangeset(AMOVZ, t)
oprangeset(AMOVZW, t)
+ case ASWPD:
+ oprangeset(ASWPB, t)
+ oprangeset(ASWPH, t)
+ oprangeset(ASWPW, t)
+
case ABEQ:
oprangeset(ABNE, t)
oprangeset(ABCS, t)
@@ -3213,6 +3229,28 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= uint32(p.From.Reg&31) << 5
o1 |= uint32(p.To.Reg & 31)
+ case 47: /* SWPx Rs, (Rb), Rt: Rs -> (Rb) -> Rt */
+ v := int32(c.regoff(&p.From))
+ rb := int(p.From.Reg)
+ if v != 0 {
+ c.ctxt.Diag("invalid offset: %v\n", p)
+ }
+ rs := p.Reg
+ rt := p.To.Reg
+ switch p.As {
+ case ASWPD:
+ o1 = 3 << 30
+ case ASWPW:
+ o1 = 2 << 30
+ case ASWPH:
+ o1 = 1 << 30
+ case ASWPB:
+ o1 = 0 << 30
+ default:
+ c.ctxt.Diag("illegal instruction: %v\n", p)
+ }
+ o1 |= 0x1c1<<21 | 0x20<<10 | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
+
case 50: /* sys/sysl */
o1 = c.opirr(p, p.As)