Commit ebd4950e authored by fanzha02's avatar fanzha02 Committed by Cherry Zhang

cmd/asm: add PRFM instruction on ARM64

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: 's avatarCherry Zhang <cherryyz@google.com>
parent 0938e4cf
......@@ -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
......
......@@ -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
......
......@@ -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:
......
......@@ -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)
......
......@@ -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
......
......@@ -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)
......
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