]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/asm: add PRFM instruction on ARM64
authorfanzha02 <fannie.zhang@arm.com>
Thu, 30 Nov 2017 08:30:53 +0000 (08:30 +0000)
committerCherry Zhang <cherryyz@google.com>
Wed, 14 Feb 2018 17:09:52 +0000 (17:09 +0000)
The current assembler cannot handle PRFM(immediate) instruciton.
The fix creates a prfopfield struct that contains the eight
prefetch operations and the value to use in instruction. And add
the test cases.

Fixes #22932

Change-Id: I621d611bd930ef3c42306a4372447c46d53b2ccf
Reviewed-on: https://go-review.googlesource.com/81675
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/asm/internal/arch/arch.go
src/cmd/asm/internal/asm/testdata/arm64.s
src/cmd/internal/obj/arm64/a.out.go
src/cmd/internal/obj/arm64/asm7.go
src/cmd/internal/obj/arm64/doc.go
src/cmd/internal/obj/arm64/list7.go

index b4ce2fd8ae6cc1fca65d543577cd76011e5313a4..cd028f6bee60636a59fbae49b9141db6f88e93e6 100644 (file)
@@ -260,6 +260,25 @@ func archArm64() *Arch {
        register["SPSel"] = arm64.REG_SPSel
        register["DAIFSet"] = arm64.REG_DAIFSet
        register["DAIFClr"] = arm64.REG_DAIFClr
+       register["PLDL1KEEP"] = arm64.REG_PLDL1KEEP
+       register["PLDL1STRM"] = arm64.REG_PLDL1STRM
+       register["PLDL2KEEP"] = arm64.REG_PLDL2KEEP
+       register["PLDL2STRM"] = arm64.REG_PLDL2STRM
+       register["PLDL3KEEP"] = arm64.REG_PLDL3KEEP
+       register["PLDL3STRM"] = arm64.REG_PLDL3STRM
+       register["PLIL1KEEP"] = arm64.REG_PLIL1KEEP
+       register["PLIL1STRM"] = arm64.REG_PLIL1STRM
+       register["PLIL2KEEP"] = arm64.REG_PLIL2KEEP
+       register["PLIL2STRM"] = arm64.REG_PLIL2STRM
+       register["PLIL3KEEP"] = arm64.REG_PLIL3KEEP
+       register["PLIL3STRM"] = arm64.REG_PLIL3STRM
+       register["PSTL1KEEP"] = arm64.REG_PSTL1KEEP
+       register["PSTL1STRM"] = arm64.REG_PSTL1STRM
+       register["PSTL2KEEP"] = arm64.REG_PSTL2KEEP
+       register["PSTL2STRM"] = arm64.REG_PSTL2STRM
+       register["PSTL3KEEP"] = arm64.REG_PSTL3KEEP
+       register["PSTL3STRM"] = arm64.REG_PSTL3STRM
+
        // Conditional operators, like EQ, NE, etc.
        register["EQ"] = arm64.COND_EQ
        register["NE"] = arm64.COND_NE
index cb563bb9961d92914a1c47724cada58c8cdc0234..18527037b30b745d14a14002268d30f5b8cdb50a 100644 (file)
@@ -135,6 +135,12 @@ TEXT       foo(SB), DUPOK|NOSPLIT, $-8
        VMOVS   (R0), V20                                       // 140040bd
        VMOVS.P 8(R0), V20                                      // 148440bc
        VMOVS.W 8(R0), V20                                      // 148c40bc
+       PRFM    (R2), PLDL1KEEP                                 // 400080f9
+       PRFM    16(R2), PLDL1KEEP                               // 400880f9
+       PRFM    48(R6), PSTL2STRM                               // d31880f9
+       PRFM    8(R12), PLIL3STRM                               // 8d0580f9
+       PRFM    (R8), $25                                       // 190180f9
+       PRFM    8(R9), $30                                      // 3e0580f9
 
        // small offset fits into instructions
        MOVB    1(R1), R2 // 22048039
index 6087b74acfd5818e2d19044564cbf7e6733975b2..e8be3cd4a3f6539972c4501bf55f346b83c96a43 100644 (file)
@@ -208,6 +208,24 @@ const (
        REG_SPSel
        REG_DAIFSet
        REG_DAIFClr
+       REG_PLDL1KEEP
+       REG_PLDL1STRM
+       REG_PLDL2KEEP
+       REG_PLDL2STRM
+       REG_PLDL3KEEP
+       REG_PLDL3STRM
+       REG_PLIL1KEEP
+       REG_PLIL1STRM
+       REG_PLIL2KEEP
+       REG_PLIL2STRM
+       REG_PLIL3KEEP
+       REG_PLIL3STRM
+       REG_PSTL1KEEP
+       REG_PSTL1STRM
+       REG_PSTL2KEEP
+       REG_PSTL2STRM
+       REG_PSTL3KEEP
+       REG_PSTL3STRM
 )
 
 // Register assignments:
index ca81238c93e93fe81f154bfb1011253a5184d771..362fd9367d4b06645b51bb14d896192d2f95459f 100644 (file)
@@ -305,6 +305,8 @@ var optab = []Optab{
        {ACSEL, C_COND, C_REG, C_REG, 18, 4, 0, 0, 0}, /* from3 optional */
        {ACSET, C_COND, C_NONE, C_REG, 18, 4, 0, 0, 0},
        {ACCMN, C_COND, C_REG, C_VCON, 19, 4, 0, 0, 0}, /* from3 either C_REG or C_VCON */
+       {APRFM, C_UOREG32K, C_NONE, C_SPR, 91, 4, 0, 0, 0},
+       {APRFM, C_UOREG32K, C_NONE, C_LCON, 91, 4, 0, 0, 0},
 
        /* scaled 12-bit unsigned displacement store */
        {AMOVB, C_REG, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
@@ -628,6 +630,30 @@ var systemreg = []struct {
        {REG_ELR_EL1, 8<<16 | 4<<12 | 1<<5},
 }
 
+var prfopfield = []struct {
+       reg int16
+       enc uint32
+}{
+       {REG_PLDL1KEEP, 0},
+       {REG_PLDL1STRM, 1},
+       {REG_PLDL2KEEP, 2},
+       {REG_PLDL2STRM, 3},
+       {REG_PLDL3KEEP, 4},
+       {REG_PLDL3STRM, 5},
+       {REG_PLIL1KEEP, 8},
+       {REG_PLIL1STRM, 9},
+       {REG_PLIL2KEEP, 10},
+       {REG_PLIL2STRM, 11},
+       {REG_PLIL3KEEP, 12},
+       {REG_PLIL3STRM, 13},
+       {REG_PSTL1KEEP, 16},
+       {REG_PSTL1STRM, 17},
+       {REG_PSTL2KEEP, 18},
+       {REG_PSTL2STRM, 19},
+       {REG_PSTL3KEEP, 20},
+       {REG_PSTL3STRM, 21},
+}
+
 func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
        p := cursym.Func.Text
        if p == nil || p.Link == nil { // handle external functions and ELF section symbols
@@ -2106,7 +2132,8 @@ func buildop(ctxt *obj.Link) {
                        AVST1,
                        AVDUP,
                        AVMOVS,
-                       AVMOVI:
+                       AVMOVI,
+                       APRFM:
                        break
 
                case obj.ANOP,
@@ -3731,8 +3758,32 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
                o1 = 0xbea71700
 
                break
-       }
 
+       case 91: /* prfm imm(Rn), <prfop | $imm5> */
+               imm := uint32(p.From.Offset)
+               r := p.From.Reg
+               v := uint32(0xff)
+               if p.To.Type == obj.TYPE_CONST {
+                       v = uint32(p.To.Offset)
+                       if v > 31 {
+                               c.ctxt.Diag("illegal prefetch operation\n%v", p)
+                       }
+               } else {
+                       for i := 0; i < len(prfopfield); i++ {
+                               if prfopfield[i].reg == p.To.Reg {
+                                       v = prfopfield[i].enc
+                                       break
+                               }
+                       }
+                       if v == 0xff {
+                               c.ctxt.Diag("illegal prefetch operation:\n%v", p)
+                       }
+               }
+
+               o1 = c.opldrpp(p, p.As)
+               o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
+
+       }
        out[0] = o1
        out[1] = o2
        out[2] = o3
@@ -4993,6 +5044,10 @@ func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 {
 
        case AVMOVS:
                return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
+
+       case APRFM:
+               return 0xf9<<24 | 2<<22
+
        }
 
        c.ctxt.Diag("bad opldr %v\n%v", a, p)
index f75f49fb9c42c105544b99efb94c6e64a9e59db0..d3d43b1f4273522b8e914be57adf078435057007 100644 (file)
@@ -10,6 +10,14 @@ Go Assembly for ARM64 Reference Manual
 
 1. Alphabetical list of basic instructions
     // TODO
+    PRFM: Prefetch Memory (immediate)
+     PRFM      imm(Rn), <prfop>
+      prfop is the prefetch operation and can have the following values:
+      PLDL1KEEP, PLDL1STRM, PLDL2KEEP, PLDL2STRM, PLDL3KEEP, PLDL3STRM,
+      PLIL1KEEP, PLIL1STRM, PLIL2KEEP, PLIL2STRM, PLIL3KEEP, PLIL3STRM,
+      PSTL1KEEP, PSTL1STRM, PSTL2KEEP, PSTL2STRM, PSTL3KEEP, PSTL3STRM.
+     PRFM      imm(Rn), $imm
+      $imm prefetch operation is encoded as an immediate.
 
 2. Alphabetical list of float-point instructions
     // TODO
index 9a9f4b45b7787303342ec59059ff811279738c4c..cf92120cbb384af8cc6462dc1628b7c632be5956 100644 (file)
@@ -134,6 +134,42 @@ func rconv(r int) string {
                return "DAIFSet"
        case r == REG_DAIFClr:
                return "DAIFClr"
+       case r == REG_PLDL1KEEP:
+               return "PLDL1KEEP"
+       case r == REG_PLDL1STRM:
+               return "PLDL1STRM"
+       case r == REG_PLDL2KEEP:
+               return "PLDL2KEEP"
+       case r == REG_PLDL2STRM:
+               return "PLDL2STRM"
+       case r == REG_PLDL3KEEP:
+               return "PLDL3KEEP"
+       case r == REG_PLDL3STRM:
+               return "PLDL3STRM"
+       case r == REG_PLIL1KEEP:
+               return "PLIL1KEEP"
+       case r == REG_PLIL1STRM:
+               return "PLIL1STRM"
+       case r == REG_PLIL2KEEP:
+               return "PLIL2KEEP"
+       case r == REG_PLIL2STRM:
+               return "PLIL2STRM"
+       case r == REG_PLIL3KEEP:
+               return "PLIL3KEEP"
+       case r == REG_PLIL3STRM:
+               return "PLIL3STRM"
+       case r == REG_PSTL1KEEP:
+               return "PSTL1KEEP"
+       case r == REG_PSTL1STRM:
+               return "PSTL1STRM"
+       case r == REG_PSTL2KEEP:
+               return "PSTL2KEEP"
+       case r == REG_PSTL2STRM:
+               return "PSTL2STRM"
+       case r == REG_PSTL3KEEP:
+               return "PSTL3KEEP"
+       case r == REG_PSTL3STRM:
+               return "PSTL3STRM"
        case REG_UXTB <= r && r < REG_UXTH:
                if (r>>5)&7 != 0 {
                        return fmt.Sprintf("R%d.UXTB<<%d", r&31, (r>>5)&7)