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 {
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.
......
......@@ -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]
......
......@@ -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
......
......@@ -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
......
......@@ -257,6 +257,10 @@ var Anames = []string{
"MOVPS",
"MOVPSW",
"MOVPW",
"SWPD",
"SWPW",
"SWPH",
"SWPB",
"BEQ",
"BNE",
"BCS",
......
......@@ -36,6 +36,7 @@ var cnames7 = []string{
"AECON",
"SBRA",
"LBRA",
"ZAUTO",
"NPAUTO",
"NSAUTO",
"PSAUTO_8",
......
......@@ -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)
......
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