From: Ben Shi Date: Tue, 20 Mar 2018 08:25:08 +0000 (+0000) Subject: cmd/internal/obj/arm64: support SWPD/SWPW/SWPH/SWPB X-Git-Tag: go1.11beta1~878 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e1040d79557de627b18c928a3c498e89f1dcd9da;p=gostls13.git 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 Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot --- 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)