Commit e1040d79 authored by Ben Shi's avatar Ben Shi Committed by Cherry Zhang

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/101516Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 9446eaa9
...@@ -78,6 +78,17 @@ func IsARM64STLXR(op obj.As) bool { ...@@ -78,6 +78,17 @@ func IsARM64STLXR(op obj.As) bool {
return false 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. // ARM64Suffix handles the special suffix for the ARM64.
// It returns a boolean to indicate success; failure means // It returns a boolean to indicate success; failure means
// cond was unrecognized. // cond was unrecognized.
......
...@@ -570,6 +570,12 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { ...@@ -570,6 +570,12 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.RegTo2 = a[2].Reg prog.RegTo2 = a[2].Reg
break 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.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1]) prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2] prog.To = a[2]
......
...@@ -607,6 +607,16 @@ again: ...@@ -607,6 +607,16 @@ again:
STPW (R3, R4), x(SB) STPW (R3, R4), x(SB)
STPW (R3, R4), x+8(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 // END
// //
// LTYPEE comma // LTYPEE comma
......
...@@ -424,6 +424,7 @@ const ( ...@@ -424,6 +424,7 @@ const (
C_SBRA // for TYPE_BRANCH C_SBRA // for TYPE_BRANCH
C_LBRA C_LBRA
C_ZAUTO // 0(RSP)
C_NPAUTO // -512 <= x < 0, 0 mod 8 C_NPAUTO // -512 <= x < 0, 0 mod 8
C_NSAUTO // -256 <= x < 0 C_NSAUTO // -256 <= x < 0
C_PSAUTO_8 // 0 to 255, 0 mod 8 C_PSAUTO_8 // 0 to 255, 0 mod 8
...@@ -748,6 +749,10 @@ const ( ...@@ -748,6 +749,10 @@ const (
AMOVPS AMOVPS
AMOVPSW AMOVPSW
AMOVPW AMOVPW
ASWPD
ASWPW
ASWPH
ASWPB
ABEQ ABEQ
ABNE ABNE
ABCS ABCS
......
...@@ -257,6 +257,10 @@ var Anames = []string{ ...@@ -257,6 +257,10 @@ var Anames = []string{
"MOVPS", "MOVPS",
"MOVPSW", "MOVPSW",
"MOVPW", "MOVPW",
"SWPD",
"SWPW",
"SWPH",
"SWPB",
"BEQ", "BEQ",
"BNE", "BNE",
"BCS", "BCS",
......
...@@ -36,6 +36,7 @@ var cnames7 = []string{ ...@@ -36,6 +36,7 @@ var cnames7 = []string{
"AECON", "AECON",
"SBRA", "SBRA",
"LBRA", "LBRA",
"ZAUTO",
"NPAUTO", "NPAUTO",
"NSAUTO", "NSAUTO",
"PSAUTO_8", "PSAUTO_8",
......
...@@ -458,6 +458,10 @@ var optab = []Optab{ ...@@ -458,6 +458,10 @@ var optab = []Optab{
{AMOVH, C_REG, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, {AMOVH, C_REG, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
{AMOVB, 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 /* pre/post-indexed/signed-offset load/store register pair
(unscaled, signed 10-bit quad-aligned and long offset) */ (unscaled, signed 10-bit quad-aligned and long offset) */
{ALDP, C_NPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, {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) { ...@@ -966,7 +970,8 @@ func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
case C_ADDCON: case C_ADDCON:
fallthrough fallthrough
case C_PSAUTO, case C_ZAUTO,
C_PSAUTO,
C_PSAUTO_8, C_PSAUTO_8,
C_PSAUTO_4, C_PSAUTO_4,
C_PPAUTO, C_PPAUTO,
...@@ -1200,6 +1205,10 @@ func log2(x uint64) uint32 { ...@@ -1200,6 +1205,10 @@ func log2(x uint64) uint32 {
} }
func autoclass(l int64) int { func autoclass(l int64) int {
if l == 0 {
return C_ZAUTO
}
if l < 0 { if l < 0 {
if l >= -256 { if l >= -256 {
return C_NSAUTO return C_NSAUTO
...@@ -1260,10 +1269,7 @@ func autoclass(l int64) int { ...@@ -1260,10 +1269,7 @@ func autoclass(l int64) int {
} }
func oregclass(l int64) int { func oregclass(l int64) int {
if l == 0 { return autoclass(l) - C_ZAUTO + C_ZOREG
return C_ZOREG
}
return autoclass(l) - C_NPAUTO + C_NPOREG
} }
/* /*
...@@ -1632,42 +1638,47 @@ func cmp(a int, b int) bool { ...@@ -1632,42 +1638,47 @@ func cmp(a int, b int) bool {
return true return true
} }
case C_PSAUTO_8:
if b == C_ZAUTO {
return true
}
case C_PSAUTO_4: case C_PSAUTO_4:
if b == C_PSAUTO_8 { if b == C_ZAUTO || b == C_PSAUTO_8 {
return true return true
} }
case C_PSAUTO: 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 return true
} }
case C_PPAUTO: case C_PPAUTO:
if b == C_PSAUTO_8 { if b == C_ZAUTO || b == C_PSAUTO_8 {
return true return true
} }
case C_UAUTO4K: case C_UAUTO4K:
switch b { 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 return true
} }
case C_UAUTO8K: case C_UAUTO8K:
switch b { 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 return true
} }
case C_UAUTO16K: case C_UAUTO16K:
switch b { 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 return true
} }
case C_UAUTO32K: case C_UAUTO32K:
switch b { 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 return true
} }
...@@ -1676,7 +1687,7 @@ func cmp(a int, b int) bool { ...@@ -1676,7 +1687,7 @@ func cmp(a int, b int) bool {
case C_LAUTO: case C_LAUTO:
switch b { 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_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8,
C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8,
C_UAUTO16K, C_UAUTO16K_8, C_UAUTO16K, C_UAUTO16K_8,
...@@ -1886,6 +1897,11 @@ func buildop(ctxt *obj.Link) { ...@@ -1886,6 +1897,11 @@ func buildop(ctxt *obj.Link) {
oprangeset(AMOVZ, t) oprangeset(AMOVZ, t)
oprangeset(AMOVZW, t) oprangeset(AMOVZW, t)
case ASWPD:
oprangeset(ASWPB, t)
oprangeset(ASWPH, t)
oprangeset(ASWPW, t)
case ABEQ: case ABEQ:
oprangeset(ABNE, t) oprangeset(ABNE, t)
oprangeset(ABCS, t) oprangeset(ABCS, t)
...@@ -3213,6 +3229,28 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { ...@@ -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.From.Reg&31) << 5
o1 |= uint32(p.To.Reg & 31) 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 */ case 50: /* sys/sysl */
o1 = c.opirr(p, p.As) o1 = c.opirr(p, p.As)
......
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