]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm64: support SWPD/SWPW/SWPH/SWPB
authorBen Shi <powerman1st@163.com>
Tue, 20 Mar 2018 08:25:08 +0000 (08:25 +0000)
committerCherry Zhang <cherryyz@google.com>
Wed, 11 Apr 2018 16:06:01 +0000 (16:06 +0000)
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>

src/cmd/asm/internal/arch/arm64.go
src/cmd/asm/internal/asm/asm.go
src/cmd/asm/internal/asm/testdata/arm64.s
src/cmd/internal/obj/arm64/a.out.go
src/cmd/internal/obj/arm64/anames.go
src/cmd/internal/obj/arm64/anames7.go
src/cmd/internal/obj/arm64/asm7.go

index 3941e363729e3ba8eabe0d4cb8bd8dd90daefc8f..b311f4c738ff560f53b5f0814c305e5775f2391d 100644 (file)
@@ -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.
index 78ca4f554df8a4a231669dd8118a8eb2fcd89ae7..6261aa843ba903f56d5d4564ee8c2fe3543484e9 100644 (file)
@@ -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]
index 2eeaa971f512bd49ced93e0fc386c8ae222eece0..ec32e0ff34aa6699c6e2dfe2cf3cf848ae1a665c 100644 (file)
@@ -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
index 0f03b0593043f33ef87af03cc2d5d858407bb066..30102041099f3e288e38713c5485aa2d780072bc 100644 (file)
@@ -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
index 64348d75344b44864bb8236faae8e1c840c4a6e4..cc92d86a4a12a7df3e047920637f7a79cab476c8 100644 (file)
@@ -257,6 +257,10 @@ var Anames = []string{
        "MOVPS",
        "MOVPSW",
        "MOVPW",
+       "SWPD",
+       "SWPW",
+       "SWPH",
+       "SWPB",
        "BEQ",
        "BNE",
        "BCS",
index ef4f30c2d7320078e21f8f830bc01a76159e7076..a0ff54024a03cb73541b47f4ba1a32f35db413bd 100644 (file)
@@ -36,6 +36,7 @@ var cnames7 = []string{
        "AECON",
        "SBRA",
        "LBRA",
+       "ZAUTO",
        "NPAUTO",
        "NSAUTO",
        "PSAUTO_8",
index b8def184de542e0b83934ba3495de7fe6b65cf82..def589faf4f05a629c36cdefa9d24f985208f9a6 100644 (file)
@@ -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)