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>
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
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
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:
{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},
{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
AVST1,
AVDUP,
AVMOVS,
- AVMOVI:
+ AVMOVI,
+ APRFM:
break
case obj.ANOP,
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
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)
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
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)