2327 lines
110 KiB
Go
2327 lines
110 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
// This file carries the extended-instruction layer: instructions the Go
|
|
// toolchain does not know at all, described as data and validated against
|
|
// golden vectors from the Arm Architecture Reference Manual rather than
|
|
// against the toolchain. It sits beside the generated tables, never inside
|
|
// them: arch/arm64_gen.go stays untouched, and Extensions returns the layer
|
|
// per architecture; the amd64 side of the layer lives in amd64_ext.go and
|
|
// attaches through the same door.
|
|
//
|
|
// The first entries are the arm64 SVE and SVE2 integer add/subtract/multiply
|
|
// family (twenty-three forms over four word shapes) and the SVE and SVE2.1
|
|
// predicate family (logical operations, breaks, permutations, tests, the
|
|
// first-fault register group and the while compares). The encodings are
|
|
// transcribed from the manual and cross-checked against the Go toolchain's
|
|
// generated encoding table and corpus; the golden vectors in
|
|
// arm64_ext_test.go pin the bytes.
|
|
|
|
package arch
|
|
|
|
import "fmt"
|
|
|
|
// ExtOperandKind classifies one operand of an extended instruction.
|
|
type ExtOperandKind uint8
|
|
|
|
// Operand kinds.
|
|
const (
|
|
ExtZReg ExtOperandKind = iota // scalable vector register Z0-Z31
|
|
ExtPReg // predicate register P0-P15
|
|
ExtImm // immediate
|
|
// The amd64 layer's register kinds.
|
|
ExtXMM // 128-bit vector register XMM0-XMM31
|
|
ExtYMM // 256-bit vector register YMM0-YMM31
|
|
ExtZMM // 512-bit vector register ZMM0-ZMM31
|
|
ExtKReg // opmask register K0-K7
|
|
ExtR32 // 32-bit general register EAX-R15D
|
|
ExtR64 // 64-bit general register RAX-R15
|
|
ExtMem // base-relative memory operand, 4660(R8) style
|
|
// The arm64 layer's general and counter registers.
|
|
ExtGReg // general register R0-R30
|
|
ExtPNReg // predicate-as-counter register PN8-PN15
|
|
)
|
|
|
|
// String returns a short label for the kind.
|
|
func (k ExtOperandKind) String() string {
|
|
switch k {
|
|
case ExtZReg:
|
|
return "scalable vector register"
|
|
case ExtPReg:
|
|
return "predicate register"
|
|
case ExtImm:
|
|
return "immediate"
|
|
case ExtXMM:
|
|
return "XMM register"
|
|
case ExtYMM:
|
|
return "YMM register"
|
|
case ExtZMM:
|
|
return "ZMM register"
|
|
case ExtKReg:
|
|
return "opmask register"
|
|
case ExtR32:
|
|
return "32-bit general register"
|
|
case ExtR64:
|
|
return "64-bit general register"
|
|
case ExtMem:
|
|
return "memory operand"
|
|
case ExtGReg:
|
|
return "general register"
|
|
case ExtPNReg:
|
|
return "predicate-as-counter register"
|
|
default:
|
|
return "operand"
|
|
}
|
|
}
|
|
|
|
// ExtArrangement is the element-size suffix a scalable vector operand
|
|
// carries: .B, .H, .S, .D or .Q. ExtArrNone means the operand is written
|
|
// bare, which the SVE forms in this layer reject.
|
|
type ExtArrangement uint8
|
|
|
|
// Arrangements, widest last.
|
|
const (
|
|
ExtArrNone ExtArrangement = iota
|
|
ExtArrB // 8-bit elements
|
|
ExtArrH // 16-bit elements
|
|
ExtArrS // 32-bit elements
|
|
ExtArrD // 64-bit elements
|
|
ExtArrQ // 128-bit elements
|
|
)
|
|
|
|
// String returns the assembler suffix, with the leading dot.
|
|
func (a ExtArrangement) String() string {
|
|
switch a {
|
|
case ExtArrB:
|
|
return ".B"
|
|
case ExtArrH:
|
|
return ".H"
|
|
case ExtArrS:
|
|
return ".S"
|
|
case ExtArrD:
|
|
return ".D"
|
|
case ExtArrQ:
|
|
return ".Q"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
// Width returns the byte width of one element under the arrangement.
|
|
func (a ExtArrangement) Width() int {
|
|
switch a {
|
|
case ExtArrB:
|
|
return 1
|
|
case ExtArrH:
|
|
return 2
|
|
case ExtArrS:
|
|
return 4
|
|
case ExtArrD:
|
|
return 8
|
|
case ExtArrQ:
|
|
return 16
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// sizeBits maps the arrangement onto the two-bit size field the integer SVE
|
|
// classes carry at bits 23..22: 00=B, 01=H, 10=S, 11=D. ok is false for the
|
|
// arrangements no such class accepts (.Q and the bare spelling).
|
|
func (a ExtArrangement) sizeBits() (uint32, bool) {
|
|
switch a {
|
|
case ExtArrB, ExtArrH, ExtArrS, ExtArrD:
|
|
return uint32(a) - 1, true
|
|
default:
|
|
return 0, false
|
|
}
|
|
}
|
|
|
|
// ExtQualifier is the predicate qualifier spelled after the slash.
|
|
type ExtQualifier uint8
|
|
|
|
// Predicate qualifiers.
|
|
const (
|
|
ExtQualNone ExtQualifier = iota // bare Pn (non-predicating position)
|
|
ExtQualMerging // /M, inactive lanes keep the destination
|
|
ExtQualZeroing // /Z, inactive lanes become zero
|
|
ExtQualAny // metadata only: the row takes /M or /Z
|
|
)
|
|
|
|
// String returns the assembler spelling, with the leading slash.
|
|
func (q ExtQualifier) String() string {
|
|
switch q {
|
|
case ExtQualMerging:
|
|
return "/M"
|
|
case ExtQualZeroing:
|
|
return "/Z"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
// ExtOperand is one operand of an extended instruction, already resolved to
|
|
// its pieces: a register with its arrangement and qualifier, or an immediate
|
|
// with its optional left shift. The assembler's future hook constructs these
|
|
// from the parsed statement; Encode consumes them.
|
|
type ExtOperand struct {
|
|
Kind ExtOperandKind
|
|
// Reg is the register number (Z: 0..31, P: 0..15, R: 0..30, PN: 8..15);
|
|
// under ExtMem it is the base general register, 0..15.
|
|
Reg int
|
|
Arr ExtArrangement // element-size suffix; ExtArrNone when bare
|
|
Qual ExtQualifier // predicate qualifier; ExtQualNone elsewhere
|
|
// Imm is the immediate value under ExtImm; under ExtMem it is the
|
|
// signed displacement the base carries.
|
|
Imm int64
|
|
// Shift carries the LSL amount an immediate form shifts the constant by
|
|
// before use (0 or 8 in the SVE add/subtract immediate class). HasShift
|
|
// separates a spelled shift (validated as written) from an unshifted
|
|
// operand (the encoder may derive the sh bit from the value).
|
|
Shift int
|
|
HasShift bool
|
|
// Broadcast spells the {1toN} broadcast on an amd64 memory operand: the
|
|
// base-relative location holds one element the hardware splats across
|
|
// every lane of the destination, which the encoder lays down as EVEX.b.
|
|
// Only the memory positions of the entries that carry Bcast accept it.
|
|
Broadcast bool
|
|
// Index and Scale spell the scaled index of an amd64 memory operand,
|
|
// the SIB byte's shape: base plus index times scale. Scale carries the
|
|
// byte multiplier 1, 2, 4 or 8, and HasIndex separates a spelled index
|
|
// from the plain base-plus-displacement operand. The index is a
|
|
// general register 0..15, and RSP is no index.
|
|
Index int
|
|
Scale int
|
|
HasIndex bool
|
|
// Mask spells the write mask of an amd64 EVEX destination, the {k1}
|
|
// through {k7} decorations: only the masked lanes take the result.
|
|
// HasMask separates a spelled mask from the unmasked destination, and
|
|
// K0 never masks, so the register runs 1..7. Only the packed
|
|
// destinations of the entries that carry Mask accept it.
|
|
Mask int
|
|
HasMask bool
|
|
// Zeroing spells the {z} decoration beside a write mask: the inactive
|
|
// lanes become zero instead of keeping the destination. It is valid
|
|
// only together with a spelled mask.
|
|
Zeroing bool
|
|
}
|
|
|
|
// ExtVector builds a scalable vector operand, ADD Z1.S style.
|
|
func ExtVector(reg int, arr ExtArrangement) ExtOperand {
|
|
return ExtOperand{Kind: ExtZReg, Reg: reg, Arr: arr}
|
|
}
|
|
|
|
// ExtPredicate builds a predicate operand with its qualifier, P0/M style.
|
|
func ExtPredicate(reg int, qual ExtQualifier) ExtOperand {
|
|
return ExtOperand{Kind: ExtPReg, Reg: reg, Qual: qual}
|
|
}
|
|
|
|
// ExtPredicateSized builds a predicate operand carrying an element-size
|
|
// suffix, P4.B style.
|
|
func ExtPredicateSized(reg int, arr ExtArrangement) ExtOperand {
|
|
return ExtOperand{Kind: ExtPReg, Reg: reg, Arr: arr}
|
|
}
|
|
|
|
// ExtCounterPredicate builds a predicate-as-counter operand, PN14.S style.
|
|
// The counter spellings run PN8-PN15, the convention the toolchain's
|
|
// generated table and corpus use for the three-bit counter field.
|
|
func ExtCounterPredicate(reg int, arr ExtArrangement) ExtOperand {
|
|
return ExtOperand{Kind: ExtPNReg, Reg: reg, Arr: arr}
|
|
}
|
|
|
|
// ExtGeneral builds a general register operand, R2 style.
|
|
func ExtGeneral(reg int) ExtOperand {
|
|
return ExtOperand{Kind: ExtGReg, Reg: reg}
|
|
}
|
|
|
|
// ExtImmediate builds an unshifted immediate operand.
|
|
func ExtImmediate(v int64) ExtOperand {
|
|
return ExtOperand{Kind: ExtImm, Imm: v}
|
|
}
|
|
|
|
// ExtShiftedImmediate builds an immediate operand with a spelled LSL amount.
|
|
func ExtShiftedImmediate(v int64, shift int) ExtOperand {
|
|
return ExtOperand{Kind: ExtImm, Imm: v, Shift: shift, HasShift: true}
|
|
}
|
|
|
|
// ExtMemory builds a base-relative memory operand, 4660(R8) style: the base
|
|
// is a 64-bit general register number, 0..15, and the displacement rides the
|
|
// ModR/M disp8 or disp32 form the encoder picks. No index register and no
|
|
// scale: the base-plus-displacement shape alone.
|
|
func ExtMemory(base int, disp int64) ExtOperand {
|
|
return ExtOperand{Kind: ExtMem, Reg: base, Imm: disp}
|
|
}
|
|
|
|
// ExtBroadcast builds the {1toN} broadcast spelling of a base-relative memory
|
|
// operand, the amd64 packed forms' m16bcst shape: the base is a 64-bit general
|
|
// register number, 0..15, the displacement keeps the plain ModR/M semantics,
|
|
// and the encoder sets EVEX.b so the single element splats across the lanes.
|
|
func ExtBroadcast(base int, disp int64) ExtOperand {
|
|
return ExtOperand{Kind: ExtMem, Reg: base, Imm: disp, Broadcast: true}
|
|
}
|
|
|
|
// ExtScaledMemory builds the base-plus-scaled-index memory operand, the amd64
|
|
// SIB shape: the base and the index are 64-bit general register numbers,
|
|
// 0..15, the scale is the byte multiplier 1, 2, 4 or 8, and the displacement
|
|
// keeps the plain ModR/M disp8 or disp32 semantics.
|
|
func ExtScaledMemory(base, index, scale int, disp int64) ExtOperand {
|
|
return ExtOperand{Kind: ExtMem, Reg: base, Imm: disp, Index: index, Scale: scale, HasIndex: true}
|
|
}
|
|
|
|
// ExtField is one named field of the 32-bit encoding word: a bit offset from
|
|
// the least significant end and the field's width.
|
|
type ExtField struct {
|
|
Off uint8
|
|
Width uint8
|
|
}
|
|
|
|
// extMask returns the field's bits as a mask.
|
|
func extMask(f ExtField) uint32 {
|
|
return ^uint32(0) >> (32 - f.Width)
|
|
}
|
|
|
|
// extSet ORs v into the field of word.
|
|
func extSet(word uint32, f ExtField, v uint32) uint32 {
|
|
return word | (v&extMask(f))<<f.Off
|
|
}
|
|
|
|
// The fields the SVE integer classes use. The 5-bit register fields are
|
|
// named after their role in the three-vector class; the predicated class
|
|
// reuses extFieldRn for its Zm operand and extFieldPg for the governing
|
|
// predicate, which that class narrows to three bits (P0-P7).
|
|
//
|
|
// The predicate classes place their operands in the same neighbourhood:
|
|
// Pd in a four-bit field at bit 0, the governing predicate either narrow
|
|
// (three bits, P0-P7) or wide (four bits, P0-P15) at bit 10, the first
|
|
// source predicate in the five-bit slot at bit 5, and Pm in a three-bit
|
|
// field at bit 16. The general registers of the while-compare class use
|
|
// the five-bit Rm slot at bit 16.
|
|
var (
|
|
extFieldRd = ExtField{0, 5} // destination (Zd or Zdn)
|
|
extFieldRn = ExtField{5, 5} // first source (Zn, or Zm in the predicated class)
|
|
extFieldRm = ExtField{16, 5} // second source (Zm in the three-vector class)
|
|
extFieldPg = ExtField{10, 3} // governing predicate P0-P7 (predicated class)
|
|
extFieldImm8 = ExtField{5, 8} // the immediate, bits 12..5
|
|
extFieldSh = ExtField{13, 1} // the shift flag: 1 means LSL #8
|
|
extSizeBHSD = ExtField{22, 2} // element-size field of every class here, bits 23..22
|
|
extFieldPd = ExtField{0, 4} // predicate destination P0-P15
|
|
extFieldPn = ExtField{5, 5} // predicate source slot P0-P15 (bit 4 unused here)
|
|
extFieldPgN = ExtField{10, 3} // narrow governing predicate P0-P7
|
|
extFieldPgW = ExtField{10, 4} // wide governing predicate P0-P15
|
|
extFieldPm = ExtField{16, 3} // predicate source P0-P7
|
|
extFieldPnc = ExtField{0, 3} // predicate-as-counter destination PN8-PN15, field holds reg-8
|
|
)
|
|
|
|
// ExtForm enumerates the operand shapes the extension layer defines, in Plan
|
|
// 9 order (sources first, destination last). A destructive SVE operand is
|
|
// written once, in destination position: the encoding carries no second copy.
|
|
type ExtForm uint8
|
|
|
|
// Operand shapes.
|
|
const (
|
|
// ExtFormVectors is the unpredicated three-vector form, the SVE integer
|
|
// add/subtract (unpredicated) class: ADD Z0.S, Z1.S, Z2.S computes
|
|
// Z0 = Z1 + Z2. Operands: Zn, Zm, Zd.
|
|
ExtFormVectors ExtForm = iota
|
|
// ExtFormPredicated is the governed destructive form, the SVE integer
|
|
// add/subtract vectors (predicated) class: ADD Z1.S, P0/M, Z0.S computes
|
|
// Z0 = Z0 + Z1 for the active lanes. Operands: Zm, Pg/M, Zdn. The
|
|
// governing predicate is a 3-bit field, so only P0-P7 encode here, and
|
|
// the class takes the merging qualifier alone: a zeroing form would need
|
|
// a MOVPRFX expansion, which one data word cannot carry.
|
|
ExtFormPredicated
|
|
// ExtFormImmediate is the add/subtract immediate form, the SVE integer
|
|
// add/subtract (immediate) class: ADD $255, Z0.S computes
|
|
// Z0 = Z0 + 255. Operands: imm{, LSL #8}, Zdn. The constant is an
|
|
// unsigned imm8, optionally shifted left by 8 bits; a bare multiple of
|
|
// 256 (up to 65280) derives the shift, the spelling the GNU assembler
|
|
// canonicalises too. .B takes no shift.
|
|
ExtFormImmediate
|
|
// ExtFormSignedImmediate is the signed immediate form of the SVE integer
|
|
// multiply (immediate) class: MUL $-128, Z0.B computes Z0 = Z0 * -128.
|
|
// Operands: simm8, Zdn. No shift exists in this class.
|
|
ExtFormSignedImmediate
|
|
// The amd64 layer's operand shapes, sources first, destination last.
|
|
// The vector register class an entry takes comes from the encoding
|
|
// template (the L'L field names it), not from the form.
|
|
// ExtFormAmdVec3 is the EVEX non-destructive three-vector form:
|
|
// VCVTNE2PS2BF16 Z6, Z5, Z4. Operands: src1, src2, dest.
|
|
ExtFormAmdVec3
|
|
// ExtFormAmdVec2 is the two-vector form: VPOPCNTD Z1, Z2, VCOMISH X1, X2.
|
|
// Operands: src, dest.
|
|
ExtFormAmdVec2
|
|
// ExtFormAmdVec2Half is the two-vector form whose destination is the
|
|
// half-width companion of the source, equal at 128 bits: VCVTNEPS2BF16
|
|
// Y6, Z5. Operands: src, dest.
|
|
ExtFormAmdVec2Half
|
|
// ExtFormAmdMask2 is the form with an opmask destination and two vector
|
|
// sources: VP2INTERSECTD K0, Z2, Z1. Operands: src1, src2, dest.
|
|
ExtFormAmdMask2
|
|
// ExtFormAmdVecGprVec is the three-operand conversion with a
|
|
// general-register source: VCVTSI2SH X1, X2, EAX. Operands: src1, gpr,
|
|
// dest.
|
|
ExtFormAmdVecGprVec
|
|
// ExtFormAmdGprVec is the two-operand form with a general-register
|
|
// source and a vector destination: VMOVW X1, EAX. Operands: gpr, dest.
|
|
ExtFormAmdGprVec
|
|
// ExtFormAmdVecGpr is the two-operand form with a vector source and a
|
|
// general-register destination: VMOVW EAX, X1 and VCVTSH2SI EAX, X1.
|
|
// Operands: src, dest.
|
|
ExtFormAmdVecGpr
|
|
// ExtFormAmdVec3Imm is the three-vector form with a control immediate,
|
|
// VGETMANTSH $11, X28, X29, X30 style: the immediate leads, the order
|
|
// the reference listings write it in. Operands: imm, src1, src2, dest.
|
|
// The immediate's layout is named by the entry's Imm8 kind.
|
|
ExtFormAmdVec3Imm
|
|
// ExtFormAmdMask2Imm is the opmask-destination form with a control
|
|
// immediate: VCMPSH $7, X28, X29, K5. Operands: imm, src1, src2, dest,
|
|
// where dest is an opmask register and the immediate's layout is named
|
|
// by the entry's Imm8 kind.
|
|
ExtFormAmdMask2Imm
|
|
// ExtFormAmdMemVec is the memory-load form: VMOVSH X30, 4660(R8) shape,
|
|
// the manual's xmm1, m16 lines that stand beside the register form.
|
|
// Operands: mem, dest.
|
|
ExtFormAmdMemVec
|
|
// ExtFormAmdVecMem is the memory-store form: VMOVSH 4660(R9), X29
|
|
// shape, the manual's m16, xmm1 lines. Operands: src, mem.
|
|
ExtFormAmdVecMem
|
|
// ExtFormPredicateLogical is the predicate logical-operation form of the
|
|
// SVE2.1 predicate classes: PAND P4.B, P2.B, P1.Z, P14.B computes
|
|
// P14 = P4 AND P2 over the active lanes of P1. Operands: Pm.B, Pn.B,
|
|
// Pg/Z, Pd.B. The zeroing qualifier on the governing predicate is part
|
|
// of the spelling; every arrangement is .B and the class carries no size
|
|
// field.
|
|
ExtFormPredicateLogical
|
|
// ExtFormPredicateSelect is PSEL's form, PSEL P4.B, P2.B, P1, P14.B:
|
|
// the governing predicate arrives bare, without a qualifier. Otherwise
|
|
// identical to ExtFormPredicateLogical.
|
|
ExtFormPredicateSelect
|
|
// ExtFormPredicateLogicalDest is the break form whose first operand is
|
|
// the destination read back: PBRKN P4.B, P2.B, P1.Z, P4.B. Operands:
|
|
// Pdm.B, Pn.B, Pg/Z, Pdm.B, with operand 1 required to equal operand 4;
|
|
// the encoding carries the register once.
|
|
ExtFormPredicateLogicalDest
|
|
// ExtFormPredicateBreak is the three-operand break form, PBRKA P5.B,
|
|
// P9.Z, P2.B. Operands: Pn.B, Pg/Z or Pg/M (both spellings encode the
|
|
// one word the manual gives), Pd.B. The governing predicate is the wide
|
|
// four-bit field, P0-P15.
|
|
ExtFormPredicateBreak
|
|
// ExtFormPredicateBreakZero is ExtFormPredicateBreak with the zeroing
|
|
// qualifier alone, PBRKAS P5.B, P9.Z, P4.B.
|
|
ExtFormPredicateBreakZero
|
|
// ExtFormPredicatePermute is the predicate permutation form, PTRN1 P5.D,
|
|
// P4.D, P2.D. Operands: Pm.T, Pn.T, Pd.T under one shared arrangement
|
|
// (.B, .H, .S or .D), which feeds the size field.
|
|
ExtFormPredicatePermute
|
|
// ExtFormPredicateFirst is PFIRST's form, PPFIRST P5.B, P9, P5.B, with
|
|
// the destination read back like ExtFormPredicateLogicalDest. Operands:
|
|
// Pdn.B, Pg (bare), Pdn.B.
|
|
ExtFormPredicateFirst
|
|
// ExtFormPredicateNext is PNEXT's form, PPNEXT P5.D, P4, P5.D, the
|
|
// destination-read-back shape with an arrangement and a size field.
|
|
// Operands: Pdn.T, Pv (bare), Pdn.T.
|
|
ExtFormPredicateNext
|
|
// ExtFormPredicateOne writes or reads a single predicate, PPFALSE P13.B
|
|
// or the unpredicated RDFFR P13.B. Operands: Pd.B.
|
|
ExtFormPredicateOne
|
|
// ExtFormPredicateWrite is WRFFR's single-source form, PWRFFR P13.B: the
|
|
// one predicate sits in the source slot, not the destination.
|
|
// Operands: Pn.B.
|
|
ExtFormPredicateWrite
|
|
// ExtFormPredicateFFRRead is the predicated first-fault read, PRDFFR
|
|
// P14.Z, P0.B. Operands: Pg/Z, Pd.B; the governing predicate is the
|
|
// wide four-bit field.
|
|
ExtFormPredicateFFRRead
|
|
// ExtFormPredicateMove is the predicate reverse, PREV P14.S, P13.S.
|
|
// Operands: Pn.T, Pd.T under one shared arrangement.
|
|
ExtFormPredicateMove
|
|
// ExtFormPredicateUnpack is the predicate unpack, PPUNPKHI P14.B, P0.H:
|
|
// the arrangements are fixed by the class (.B source, .H destination)
|
|
// and carry no size field. Operands: Pn.B, Pd.H.
|
|
ExtFormPredicateUnpack
|
|
// ExtFormPredicateTest is PTEST, PPTEST P14.B, P0, which sets the flags
|
|
// and takes no destination. Operands: Pn.B, Pg (bare).
|
|
ExtFormPredicateTest
|
|
// ExtFormWhile is the while-compare form, PWHILELT R2, R10, P10.H:
|
|
// P10 counts the lanes where the signed comparison holds. Operands:
|
|
// Rm (R0-R30), Rn (R0-R30), Pd.T, the arrangement feeding the size
|
|
// field.
|
|
ExtFormWhile
|
|
// ExtFormPredicateCounter is PTRUE's counter-register form, PPTRUE
|
|
// PN14.S: the destination is a predicate-as-counter register, spelled
|
|
// PN8-PN15 and encoded as reg-8 in the three-bit field. Operands:
|
|
// PNd.T.
|
|
ExtFormPredicateCounter
|
|
// ExtFormNone takes no operands at all, SETFFR.
|
|
ExtFormNone
|
|
// ExtFormZUnary is the SVE2.1 Z-alias unary predicated form, ZABS Z7.D,
|
|
// P4.M, Z13.D. Operands: Zn.T, Pg/M or Pg/Z (the row's PgQual says
|
|
// which), Zd.T, one shared arrangement feeding the size field, or the
|
|
// row's fixed arrangement where the class locks one (.Q, .D). Fields:
|
|
// Zn in the source slot, Pg narrow, Zd in the destination.
|
|
ExtFormZUnary
|
|
// ExtFormZPredicatedSource is the Z-alias binary predicated form,
|
|
// ZADD Z15.B, Z0.B, P3.M, Z0.B: the destination's source copy is
|
|
// spelled and must equal the destination. Operands: Zm.T, Zdn.T,
|
|
// Pg/M, Zdn.T. Fields: Zm in the second-source slot, Zdn in the
|
|
// first-source slot, Pg narrow, Zdn in the destination.
|
|
ExtFormZPredicatedSource
|
|
// ExtFormZImmediateSource is the Z-alias immediate form, ZADD $6,
|
|
// Z7.D, Z7.D: the destination's source copy is spelled and must equal
|
|
// the destination, the register encoding carried once. Operands:
|
|
// imm{, LSL #8}, Zdn.T, Zdn.T.
|
|
ExtFormZImmediateSource
|
|
// ExtFormZSelect is the vector select, ZSEL Z23.B, Z21.B, P14, Z2.B.
|
|
// Operands: Zm.T, Zn.T, Pv (bare), Zd.T, one shared arrangement.
|
|
ExtFormZSelect
|
|
// ExtFormZGov is the governed compact/expand, ZCOMPACT Z7.D, P4,
|
|
// Z13.D. Operands: Zn.T, Pg (bare), Zd.T, one shared arrangement.
|
|
ExtFormZGov
|
|
// ExtFormZMove is the vector reverse, ZREV Z1.S, Z26.S. Operands:
|
|
// Zn.T, Zd.T, one shared arrangement.
|
|
ExtFormZMove
|
|
// ExtFormZMoveBare is MOVPRFX's arrangement-less spelling, ZMOVPRFX
|
|
// Z11, Z6. Operands: Zn, Zd, no suffixes at all.
|
|
ExtFormZMoveBare
|
|
// ExtFormZUnpack is the vector unpack, ZSUNPKHI Z15.B, Z0.H: the
|
|
// source is locked to .B, the destination's arrangement feeds the size
|
|
// field. Operands: Zn.B, Zd.T.
|
|
ExtFormZUnpack
|
|
// ExtFormZFromGeneral copies a general register into a vector,
|
|
// ZDUP R2, Z10.D and ZINSR R2, Z10.D: the class locks the arrangement
|
|
// into the word, so the row's Arr is validated and nothing is encoded
|
|
// from it. Operands: R (R0-R30), Zd.T.
|
|
ExtFormZFromGeneral
|
|
// ExtFormVectorsZm is the unpredicated three-vector form whose
|
|
// spelled order starts with the second source: ZADD Z7.D, Z23.D, Z13.D
|
|
// spells Zm first, where the SVE1-era spellings spell Zn first. The
|
|
// fields are the standard three-vector slots; only the operand order
|
|
// differs. Rows with a fixed arrangement (the .D logical aliases, the
|
|
// .Q permutations) validate it and write no size field.
|
|
ExtFormVectorsZm
|
|
// ExtFormZLastReg is the last-active-element to register,
|
|
// ZLASTA Z10.D, P3, R15. Operands: Zn.T, Pg (bare), R (R0-R30), the
|
|
// arrangement feeding the size field.
|
|
ExtFormZLastReg
|
|
)
|
|
|
|
// Arity returns the operand count the form takes.
|
|
func (f ExtForm) Arity() int {
|
|
switch f {
|
|
case ExtFormVectors, ExtFormPredicated, ExtFormPredicatePermute,
|
|
ExtFormPredicateFirst, ExtFormPredicateNext, ExtFormWhile,
|
|
ExtFormPredicateBreak, ExtFormPredicateBreakZero,
|
|
ExtFormZUnary, ExtFormZGov, ExtFormVectorsZm, ExtFormZImmediateSource:
|
|
return 3
|
|
case ExtFormPredicateLogical, ExtFormPredicateSelect, ExtFormPredicateLogicalDest,
|
|
ExtFormZPredicatedSource, ExtFormZSelect:
|
|
return 4
|
|
case ExtFormImmediate, ExtFormSignedImmediate, ExtFormPredicateFFRRead,
|
|
ExtFormPredicateMove, ExtFormPredicateUnpack, ExtFormPredicateTest,
|
|
ExtFormZMoveBare, ExtFormZFromGeneral,
|
|
ExtFormZLastReg, ExtFormZMove, ExtFormZUnpack:
|
|
return 2
|
|
case ExtFormAmdVec3, ExtFormAmdMask2, ExtFormAmdVecGprVec:
|
|
return 3
|
|
case ExtFormAmdVec2, ExtFormAmdVec2Half, ExtFormAmdGprVec, ExtFormAmdVecGpr:
|
|
return 2
|
|
case ExtFormAmdVec3Imm, ExtFormAmdMask2Imm:
|
|
return 4
|
|
case ExtFormAmdMemVec, ExtFormAmdVecMem:
|
|
return 2
|
|
case ExtFormPredicateOne, ExtFormPredicateWrite, ExtFormPredicateCounter:
|
|
return 1
|
|
case ExtFormNone:
|
|
return 0
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// Kinds returns the operand kind each position of the form wants, in the
|
|
// order the operands arrive. The registry uses the list to pick the most
|
|
// specific rejection when every matching form refuses an operand list.
|
|
func (f ExtForm) Kinds() []ExtOperandKind {
|
|
switch f {
|
|
case ExtFormVectors:
|
|
return []ExtOperandKind{ExtZReg, ExtZReg, ExtZReg}
|
|
case ExtFormPredicated:
|
|
return []ExtOperandKind{ExtZReg, ExtPReg, ExtZReg}
|
|
case ExtFormImmediate, ExtFormSignedImmediate:
|
|
return []ExtOperandKind{ExtImm, ExtZReg}
|
|
// The amd64 forms return no kinds: the exact vector class depends on the
|
|
// entry's encoding template (its L'L field), which the form alone cannot
|
|
// name, and the encode paths diagnose the class themselves.
|
|
case ExtFormPredicateLogical, ExtFormPredicateSelect, ExtFormPredicateLogicalDest:
|
|
return []ExtOperandKind{ExtPReg, ExtPReg, ExtPReg, ExtPReg}
|
|
case ExtFormPredicateBreak, ExtFormPredicateBreakZero, ExtFormPredicateFFRRead:
|
|
return []ExtOperandKind{ExtPReg, ExtPReg, ExtPReg}
|
|
case ExtFormPredicatePermute:
|
|
return []ExtOperandKind{ExtPReg, ExtPReg, ExtPReg}
|
|
case ExtFormPredicateFirst, ExtFormPredicateNext:
|
|
return []ExtOperandKind{ExtPReg, ExtPReg, ExtPReg}
|
|
case ExtFormPredicateOne, ExtFormPredicateWrite, ExtFormPredicateCounter:
|
|
return []ExtOperandKind{ExtPReg}
|
|
case ExtFormPredicateMove, ExtFormPredicateUnpack, ExtFormPredicateTest:
|
|
return []ExtOperandKind{ExtPReg, ExtPReg}
|
|
case ExtFormWhile:
|
|
return []ExtOperandKind{ExtGReg, ExtGReg, ExtPReg}
|
|
case ExtFormZUnary, ExtFormZGov, ExtFormZMove, ExtFormVectorsZm:
|
|
return []ExtOperandKind{ExtZReg, ExtZReg, ExtZReg}
|
|
case ExtFormZPredicatedSource:
|
|
return []ExtOperandKind{ExtZReg, ExtZReg, ExtPReg, ExtZReg}
|
|
case ExtFormZImmediateSource:
|
|
return []ExtOperandKind{ExtImm, ExtZReg, ExtZReg}
|
|
case ExtFormZSelect:
|
|
return []ExtOperandKind{ExtZReg, ExtZReg, ExtPReg, ExtZReg}
|
|
case ExtFormZMoveBare:
|
|
return []ExtOperandKind{ExtZReg, ExtZReg}
|
|
case ExtFormZFromGeneral:
|
|
return []ExtOperandKind{ExtGReg, ExtZReg}
|
|
case ExtFormZLastReg:
|
|
return []ExtOperandKind{ExtZReg, ExtPReg, ExtGReg}
|
|
case ExtFormNone:
|
|
return nil
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// String returns a short label for the form, for diagnostics.
|
|
func (f ExtForm) String() string {
|
|
switch f {
|
|
case ExtFormVectors:
|
|
return "unpredicated vectors"
|
|
case ExtFormPredicated:
|
|
return "predicated (merging)"
|
|
case ExtFormImmediate:
|
|
return "unsigned immediate"
|
|
case ExtFormSignedImmediate:
|
|
return "signed immediate"
|
|
case ExtFormAmdVec3:
|
|
return "three vectors"
|
|
case ExtFormAmdVec2:
|
|
return "two vectors"
|
|
case ExtFormAmdVec2Half:
|
|
return "two vectors, half-width destination"
|
|
case ExtFormAmdMask2:
|
|
return "two vectors into an opmask"
|
|
case ExtFormAmdVecGprVec:
|
|
return "vector, general register, vector"
|
|
case ExtFormAmdGprVec:
|
|
return "general register, vector"
|
|
case ExtFormAmdVecGpr:
|
|
return "vector, general register"
|
|
case ExtFormAmdVec3Imm:
|
|
return "immediate, three vectors"
|
|
case ExtFormAmdMask2Imm:
|
|
return "immediate, two vectors into an opmask"
|
|
case ExtFormAmdMemVec:
|
|
return "memory into a vector"
|
|
case ExtFormAmdVecMem:
|
|
return "a vector into memory"
|
|
case ExtFormPredicateLogical:
|
|
return "predicate logical"
|
|
case ExtFormPredicateSelect:
|
|
return "predicate select"
|
|
case ExtFormPredicateLogicalDest:
|
|
return "predicate logical, shared destination"
|
|
case ExtFormPredicateBreak:
|
|
return "break"
|
|
case ExtFormPredicateBreakZero:
|
|
return "break, zeroing"
|
|
case ExtFormPredicatePermute:
|
|
return "predicate permutation"
|
|
case ExtFormPredicateFirst:
|
|
return "predicate first"
|
|
case ExtFormPredicateNext:
|
|
return "predicate next"
|
|
case ExtFormPredicateOne:
|
|
return "single predicate"
|
|
case ExtFormPredicateWrite:
|
|
return "single source predicate"
|
|
case ExtFormPredicateFFRRead:
|
|
return "FFR read"
|
|
case ExtFormPredicateMove:
|
|
return "predicate move"
|
|
case ExtFormPredicateUnpack:
|
|
return "predicate unpack"
|
|
case ExtFormPredicateTest:
|
|
return "predicate test"
|
|
case ExtFormWhile:
|
|
return "while compare"
|
|
case ExtFormPredicateCounter:
|
|
return "counter predicate"
|
|
case ExtFormVectorsZm:
|
|
return "unpredicated vectors, Zm first"
|
|
case ExtFormZUnary:
|
|
return "predicated vector"
|
|
case ExtFormZPredicatedSource:
|
|
return "predicated vector with source"
|
|
case ExtFormZImmediateSource:
|
|
return "immediate with source"
|
|
case ExtFormZSelect:
|
|
return "vector select"
|
|
case ExtFormZGov:
|
|
return "governed compact"
|
|
case ExtFormZMove:
|
|
return "vector move"
|
|
case ExtFormZMoveBare:
|
|
return "bare vector move"
|
|
case ExtFormZUnpack:
|
|
return "vector unpack"
|
|
case ExtFormZFromGeneral:
|
|
return "general into vector"
|
|
case ExtFormZLastReg:
|
|
return "last element to register"
|
|
case ExtFormNone:
|
|
return "no operands"
|
|
default:
|
|
return "unknown form"
|
|
}
|
|
}
|
|
|
|
// ExtFeature names the architecture feature an extended instruction belongs
|
|
// to. The field is metadata: the assembler offers every instruction it
|
|
// registers, and a feature check is the caller's decision, not the encoder's.
|
|
type ExtFeature string
|
|
|
|
// The features the arm64 layer covers.
|
|
const (
|
|
ExtFeatureSVE ExtFeature = "sve"
|
|
ExtFeatureSVE2 ExtFeature = "sve2"
|
|
ExtFeatureSVE2p1 ExtFeature = "sve2p1"
|
|
)
|
|
|
|
// ExtImm8Kind names the imm8-control layout an amd64 extended entry carries
|
|
// in its immediate operand. The kind drives the validation at encode time:
|
|
// a value the manual reserves is an error, never a silent mis-encoding.
|
|
type ExtImm8Kind uint8
|
|
|
|
// The imm8-control layouts, ExtImm8None first as the zero value an entry
|
|
// without an immediate carries.
|
|
const (
|
|
// ExtImm8None marks a form that takes no immediate operand.
|
|
ExtImm8None ExtImm8Kind = iota
|
|
// ExtImm8ScaleRound is the fraction-bits-plus-round-control layout of
|
|
// VRNDSCALESH and VREDUCESH: imm8[7:4] carries the number of fraction
|
|
// bits M, imm8[3] the precision-exception control, imm8[2] the rounding
|
|
// mode source and imm8[1:0] the rounding mode. Every byte encodes.
|
|
ExtImm8ScaleRound
|
|
// ExtImm8GetMant is the mantissa-extraction control of VGETMANTSH:
|
|
// imm8[3:2] the sign control, imm8[1:0] the normalisation interval,
|
|
// and imm8[7:4] reserved, which must encode as zero.
|
|
ExtImm8GetMant
|
|
// ExtImm8CmpPredicate is the comparison-predicate control of VCMPSH:
|
|
// imm8[4:0] names one of the 32 predicates and the bits above are
|
|
// masked away by the hardware, so every byte encodes.
|
|
ExtImm8CmpPredicate
|
|
)
|
|
|
|
// String returns a short label for the imm8-control layout, for diagnostics.
|
|
func (k ExtImm8Kind) String() string {
|
|
switch k {
|
|
case ExtImm8ScaleRound:
|
|
return "fraction bits and round control"
|
|
case ExtImm8GetMant:
|
|
return "mantissa extraction control"
|
|
case ExtImm8CmpPredicate:
|
|
return "comparison predicate"
|
|
default:
|
|
return "no immediate"
|
|
}
|
|
}
|
|
|
|
// ExtInstr is one extended instruction: the metadata a lookup needs and the
|
|
// encoding as data. Word holds the fixed bits of the 32-bit encoding with
|
|
// every operand field and the size field zero; the form says which fields the
|
|
// operands fill; the size field receives the arrangement's bits at encode
|
|
// time. Ref names the manual entry the encoding is transcribed from, the
|
|
// golden source in place of a toolchain oracle.
|
|
type ExtInstr struct {
|
|
Name string // upper-case mnemonic
|
|
Summary string // one line of hover documentation
|
|
Word uint32 // fixed encoding bits, operand fields zero
|
|
Form ExtForm // operand shape
|
|
Size ExtField // element-size field the arrangement fills
|
|
Feature ExtFeature // sve, sve2 or sve2p1
|
|
Ref string // the ARM ARM entry the encoding comes from
|
|
// Bytes is the amd64 encoding template: the EVEX prefix, opcode and
|
|
// ModR/M byte of one form, with every register-derived bit zero. The
|
|
// vector length and the general-register width an entry encodes are read
|
|
// back out of it at encode time.
|
|
Bytes []byte
|
|
// Wig records that the entry ignores the W bit in its general-register
|
|
// position, so both 32-bit and 64-bit registers encode.
|
|
Wig bool
|
|
// Imm8 names the imm8-control layout the amd64 entry's immediate
|
|
// operand carries, ExtImm8None when the form takes none. The arm64
|
|
// entries all carry the zero value.
|
|
Imm8 ExtImm8Kind
|
|
// Mem names the 1-based operand position that may carry a memory
|
|
// operand beside the register the position normally takes: 2 on the
|
|
// arithmetic whose second source the manual spells xmm3/m16, 1 on the
|
|
// narrow BF16 convert whose source it spells m256/m512. Zero means
|
|
// the form takes registers alone. The load and store shapes are forms
|
|
// of their own, ExtFormAmdMemVec and ExtFormAmdVecMem, and need no
|
|
// flag. The arm64 entries all carry the zero value.
|
|
Mem int
|
|
// Bcast records that the entry's memory position takes the {1toN}
|
|
// broadcast beside the plain vector source, the SDM's m16bcst and
|
|
// m32bcst spellings: one element the hardware splats across the lanes,
|
|
// encoded as EVEX.b. The packed arithmetic carries it; the scalar
|
|
// forms and the full-width sources do not. The arm64 entries all
|
|
// carry the zero value.
|
|
Bcast bool
|
|
// Mask records that the entry's packed destination takes the write
|
|
// mask, the SDM's {k1}{z} decorations: EVEX.aaa carries the masking
|
|
// register and EVEX.z the zeroing bit. The packed forms carry it; the
|
|
// scalar forms, the compares without a vector destination, the
|
|
// opmask-destination forms and the load and store shapes do not. The
|
|
// arm64 entries all carry the zero value.
|
|
Mask bool
|
|
// PgQual names the qualifier the row's governing predicate requires,
|
|
// where the form takes one: merging, zeroing or either (the MOVPRFX
|
|
// classes spell both with one encoding). Forms without such a
|
|
// predicate ignore it.
|
|
PgQual ExtQualifier
|
|
// Arr fixes the one arrangement the row takes, where the class locks it
|
|
// into the word (the .D-locked ZDUP and ZINSR general-register forms,
|
|
// the .Q permutations). ExtArrNone leaves the arrangement to the
|
|
// operands and the size field.
|
|
Arr ExtArrangement
|
|
}
|
|
|
|
// Encode assembles the operands into the 4 little-endian bytes of the
|
|
// instruction word. The operand kinds, register ranges, arrangements and
|
|
// immediate ranges are validated against the form; an operand the class
|
|
// cannot carry is an error, never a silent mis-encoding.
|
|
func (in ExtInstr) Encode(ops []ExtOperand) ([]byte, error) {
|
|
if len(ops) != in.Form.Arity() {
|
|
return nil, fmt.Errorf("%s: the %s form takes %d operands, got %d",
|
|
in.Name, in.Form, in.Form.Arity(), len(ops))
|
|
}
|
|
switch in.Form {
|
|
case ExtFormVectors:
|
|
return in.encodeVectors(ops)
|
|
case ExtFormPredicated:
|
|
return in.encodePredicated(ops)
|
|
case ExtFormImmediate:
|
|
return in.encodeImmediate(ops)
|
|
case ExtFormSignedImmediate:
|
|
return in.encodeSignedImmediate(ops)
|
|
case ExtFormAmdVec3, ExtFormAmdVec2, ExtFormAmdVec2Half, ExtFormAmdMask2,
|
|
ExtFormAmdVecGprVec, ExtFormAmdGprVec, ExtFormAmdVecGpr,
|
|
ExtFormAmdVec3Imm, ExtFormAmdMask2Imm, ExtFormAmdMemVec, ExtFormAmdVecMem:
|
|
return in.encodeAmd64(ops)
|
|
case ExtFormPredicateLogical, ExtFormPredicateSelect:
|
|
return in.encodePredicateLogical(ops)
|
|
case ExtFormPredicateLogicalDest:
|
|
return in.encodePredicateLogicalDest(ops)
|
|
case ExtFormPredicateBreak, ExtFormPredicateBreakZero:
|
|
return in.encodePredicateBreak(ops)
|
|
case ExtFormPredicatePermute:
|
|
return in.encodePredicatePermute(ops)
|
|
case ExtFormPredicateFirst, ExtFormPredicateNext:
|
|
return in.encodePredicateReadBack(ops)
|
|
case ExtFormPredicateOne:
|
|
return in.encodePredicateOne(ops)
|
|
case ExtFormPredicateWrite:
|
|
return in.encodePredicateWrite(ops)
|
|
case ExtFormPredicateFFRRead:
|
|
return in.encodePredicateFFRRead(ops)
|
|
case ExtFormPredicateMove:
|
|
return in.encodePredicateMove(ops)
|
|
case ExtFormPredicateUnpack:
|
|
return in.encodePredicateUnpack(ops)
|
|
case ExtFormPredicateTest:
|
|
return in.encodePredicateTest(ops)
|
|
case ExtFormWhile:
|
|
return in.encodeWhile(ops)
|
|
case ExtFormPredicateCounter:
|
|
return in.encodePredicateCounter(ops)
|
|
case ExtFormZUnary:
|
|
return in.encodeZUnary(ops)
|
|
case ExtFormVectorsZm:
|
|
return in.encodeVectorsZm(ops)
|
|
case ExtFormZPredicatedSource:
|
|
return in.encodeZPredicatedSource(ops)
|
|
case ExtFormZImmediateSource:
|
|
return in.encodeZImmediateSource(ops)
|
|
case ExtFormZSelect:
|
|
return in.encodeZSelect(ops)
|
|
case ExtFormZGov:
|
|
return in.encodeZGov(ops)
|
|
case ExtFormZMove:
|
|
return in.encodeZMove(ops)
|
|
case ExtFormZMoveBare:
|
|
return in.encodeZMoveBare(ops)
|
|
case ExtFormZUnpack:
|
|
return in.encodeZUnpack(ops)
|
|
case ExtFormZFromGeneral:
|
|
return in.encodeZFromGeneral(ops)
|
|
case ExtFormZLastReg:
|
|
return in.encodeZLastReg(ops)
|
|
case ExtFormNone:
|
|
if len(ops) != 0 {
|
|
return nil, fmt.Errorf("%s: the %s form takes no operands, got %d",
|
|
in.Name, in.Form, len(ops))
|
|
}
|
|
return extWordLE(in.Word), nil
|
|
default:
|
|
return nil, fmt.Errorf("%s: unknown form %d", in.Name, in.Form)
|
|
}
|
|
}
|
|
|
|
// encodeVectors fills the unpredicated three-vector form: Zn, Zm, Zd, all
|
|
// under one required arrangement.
|
|
func (in ExtInstr) encodeVectors(ops []ExtOperand) ([]byte, error) {
|
|
for i, op := range ops {
|
|
if op.Kind != ExtZReg {
|
|
return nil, fmt.Errorf("%s: operand %d wants a scalable vector register, got %s",
|
|
in.Name, i+1, op.Kind)
|
|
}
|
|
if op.Reg < 0 || op.Reg > 31 {
|
|
return nil, fmt.Errorf("%s: operand %d is Z%d, outside Z0-Z31", in.Name, i+1, op.Reg)
|
|
}
|
|
}
|
|
arr, err := in.sharedArrangement(ops)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
size, ok := arr.sizeBits()
|
|
if !ok {
|
|
return nil, fmt.Errorf("%s: arrangement %s has no size encoding in this class", in.Name, arr)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldRn, uint32(ops[0].Reg))
|
|
word = extSet(word, extFieldRm, uint32(ops[1].Reg))
|
|
word = extSet(word, extFieldRd, uint32(ops[2].Reg))
|
|
word = extSet(word, in.Size, size)
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicated fills the governed destructive form: Zm, Pg/M, Zdn. The
|
|
// predicate is a 3-bit field, the merging qualifier alone, and carries no
|
|
// arrangement suffix in this class.
|
|
func (in ExtInstr) encodePredicated(ops []ExtOperand) ([]byte, error) {
|
|
zm, pg, zdn := ops[0], ops[1], ops[2]
|
|
if zm.Kind != ExtZReg {
|
|
return nil, fmt.Errorf("%s: operand 1 wants a scalable vector register, got %s",
|
|
in.Name, zm.Kind)
|
|
}
|
|
if zm.Reg < 0 || zm.Reg > 31 {
|
|
return nil, fmt.Errorf("%s: operand 1 is Z%d, outside Z0-Z31", in.Name, zm.Reg)
|
|
}
|
|
if pg.Kind != ExtPReg {
|
|
return nil, fmt.Errorf("%s: operand 2 wants a predicate register, got %s",
|
|
in.Name, pg.Kind)
|
|
}
|
|
if pg.Reg < 0 || pg.Reg > 7 {
|
|
return nil, fmt.Errorf("%s: operand 2 is P%d, outside P0-P7 in this class", in.Name, pg.Reg)
|
|
}
|
|
if pg.Qual != ExtQualMerging {
|
|
return nil, fmt.Errorf("%s: operand 2 wants the merging qualifier /M, got %q",
|
|
in.Name, pg.Qual)
|
|
}
|
|
if pg.Arr != ExtArrNone {
|
|
return nil, fmt.Errorf("%s: the governing predicate carries no arrangement suffix, got %s",
|
|
in.Name, pg.Arr)
|
|
}
|
|
if zdn.Kind != ExtZReg {
|
|
return nil, fmt.Errorf("%s: operand 3 wants a scalable vector register, got %s",
|
|
in.Name, zdn.Kind)
|
|
}
|
|
if zdn.Reg < 0 || zdn.Reg > 31 {
|
|
return nil, fmt.Errorf("%s: operand 3 is Z%d, outside Z0-Z31", in.Name, zdn.Reg)
|
|
}
|
|
if zm.Arr != zdn.Arr {
|
|
return nil, fmt.Errorf("%s: operands 1 and 3 carry arrangements %s and %s, they must match",
|
|
in.Name, zm.Arr, zdn.Arr)
|
|
}
|
|
size, ok := zdn.Arr.sizeBits()
|
|
if !ok {
|
|
return nil, fmt.Errorf("%s: arrangement %s has no size encoding in this class", in.Name, zdn.Arr)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldRn, uint32(zm.Reg))
|
|
word = extSet(word, extFieldPg, uint32(pg.Reg))
|
|
word = extSet(word, extFieldRd, uint32(zdn.Reg))
|
|
word = extSet(word, in.Size, size)
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeImmediate fills the add/subtract immediate form: imm{, LSL #8}, Zdn.
|
|
// The class encodes an unsigned imm8 with one shift bit, so a bare multiple
|
|
// of 256 derives the shift the way the GNU assembler canonicalises it.
|
|
func (in ExtInstr) encodeImmediate(ops []ExtOperand) ([]byte, error) {
|
|
imm, zdn := ops[0], ops[1]
|
|
imm8, sh, err := in.addSubImmediate(imm, zdn.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldImm8, uint32(imm8))
|
|
if sh != 0 {
|
|
word = extSet(word, extFieldSh, 1)
|
|
}
|
|
word, err = in.setDestAndSize(word, zdn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeSignedImmediate fills the multiply immediate form: simm8, Zdn, with
|
|
// no shift bit in the class.
|
|
func (in ExtInstr) encodeSignedImmediate(ops []ExtOperand) ([]byte, error) {
|
|
imm, zdn := ops[0], ops[1]
|
|
if imm.Kind != ExtImm {
|
|
return nil, fmt.Errorf("%s: operand 1 wants an immediate, got %s", in.Name, imm.Kind)
|
|
}
|
|
if imm.HasShift {
|
|
return nil, fmt.Errorf("%s: the signed immediate class takes no shift", in.Name)
|
|
}
|
|
if imm.Imm < -128 || imm.Imm > 127 {
|
|
return nil, fmt.Errorf("%s: immediate %d is outside the signed 8-bit range -128..127",
|
|
in.Name, imm.Imm)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldImm8, uint32(imm.Imm))
|
|
word, err := in.setDestAndSize(word, zdn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// addSubImmediate resolves the immediate operand of the add/subtract
|
|
// immediate class into its imm8 and shift bit: a spelled shift is validated
|
|
// as written, a bare multiple of 256 (on .H, .S or .D) derives one.
|
|
func (in ExtInstr) addSubImmediate(op ExtOperand, arr ExtArrangement) (imm8, sh int, err error) {
|
|
if op.Kind != ExtImm {
|
|
return 0, 0, fmt.Errorf("%s: operand 1 wants an immediate, got %s", in.Name, op.Kind)
|
|
}
|
|
switch {
|
|
case op.HasShift:
|
|
if op.Shift != 0 && op.Shift != 8 {
|
|
return 0, 0, fmt.Errorf("%s: the shift amount must be 0 or 8, got %d", in.Name, op.Shift)
|
|
}
|
|
if arr == ExtArrB && op.Shift != 0 {
|
|
return 0, 0, fmt.Errorf("%s: arrangement .B takes no shift", in.Name)
|
|
}
|
|
if op.Imm < 0 || op.Imm > 255 {
|
|
return 0, 0, fmt.Errorf("%s: immediate %d is outside the unsigned 8-bit range 0..255",
|
|
in.Name, op.Imm)
|
|
}
|
|
return int(op.Imm), op.Shift, nil
|
|
case op.Imm >= 0 && op.Imm <= 255:
|
|
return int(op.Imm), 0, nil
|
|
case arr != ExtArrB && op.Imm >= 256 && op.Imm <= 255<<8 && op.Imm%256 == 0:
|
|
// A bare multiple of 256 rides the shift bit, 65280 = 255<<8 included.
|
|
return int(op.Imm / 256), 8, nil
|
|
default:
|
|
return 0, 0, fmt.Errorf("%s: immediate %d is not an unsigned imm8%s, nor a multiple of 256 the shift bit can carry",
|
|
in.Name, op.Imm, arr.shiftNote())
|
|
}
|
|
}
|
|
|
|
// shiftNote describes where a shifted constant is expressible, for the
|
|
// immediate range error.
|
|
func (arr ExtArrangement) shiftNote() string {
|
|
if arr == ExtArrB {
|
|
return " (and .B takes no shifted constant)"
|
|
}
|
|
return " (a multiple of 256 up to 65280 shifts)"
|
|
}
|
|
|
|
// predicateOperand validates one predicate operand: its kind, its register
|
|
// range and, when want is non-empty, the one arrangement the class takes.
|
|
func (in ExtInstr) predicateOperand(op ExtOperand, position int, lo, hi int, want ExtArrangement) error {
|
|
if op.Kind != ExtPReg {
|
|
return fmt.Errorf("%s: operand %d wants a predicate register, got %s",
|
|
in.Name, position, op.Kind)
|
|
}
|
|
if op.Reg < lo || op.Reg > hi {
|
|
return fmt.Errorf("%s: operand %d is P%d, outside P%d-P%d in this class",
|
|
in.Name, position, op.Reg, lo, hi)
|
|
}
|
|
if want != ExtArrNone && op.Arr != want {
|
|
return fmt.Errorf("%s: operand %d carries arrangement %s, want %s",
|
|
in.Name, position, op.Arr, want)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// encodePredicateLogical fills the four-operand predicate logical form:
|
|
// Pm.B, Pn.B, Pg{qualifier}, Pd.B. Pm takes P0-P7, Pn and Pd P0-P15; the
|
|
// governing predicate takes P0-P7 and its qualifier is zeroing for the
|
|
// logical operations and bare for PSEL, which the form distinguishes.
|
|
func (in ExtInstr) encodePredicateLogical(ops []ExtOperand) ([]byte, error) {
|
|
pm, pn, pg, pd := ops[0], ops[1], ops[2], ops[3]
|
|
if err := in.predicateOperand(pm, 1, 0, 7, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pn, 2, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
// The governing predicate carries its qualifier in place of an
|
|
// arrangement (P1.Z), so the form judges the qualifier below.
|
|
if err := in.predicateOperand(pg, 3, 0, 7, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if pg.Arr != ExtArrNone {
|
|
return nil, fmt.Errorf("%s: the governing predicate carries no arrangement suffix, got %s",
|
|
in.Name, pg.Arr)
|
|
}
|
|
if err := in.predicateOperand(pd, 4, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
wantQual := ExtQualZeroing
|
|
if in.Form == ExtFormPredicateSelect {
|
|
wantQual = ExtQualNone
|
|
}
|
|
if pg.Qual != wantQual {
|
|
if wantQual == ExtQualNone {
|
|
return nil, fmt.Errorf("%s: operand 3 takes no qualifier, got %q",
|
|
in.Name, pg.Qual)
|
|
}
|
|
return nil, fmt.Errorf("%s: operand 3 wants the zeroing qualifier, got %q",
|
|
in.Name, pg.Qual)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPm, uint32(pm.Reg))
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPgN, uint32(pg.Reg))
|
|
word = extSet(word, extFieldPd, uint32(pd.Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateLogicalDest fills the break form whose first operand is the
|
|
// destination read back: Pdm.B, Pn.B, Pg/Z, Pdm.B. The encoding carries the
|
|
// register once, so operands 1 and 4 must name the same register.
|
|
func (in ExtInstr) encodePredicateLogicalDest(ops []ExtOperand) ([]byte, error) {
|
|
pdm, pn, pg := ops[0], ops[1], ops[2]
|
|
if err := in.predicateOperand(pdm, 1, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pn, 2, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pg, 3, 0, 7, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if pg.Arr != ExtArrNone {
|
|
return nil, fmt.Errorf("%s: the governing predicate carries no arrangement suffix, got %s",
|
|
in.Name, pg.Arr)
|
|
}
|
|
if err := in.predicateOperand(ops[3], 4, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
if pg.Qual != ExtQualZeroing {
|
|
return nil, fmt.Errorf("%s: operand 3 wants the zeroing qualifier, got %q",
|
|
in.Name, pg.Qual)
|
|
}
|
|
if ops[3].Reg != pdm.Reg {
|
|
return nil, fmt.Errorf("%s: operands 1 and 4 are the same register Pdm, got P%d and P%d",
|
|
in.Name, pdm.Reg, ops[3].Reg)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPgN, uint32(pg.Reg))
|
|
word = extSet(word, extFieldPd, uint32(pdm.Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateBreak fills the three-operand break form: Pn.B, Pg{qual},
|
|
// Pd.B. The governing predicate is the wide four-bit field (P0-P15); the
|
|
// plain break accepts the merging or the zeroing qualifier, the S variant
|
|
// the zeroing alone.
|
|
func (in ExtInstr) encodePredicateBreak(ops []ExtOperand) ([]byte, error) {
|
|
pn, pg, pd := ops[0], ops[1], ops[2]
|
|
if err := in.predicateOperand(pn, 1, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pg, 2, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pd, 3, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
switch {
|
|
case pg.Qual == ExtQualZeroing:
|
|
case pg.Qual == ExtQualMerging && in.Form == ExtFormPredicateBreak:
|
|
default:
|
|
return nil, fmt.Errorf("%s: operand 2 wants the zeroing qualifier%s, got %q",
|
|
in.Name, mergingNote(in.Form), pg.Qual)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPgW, uint32(pg.Reg))
|
|
word = extSet(word, extFieldPd, uint32(pd.Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// mergingNote describes the qualifier rule of a break form, for the error.
|
|
func mergingNote(f ExtForm) string {
|
|
if f == ExtFormPredicateBreak {
|
|
return " or the merging qualifier"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// encodePredicatePermute fills the predicate permutation form: Pm.T, Pn.T,
|
|
// Pd.T under one shared arrangement, which feeds the size field.
|
|
func (in ExtInstr) encodePredicatePermute(ops []ExtOperand) ([]byte, error) {
|
|
pm, pn, pd := ops[0], ops[1], ops[2]
|
|
if err := in.predicateOperand(pm, 1, 0, 7, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pn, 2, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pd, 3, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
size, err := in.sharedSize(pm.Arr, pn.Arr, pd.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPm, uint32(pm.Reg))
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPd, uint32(pd.Reg))
|
|
word = extSet(word, in.Size, size)
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateReadBack fills the destination-read-back forms of PFIRST
|
|
// and PNEXT: Pdn{.B or .T}, Pg or Pv (bare), Pdn. Operands 1 and 3 name the
|
|
// same register; PNEXT carries the size field, PFIRST is .B alone.
|
|
func (in ExtInstr) encodePredicateReadBack(ops []ExtOperand) ([]byte, error) {
|
|
pdn, pg := ops[0], ops[1]
|
|
if err := in.predicateOperand(pdn, 1, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pg, 2, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(ops[2], 3, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if pg.Arr != ExtArrNone {
|
|
return nil, fmt.Errorf("%s: operand 2 carries no arrangement suffix, got %s",
|
|
in.Name, pg.Arr)
|
|
}
|
|
if pg.Qual != ExtQualNone {
|
|
return nil, fmt.Errorf("%s: operand 2 takes no qualifier, got %q", in.Name, pg.Qual)
|
|
}
|
|
if ops[2].Reg != pdn.Reg || ops[2].Arr != pdn.Arr {
|
|
return nil, fmt.Errorf("%s: operands 1 and 3 are the same register Pdn, got P%d and P%d",
|
|
in.Name, pdn.Reg, ops[2].Reg)
|
|
}
|
|
var size uint32
|
|
if in.Form == ExtFormPredicateNext {
|
|
var ok bool
|
|
size, ok = pdn.Arr.sizeBits()
|
|
if !ok {
|
|
return nil, fmt.Errorf("%s: arrangement %s has no size encoding in this class",
|
|
in.Name, pdn.Arr)
|
|
}
|
|
} else if pdn.Arr != ExtArrB {
|
|
return nil, fmt.Errorf("%s: operand 1 carries arrangement %s, want .B",
|
|
in.Name, pdn.Arr)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pg.Reg))
|
|
word = extSet(word, extFieldPd, uint32(pdn.Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateOne fills the single-predicate form: Pd.B, destination in
|
|
// the four-bit field.
|
|
func (in ExtInstr) encodePredicateOne(ops []ExtOperand) ([]byte, error) {
|
|
if err := in.predicateOperand(ops[0], 1, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
word := extSet(in.Word, extFieldPd, uint32(ops[0].Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateWrite fills WRFFR's single-source form: Pn.B in the
|
|
// five-bit source slot.
|
|
func (in ExtInstr) encodePredicateWrite(ops []ExtOperand) ([]byte, error) {
|
|
if err := in.predicateOperand(ops[0], 1, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
word := extSet(in.Word, extFieldPn, uint32(ops[0].Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateFFRRead fills the predicated first-fault read: Pg/Z, Pd.B.
|
|
// The first operand is the mask the read passes through, so it sits in the
|
|
// five-bit source slot, not in a governing-predicate field.
|
|
func (in ExtInstr) encodePredicateFFRRead(ops []ExtOperand) ([]byte, error) {
|
|
pg, pd := ops[0], ops[1]
|
|
if err := in.predicateOperand(pg, 1, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pd, 2, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
if pg.Qual != ExtQualZeroing {
|
|
return nil, fmt.Errorf("%s: operand 1 wants the zeroing qualifier, got %q",
|
|
in.Name, pg.Qual)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pg.Reg))
|
|
word = extSet(word, extFieldPd, uint32(pd.Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateMove fills the predicate reverse: Pn.T, Pd.T under one
|
|
// shared arrangement.
|
|
func (in ExtInstr) encodePredicateMove(ops []ExtOperand) ([]byte, error) {
|
|
pn, pd := ops[0], ops[1]
|
|
if err := in.predicateOperand(pn, 1, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pd, 2, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
size, err := in.sharedSize(pn.Arr, pd.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPd, uint32(pd.Reg))
|
|
word = extSet(word, in.Size, size)
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateUnpack fills the predicate unpack: Pn.B, Pd.H, both
|
|
// arrangements fixed by the class.
|
|
func (in ExtInstr) encodePredicateUnpack(ops []ExtOperand) ([]byte, error) {
|
|
pn, pd := ops[0], ops[1]
|
|
if err := in.predicateOperand(pn, 1, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pd, 2, 0, 15, ExtArrH); err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPd, uint32(pd.Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateTest fills PTEST: Pn.B, Pg (bare), no destination.
|
|
func (in ExtInstr) encodePredicateTest(ops []ExtOperand) ([]byte, error) {
|
|
pn, pg := ops[0], ops[1]
|
|
if err := in.predicateOperand(pn, 1, 0, 15, ExtArrB); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pg, 2, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if pg.Qual != ExtQualNone {
|
|
return nil, fmt.Errorf("%s: operand 2 takes no qualifier, got %q", in.Name, pg.Qual)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPgW, uint32(pg.Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeWhile fills the while-compare form: Rm, Rn, Pd.T, the arrangement
|
|
// feeding the size field. The general registers run R0-R30; the class takes
|
|
// no stack pointer and no zero register spelling.
|
|
func (in ExtInstr) encodeWhile(ops []ExtOperand) ([]byte, error) {
|
|
rm, rn, pd := ops[0], ops[1], ops[2]
|
|
for i, op := range []ExtOperand{rm, rn} {
|
|
if op.Kind != ExtGReg {
|
|
return nil, fmt.Errorf("%s: operand %d wants a general register, got %s",
|
|
in.Name, i+1, op.Kind)
|
|
}
|
|
if op.Reg < 0 || op.Reg > 30 {
|
|
return nil, fmt.Errorf("%s: operand %d is R%d, outside R0-R30",
|
|
in.Name, i+1, op.Reg)
|
|
}
|
|
}
|
|
if err := in.predicateOperand(pd, 3, 0, 15, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
size, ok := pd.Arr.sizeBits()
|
|
if !ok {
|
|
return nil, fmt.Errorf("%s: arrangement %s has no size encoding in this class",
|
|
in.Name, pd.Arr)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldRm, uint32(rm.Reg))
|
|
word = extSet(word, extFieldPn, uint32(rn.Reg))
|
|
word = extSet(word, extFieldPd, uint32(pd.Reg))
|
|
word = extSet(word, in.Size, size)
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodePredicateCounter fills PTRUE's counter form: PNd.T, the
|
|
// predicate-as-counter destination spelled PN8-PN15 and encoded as reg-8.
|
|
func (in ExtInstr) encodePredicateCounter(ops []ExtOperand) ([]byte, error) {
|
|
pnd := ops[0]
|
|
if pnd.Kind != ExtPNReg {
|
|
return nil, fmt.Errorf("%s: operand 1 wants a predicate-as-counter register, got %s",
|
|
in.Name, pnd.Kind)
|
|
}
|
|
if pnd.Reg < 8 || pnd.Reg > 15 {
|
|
return nil, fmt.Errorf("%s: operand 1 is PN%d, outside PN8-PN15", in.Name, pnd.Reg)
|
|
}
|
|
size, ok := pnd.Arr.sizeBits()
|
|
if !ok {
|
|
return nil, fmt.Errorf("%s: arrangement %s has no size encoding in this class",
|
|
in.Name, pnd.Arr)
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPnc, uint32(pnd.Reg-8))
|
|
word = extSet(word, in.Size, size)
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// zVector validates one Z operand for the Z-alias classes: kind, range and
|
|
// the row's arrangement rule, shared when in.Arr is none, fixed otherwise.
|
|
func (in ExtInstr) zVector(op ExtOperand, position int) error {
|
|
if op.Kind != ExtZReg {
|
|
return fmt.Errorf("%s: operand %d wants a scalable vector register, got %s",
|
|
in.Name, position, op.Kind)
|
|
}
|
|
if op.Reg < 0 || op.Reg > 31 {
|
|
return fmt.Errorf("%s: operand %d is Z%d, outside Z0-Z31", in.Name, position, op.Reg)
|
|
}
|
|
if in.Arr != ExtArrNone {
|
|
if op.Arr != in.Arr {
|
|
return fmt.Errorf("%s: operand %d carries arrangement %s, want %s",
|
|
in.Name, position, op.Arr, in.Arr)
|
|
}
|
|
} else if op.Arr == ExtArrNone {
|
|
return fmt.Errorf("%s: operand %d carries no arrangement suffix", in.Name, position)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// zBare validates a Z operand that must carry no suffix at all (the bare
|
|
// MOVPRFX spelling).
|
|
func (in ExtInstr) zBare(op ExtOperand, position int) error {
|
|
if op.Kind != ExtZReg {
|
|
return fmt.Errorf("%s: operand %d wants a scalable vector register, got %s",
|
|
in.Name, position, op.Kind)
|
|
}
|
|
if op.Reg < 0 || op.Reg > 31 {
|
|
return fmt.Errorf("%s: operand %d is Z%d, outside Z0-Z31", in.Name, position, op.Reg)
|
|
}
|
|
if op.Arr != ExtArrNone {
|
|
return fmt.Errorf("%s: operand %d takes no arrangement suffix, got %s",
|
|
in.Name, position, op.Arr)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// zGov validates the bare governing predicate of the Z-alias forms: a
|
|
// wide four-bit predicate (P0-P15, the field at bits 13..10 that the
|
|
// ZSEL corpus line pins) with no suffix.
|
|
func (in ExtInstr) zGov(op ExtOperand, position int) error {
|
|
if op.Kind != ExtPReg {
|
|
return fmt.Errorf("%s: operand %d wants a predicate register, got %s",
|
|
in.Name, position, op.Kind)
|
|
}
|
|
if op.Reg < 0 || op.Reg > 15 {
|
|
return fmt.Errorf("%s: operand %d is P%d, outside P0-P15 in this class",
|
|
in.Name, position, op.Reg)
|
|
}
|
|
if op.Arr != ExtArrNone || op.Qual != ExtQualNone {
|
|
return fmt.Errorf("%s: operand %d takes no suffix, got %s%s",
|
|
in.Name, position, op.Arr, op.Qual)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// zSize returns the size encoding for a Z-alias arrangement: the shared
|
|
// arrangement when the row locks none, else nothing (the fixed arrangement
|
|
// rides the word's own bits).
|
|
func (in ExtInstr) zSize(arrs ...ExtArrangement) (uint32, error) {
|
|
if in.Arr != ExtArrNone {
|
|
return 0, nil
|
|
}
|
|
return in.sharedSize(arrs...)
|
|
}
|
|
|
|
// encodeZUnary fills the Z-alias unary predicated form: Zn.T, Pg{qual},
|
|
// Zd.T. The row's PgQual says which qualifier the governing predicate
|
|
// takes; the arrangement is shared, or fixed where the row locks one.
|
|
func (in ExtInstr) encodeZUnary(ops []ExtOperand) ([]byte, error) {
|
|
pn, pg, pd := ops[0], ops[1], ops[2]
|
|
if err := in.zVector(pn, 1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zVector(pd, 3); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pg, 2, 0, 7, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if pg.Arr != ExtArrNone {
|
|
return nil, fmt.Errorf("%s: the governing predicate carries no arrangement suffix, got %s",
|
|
in.Name, pg.Arr)
|
|
}
|
|
switch {
|
|
case pg.Qual == in.PgQual:
|
|
case in.PgQual == ExtQualAny && (pg.Qual == ExtQualMerging || pg.Qual == ExtQualZeroing):
|
|
default:
|
|
if in.PgQual == ExtQualAny {
|
|
return nil, fmt.Errorf("%s: operand 2 wants the merging or zeroing qualifier, got %q",
|
|
in.Name, pg.Qual)
|
|
}
|
|
return nil, fmt.Errorf("%s: operand 2 wants the %s qualifier, got %q",
|
|
in.Name, in.PgQual, pg.Qual)
|
|
}
|
|
size, err := in.zSize(pn.Arr, pd.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPgN, uint32(pg.Reg))
|
|
word = extSet(word, extFieldRd, uint32(pd.Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeZPredicatedSource fills the Z-alias binary predicated form: Zm.T,
|
|
// Zdn.T, Pg/M, Zdn.T, the source copy spelled and equal to the destination.
|
|
func (in ExtInstr) encodeZPredicatedSource(ops []ExtOperand) ([]byte, error) {
|
|
zm, zdn, pg := ops[0], ops[1], ops[2]
|
|
if err := in.zVector(zm, 1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zVector(zdn, 2); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.predicateOperand(pg, 3, 0, 7, ExtArrNone); err != nil {
|
|
return nil, err
|
|
}
|
|
if pg.Arr != ExtArrNone {
|
|
return nil, fmt.Errorf("%s: the governing predicate carries no arrangement suffix, got %s",
|
|
in.Name, pg.Arr)
|
|
}
|
|
if err := in.zVector(ops[3], 4); err != nil {
|
|
return nil, err
|
|
}
|
|
if pg.Qual != ExtQualMerging {
|
|
return nil, fmt.Errorf("%s: operand 3 wants the merging qualifier, got %q",
|
|
in.Name, pg.Qual)
|
|
}
|
|
if ops[3].Reg != zdn.Reg || ops[3].Arr != zdn.Arr {
|
|
return nil, fmt.Errorf("%s: operands 2 and 4 are the same register Zdn, got Z%d and Z%d",
|
|
in.Name, zdn.Reg, ops[3].Reg)
|
|
}
|
|
size, err := in.zSize(zm.Arr, zdn.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldRn, uint32(zm.Reg))
|
|
word = extSet(word, extFieldRm, uint32(zdn.Reg))
|
|
word = extSet(word, extFieldPgN, uint32(pg.Reg))
|
|
word = extSet(word, extFieldRd, uint32(zdn.Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeZImmediateSource fills the Z-alias immediate form: imm{, LSL #8},
|
|
// Zdn.T, Zdn.T, the register encoded once from the repeated spelling.
|
|
func (in ExtInstr) encodeZImmediateSource(ops []ExtOperand) ([]byte, error) {
|
|
imm, zdn := ops[0], ops[1]
|
|
if imm.Kind != ExtImm {
|
|
return nil, fmt.Errorf("%s: operand 1 wants an immediate, got %s", in.Name, imm.Kind)
|
|
}
|
|
if err := in.zVector(zdn, 2); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zVector(ops[2], 3); err != nil {
|
|
return nil, err
|
|
}
|
|
if ops[2].Reg != zdn.Reg || ops[2].Arr != zdn.Arr {
|
|
return nil, fmt.Errorf("%s: operands 2 and 3 are the same register Zdn, got Z%d and Z%d",
|
|
in.Name, zdn.Reg, ops[2].Reg)
|
|
}
|
|
imm8, sh, err := in.addSubImmediate(imm, zdn.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
size, err := in.zSize(zdn.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldImm8, uint32(imm8))
|
|
if sh != 0 {
|
|
word = extSet(word, extFieldSh, 1)
|
|
}
|
|
word = extSet(word, extFieldRd, uint32(zdn.Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeZSelect fills the vector select: Zm.T, Zn.T, Pv, Zd.T.
|
|
func (in ExtInstr) encodeZSelect(ops []ExtOperand) ([]byte, error) {
|
|
zm, zn, pv, zd := ops[0], ops[1], ops[2], ops[3]
|
|
if err := in.zVector(zm, 1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zVector(zn, 2); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zVector(zd, 4); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zGov(pv, 3); err != nil {
|
|
return nil, err
|
|
}
|
|
size, err := in.zSize(zm.Arr, zn.Arr, zd.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldRm, uint32(zm.Reg))
|
|
word = extSet(word, extFieldPn, uint32(zn.Reg))
|
|
word = extSet(word, extFieldPgW, uint32(pv.Reg))
|
|
word = extSet(word, extFieldRd, uint32(zd.Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeZGov fills the governed compact/expand: Zn.T, Pg, Zd.T.
|
|
func (in ExtInstr) encodeZGov(ops []ExtOperand) ([]byte, error) {
|
|
pn, pg, zd := ops[0], ops[1], ops[2]
|
|
if err := in.zVector(pn, 1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zVector(zd, 3); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zGov(pg, 2); err != nil {
|
|
return nil, err
|
|
}
|
|
size, err := in.zSize(pn.Arr, zd.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPgW, uint32(pg.Reg))
|
|
word = extSet(word, extFieldRd, uint32(zd.Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeZMove fills the vector reverse: Zn.T, Zd.T, one shared arrangement.
|
|
func (in ExtInstr) encodeZMove(ops []ExtOperand) ([]byte, error) {
|
|
pn, zd := ops[0], ops[1]
|
|
if err := in.zVector(pn, 1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zVector(zd, 2); err != nil {
|
|
return nil, err
|
|
}
|
|
size, err := in.zSize(pn.Arr, zd.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldRd, uint32(zd.Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeZMoveBare fills MOVPRFX's arrangement-less spelling: Zn, Zd.
|
|
func (in ExtInstr) encodeZMoveBare(ops []ExtOperand) ([]byte, error) {
|
|
if err := in.zBare(ops[0], 1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zBare(ops[1], 2); err != nil {
|
|
return nil, err
|
|
}
|
|
word := extSet(in.Word, extFieldPn, uint32(ops[0].Reg))
|
|
word = extSet(word, extFieldRd, uint32(ops[1].Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeVectorsZm fills the Z-alias three-vector form whose spelled order
|
|
// starts with Zm: ZADD Z7.D, Z23.D, Z13.D puts Zm in the second-source
|
|
// slot, Zn in the first-source slot and Zd in the destination. Rows with
|
|
// a fixed arrangement validate it and leave the size bits to the word.
|
|
func (in ExtInstr) encodeVectorsZm(ops []ExtOperand) ([]byte, error) {
|
|
for i, op := range ops {
|
|
if err := in.zVector(op, i+1); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
var size uint32
|
|
if in.Arr == ExtArrNone {
|
|
var err error
|
|
size, err = in.sharedSize(ops[0].Arr, ops[1].Arr, ops[2].Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldRm, uint32(ops[0].Reg))
|
|
word = extSet(word, extFieldRn, uint32(ops[1].Reg))
|
|
word = extSet(word, extFieldRd, uint32(ops[2].Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeZUnpack fills the vector unpack: Zn.B, Zd.T, the size field
|
|
// riding the destination's arrangement.
|
|
func (in ExtInstr) encodeZUnpack(ops []ExtOperand) ([]byte, error) {
|
|
pn, zd := ops[0], ops[1]
|
|
if err := in.zVector(pn, 1); err != nil {
|
|
return nil, err
|
|
}
|
|
if pn.Arr != ExtArrB {
|
|
return nil, fmt.Errorf("%s: operand 1 carries arrangement %s, want .B", in.Name, pn.Arr)
|
|
}
|
|
if err := in.zVector(zd, 2); err != nil {
|
|
return nil, err
|
|
}
|
|
size, err := in.zSize(zd.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldRd, uint32(zd.Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeZFromGeneral fills the general-into-vector forms, ZDUP and ZINSR:
|
|
// R, Zd.T with the arrangement locked by the row.
|
|
func (in ExtInstr) encodeZFromGeneral(ops []ExtOperand) ([]byte, error) {
|
|
rn, zd := ops[0], ops[1]
|
|
if rn.Kind != ExtGReg {
|
|
return nil, fmt.Errorf("%s: operand 1 wants a general register, got %s", in.Name, rn.Kind)
|
|
}
|
|
if rn.Reg < 0 || rn.Reg > 30 {
|
|
return nil, fmt.Errorf("%s: operand 1 is R%d, outside R0-R30", in.Name, rn.Reg)
|
|
}
|
|
if err := in.zVector(zd, 2); err != nil {
|
|
return nil, err
|
|
}
|
|
word := extSet(in.Word, extFieldPn, uint32(rn.Reg))
|
|
word = extSet(word, extFieldRd, uint32(zd.Reg))
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// encodeZLastReg fills the last-active-element to register: Zn.T, Pg, R.
|
|
func (in ExtInstr) encodeZLastReg(ops []ExtOperand) ([]byte, error) {
|
|
pn, pg, rd := ops[0], ops[1], ops[2]
|
|
if err := in.zVector(pn, 1); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := in.zGov(pg, 2); err != nil {
|
|
return nil, err
|
|
}
|
|
if rd.Kind != ExtGReg {
|
|
return nil, fmt.Errorf("%s: operand 3 wants a general register, got %s", in.Name, rd.Kind)
|
|
}
|
|
if rd.Reg < 0 || rd.Reg > 30 {
|
|
return nil, fmt.Errorf("%s: operand 3 is R%d, outside R0-R30", in.Name, rd.Reg)
|
|
}
|
|
size, err := in.zSize(pn.Arr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
word := in.Word
|
|
word = extSet(word, extFieldPn, uint32(pn.Reg))
|
|
word = extSet(word, extFieldPgW, uint32(pg.Reg))
|
|
word = extSet(word, extFieldRd, uint32(rd.Reg))
|
|
if size != 0 {
|
|
word = extSet(word, in.Size, size)
|
|
}
|
|
return extWordLE(word), nil
|
|
}
|
|
|
|
// sharedSize returns the one element-size encoding the given arrangements
|
|
// agree on, or an error when any operand is bare, they disagree, or the
|
|
// arrangement has no size field.
|
|
func (in ExtInstr) sharedSize(arrs ...ExtArrangement) (uint32, error) {
|
|
arr := arrs[0]
|
|
for i, a := range arrs {
|
|
if a == ExtArrNone {
|
|
return 0, fmt.Errorf("%s: operand %d carries no arrangement suffix", in.Name, i+1)
|
|
}
|
|
if a != arr {
|
|
return 0, fmt.Errorf("%s: operand %d carries arrangement %s, want %s",
|
|
in.Name, i+1, a, arr)
|
|
}
|
|
}
|
|
size, ok := arr.sizeBits()
|
|
if !ok {
|
|
return 0, fmt.Errorf("%s: arrangement %s has no size encoding in this class", in.Name, arr)
|
|
}
|
|
return size, nil
|
|
}
|
|
|
|
// setDestAndSize fills the destructive destination register and the size
|
|
// field from the arrangement the vector carries.
|
|
func (in ExtInstr) setDestAndSize(word uint32, zdn ExtOperand) (uint32, error) {
|
|
if zdn.Kind != ExtZReg {
|
|
return 0, fmt.Errorf("%s: operand 2 wants a scalable vector register, got %s",
|
|
in.Name, zdn.Kind)
|
|
}
|
|
if zdn.Reg < 0 || zdn.Reg > 31 {
|
|
return 0, fmt.Errorf("%s: operand 2 is Z%d, outside Z0-Z31", in.Name, zdn.Reg)
|
|
}
|
|
size, ok := zdn.Arr.sizeBits()
|
|
if !ok {
|
|
return 0, fmt.Errorf("%s: arrangement %s has no size encoding in this class", in.Name, zdn.Arr)
|
|
}
|
|
word = extSet(word, extFieldRd, uint32(zdn.Reg))
|
|
word = extSet(word, in.Size, size)
|
|
return word, nil
|
|
}
|
|
|
|
// sharedArrangement returns the one arrangement all vector operands carry, or
|
|
// an error when any operand is bare or they disagree.
|
|
func (in ExtInstr) sharedArrangement(ops []ExtOperand) (ExtArrangement, error) {
|
|
arr := ops[0].Arr
|
|
for i, op := range ops {
|
|
if op.Arr == ExtArrNone {
|
|
return 0, fmt.Errorf("%s: operand %d carries no arrangement suffix", in.Name, i+1)
|
|
}
|
|
if op.Arr != arr {
|
|
return 0, fmt.Errorf("%s: operand %d carries arrangement %s, want %s",
|
|
in.Name, i+1, op.Arr, arr)
|
|
}
|
|
}
|
|
return arr, nil
|
|
}
|
|
|
|
// extWordLE returns a 32-bit encoding word as 4 little-endian bytes.
|
|
func extWordLE(w uint32) []byte {
|
|
return []byte{byte(w), byte(w >> 8), byte(w >> 16), byte(w >> 24)}
|
|
}
|
|
|
|
// --- the arm64 SVE/SVE2 table ------------------------------------------------
|
|
|
|
// arm64Extensions is the extended instruction layer of arm64: the SVE and
|
|
// SVE2 integer add/subtract/multiply family. The Go toolchain knows none of
|
|
// these; the encodings are transcribed from the ARM Architecture Reference
|
|
// Manual (DDI 0487J, Part C, Chapter C8, the alphabetical list of SVE
|
|
// instructions) and cross-checked against the GNU assembler's and LLVM's
|
|
// published encodings.
|
|
var arm64Extensions = []ExtInstr{
|
|
// Unpredicated three-vector forms: ADD Z0.S, Z1.S, Z2.S.
|
|
{Name: "ADD", Summary: "Add scalable vector elements, unpredicated",
|
|
Word: 0x04200000, Form: ExtFormVectors, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: ADD (vectors, unpredicated)"},
|
|
{Name: "SUB", Summary: "Subtract scalable vector elements, unpredicated",
|
|
Word: 0x04200400, Form: ExtFormVectors, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SUB (vectors, unpredicated)"},
|
|
{Name: "SQADD", Summary: "Add signed saturating scalable vector elements, unpredicated",
|
|
Word: 0x04201000, Form: ExtFormVectors, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SQADD (vectors, unpredicated)"},
|
|
{Name: "UQADD", Summary: "Add unsigned saturating scalable vector elements, unpredicated",
|
|
Word: 0x04201400, Form: ExtFormVectors, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: UQADD (vectors, unpredicated)"},
|
|
{Name: "SQSUB", Summary: "Subtract signed saturating scalable vector elements, unpredicated",
|
|
Word: 0x04201800, Form: ExtFormVectors, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SQSUB (vectors, unpredicated)"},
|
|
{Name: "UQSUB", Summary: "Subtract unsigned saturating scalable vector elements, unpredicated",
|
|
Word: 0x04201c00, Form: ExtFormVectors, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: UQSUB (vectors, unpredicated)"},
|
|
{Name: "MUL", Summary: "Multiply scalable vector elements, unpredicated",
|
|
Word: 0x04206000, Form: ExtFormVectors, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: MUL (vectors, unpredicated)"},
|
|
{Name: "SMULH", Summary: "Multiply signed scalable vector elements, keeping the high half, unpredicated",
|
|
Word: 0x04206800, Form: ExtFormVectors, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SMULH (vectors, unpredicated)"},
|
|
{Name: "UMULH", Summary: "Multiply unsigned scalable vector elements, keeping the high half, unpredicated",
|
|
Word: 0x04206c00, Form: ExtFormVectors, Size: extSizeBHSD, Feature: ExtFeatureSVE2,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: UMULH (vectors, unpredicated)"},
|
|
|
|
// Governed destructive forms, merging: ADD Z1.S, P0/M, Z0.S.
|
|
{Name: "ADD", Summary: "Add scalable vector elements under a governing predicate, merging",
|
|
Word: 0x04000000, Form: ExtFormPredicated, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: ADD (vectors, predicated)"},
|
|
{Name: "SUB", Summary: "Subtract scalable vector elements under a governing predicate, merging",
|
|
Word: 0x04010000, Form: ExtFormPredicated, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SUB (vectors, predicated)"},
|
|
{Name: "SUBR", Summary: "Reverse-subtract scalable vector elements under a governing predicate, merging",
|
|
Word: 0x04030000, Form: ExtFormPredicated, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SUBR (vectors, predicated)"},
|
|
{Name: "MUL", Summary: "Multiply scalable vector elements under a governing predicate, merging",
|
|
Word: 0x04100000, Form: ExtFormPredicated, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: MUL (vectors, predicated)"},
|
|
{Name: "SMULH", Summary: "Multiply signed scalable vector elements, keeping the high half, under a governing predicate, merging",
|
|
Word: 0x04120000, Form: ExtFormPredicated, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SMULH (vectors, predicated)"},
|
|
{Name: "UMULH", Summary: "Multiply unsigned scalable vector elements, keeping the high half, under a governing predicate, merging",
|
|
Word: 0x04130000, Form: ExtFormPredicated, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: UMULH (vectors, predicated)"},
|
|
|
|
// Immediate forms: ADD $255, Z0.S.
|
|
{Name: "ADD", Summary: "Add an unsigned immediate to scalable vector elements",
|
|
Word: 0x2520c000, Form: ExtFormImmediate, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: ADD (vectors, immediate)"},
|
|
{Name: "SUB", Summary: "Subtract an unsigned immediate from scalable vector elements",
|
|
Word: 0x2521c000, Form: ExtFormImmediate, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SUB (vectors, immediate)"},
|
|
{Name: "SUBR", Summary: "Subtract scalable vector elements from an unsigned immediate",
|
|
Word: 0x2523c000, Form: ExtFormImmediate, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SUBR (vectors, immediate)"},
|
|
{Name: "SQADD", Summary: "Add a signed saturating unsigned immediate to scalable vector elements",
|
|
Word: 0x2524c000, Form: ExtFormImmediate, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SQADD (vectors, immediate)"},
|
|
{Name: "UQADD", Summary: "Add an unsigned saturating immediate to scalable vector elements",
|
|
Word: 0x2525c000, Form: ExtFormImmediate, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: UQADD (vectors, immediate)"},
|
|
{Name: "SQSUB", Summary: "Subtract an unsigned immediate from scalable vector elements with signed saturation",
|
|
Word: 0x2526c000, Form: ExtFormImmediate, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: SQSUB (vectors, immediate)"},
|
|
{Name: "UQSUB", Summary: "Subtract an unsigned immediate from scalable vector elements with unsigned saturation",
|
|
Word: 0x2527c000, Form: ExtFormImmediate, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: UQSUB (vectors, immediate)"},
|
|
|
|
// The signed immediate of the multiply class: MUL $-128, Z0.B.
|
|
{Name: "MUL", Summary: "Multiply scalable vector elements by a signed immediate",
|
|
Word: 0x2530c000, Form: ExtFormSignedImmediate, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J, C8.2 SVE instruction descriptions: MUL (vectors, immediate)"},
|
|
|
|
// --- the SVE and SVE2.1 predicate family ---------------------------------
|
|
//
|
|
// The classes below operate on predicates and predicate-as-counter
|
|
// registers. Their encodings follow the field layouts the ARM
|
|
// Architecture Reference Manual's SVE2.1 predicate classes give, as laid
|
|
// out in the toolchain's generated encoding table
|
|
// (cmd/internal/obj/arm64/inst_gen.go, itself generated by
|
|
// x/arch/arm64/instgen from Arm's official ISA description) and in its
|
|
// generated corpus file arm64sveenc.s: the golden test pins every
|
|
// corpus line of each class byte for byte, so no class rests on
|
|
// transcription alone. The toolchain's spellings are kept, including
|
|
// its P prefix on the predicate-register instructions (PRDFFR for
|
|
// RDFFR, PPTRUE for PTRUE, PREV for the predicate REV), because those
|
|
// are the names the corpus assembles under.
|
|
|
|
// Predicate logical operations, SVE2.1: PAND P4.B, P2.B, P1.Z, P14.B.
|
|
{Name: "PAND", Summary: "And predicates over a governing predicate's active lanes",
|
|
Word: 0x25004000, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PAND (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PANDS", Summary: "And predicates, setting the condition flags",
|
|
Word: 0x25404000, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PANDS (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBIC", Summary: "And-complement predicates over a governing predicate's active lanes",
|
|
Word: 0x25004010, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBIC (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBICS", Summary: "And-complement predicates, setting the condition flags",
|
|
Word: 0x25404010, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBICS (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PEOR", Summary: "Exclusive-or predicates over a governing predicate's active lanes",
|
|
Word: 0x25004200, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PEOR (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PEORS", Summary: "Exclusive-or predicates, setting the condition flags",
|
|
Word: 0x25404200, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PEORS (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PNAND", Summary: "And-complement two predicates into one",
|
|
Word: 0x25804210, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PNAND (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PNANDS", Summary: "And-complement two predicates, setting the condition flags",
|
|
Word: 0x25c04210, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PNANDS (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PNOR", Summary: "Or-complement two predicates into one",
|
|
Word: 0x25804200, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PNOR (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PNORS", Summary: "Or-complement two predicates, setting the condition flags",
|
|
Word: 0x25c04200, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PNORS (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PORN", Summary: "Or-complement two predicates into one, complement reversed",
|
|
Word: 0x25804010, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PORN (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PORNS", Summary: "Or-complement two predicates, complement reversed, setting the flags",
|
|
Word: 0x25c04010, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PORNS (predicates); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PORR", Summary: "Or two predicates into one",
|
|
Word: 0x25804000, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: POR (predicates) as PORR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PORRS", Summary: "Or two predicates, setting the condition flags",
|
|
Word: 0x25c04000, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PORS (predicates) as PORR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PSEL", Summary: "Select predicate elements by a governing predicate",
|
|
Word: 0x25004210, Form: ExtFormPredicateSelect, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PSEL (predicates); inst_gen.go + arm64sveenc.s"},
|
|
|
|
// Break operations, SVE2.1 generalised breaks.
|
|
{Name: "PBRKA", Summary: "Break after the first true of the governing predicate",
|
|
Word: 0x25104000, Form: ExtFormPredicateBreak, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKA (break after first true); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBRKAS", Summary: "Break after the first false, setting the condition flags",
|
|
Word: 0x25504000, Form: ExtFormPredicateBreakZero, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKAS (break after first false); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBRKB", Summary: "Break before the first true of the governing predicate",
|
|
Word: 0x25904000, Form: ExtFormPredicateBreak, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKB (break before first true); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBRKBS", Summary: "Break before the first false, setting the condition flags",
|
|
Word: 0x25d04000, Form: ExtFormPredicateBreakZero, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKBS (break before first false); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBRKN", Summary: "Break after the first true of the second source",
|
|
Word: 0x25184000, Form: ExtFormPredicateLogicalDest, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKN (break after first true); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBRKNS", Summary: "Break after the first true of the second source, setting the flags",
|
|
Word: 0x25584000, Form: ExtFormPredicateLogicalDest, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKNS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBRKPA", Summary: "Break after the first true, preserving the first source's leading lanes",
|
|
Word: 0x2500c000, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKPA (break propagating after); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBRKPAS", Summary: "Break propagating after the first false, setting the flags",
|
|
Word: 0x2540c000, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKPAS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBRKPB", Summary: "Break propagating before the first true",
|
|
Word: 0x2500c010, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKPB (break propagating before); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PBRKPBS", Summary: "Break propagating before the first false, setting the flags",
|
|
Word: 0x2540c010, Form: ExtFormPredicateLogical, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: PBRKPBS; inst_gen.go + arm64sveenc.s"},
|
|
|
|
// Predicate permutations, SVE2.1.
|
|
{Name: "PTRN1", Summary: "Transpose odd predicate elements",
|
|
Word: 0x05205000, Form: ExtFormPredicatePermute, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: TRN1 (predicates) as PTRN1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PTRN2", Summary: "Transpose even predicate elements",
|
|
Word: 0x05205400, Form: ExtFormPredicatePermute, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: TRN2 (predicates) as PTRN2; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PUZP1", Summary: "Unzip odd predicate elements",
|
|
Word: 0x05204800, Form: ExtFormPredicatePermute, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: UZP1 (predicates) as PUZP1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PUZP2", Summary: "Unzip even predicate elements",
|
|
Word: 0x05204c00, Form: ExtFormPredicatePermute, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: UZP2 (predicates) as PUZP2; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PZIP1", Summary: "Zip odd predicate elements",
|
|
Word: 0x05204000, Form: ExtFormPredicatePermute, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZIP1 (predicates) as PZIP1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PZIP2", Summary: "Zip even predicate elements",
|
|
Word: 0x05204400, Form: ExtFormPredicatePermute, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZIP2 (predicates) as PZIP2; inst_gen.go + arm64sveenc.s"},
|
|
|
|
// Predicate initialise, test and permute singles.
|
|
{Name: "PPFALSE", Summary: "Initialise a predicate to false",
|
|
Word: 0x2518e400, Form: ExtFormPredicateOne, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: PFALSE as PPFALSE; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PPFIRST", Summary: "Set the first active element of a predicate",
|
|
Word: 0x2558c000, Form: ExtFormPredicateFirst, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: PFIRST as PPFIRST; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PPNEXT", Summary: "Set the next active element of a predicate",
|
|
Word: 0x2519c400, Form: ExtFormPredicateNext, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: PNEXT as PPNEXT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PPTEST", Summary: "Test a predicate against a governing predicate, setting the flags",
|
|
Word: 0x2550c000, Form: ExtFormPredicateTest, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: PTEST as PPTEST; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PPTRUE", Summary: "Initialise a predicate-as-counter register from a pattern",
|
|
Word: 0x25207810, Form: ExtFormPredicateCounter, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: PTRUE (counter form) as PPTRUE; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PPUNPKHI", Summary: "Unpack the even elements of a half-word predicate",
|
|
Word: 0x05314000, Form: ExtFormPredicateUnpack, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: PUNPKHI as PPUNPKHI; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PPUNPKLO", Summary: "Unpack the odd elements of a half-word predicate",
|
|
Word: 0x05304000, Form: ExtFormPredicateUnpack, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: PUNPKLO as PPUNPKLO; inst_gen.go + arm64sveenc.s"},
|
|
|
|
// First-fault register and predicate reverse.
|
|
{Name: "PRDFFR", Summary: "Read the first-fault register to a predicate, zeroing",
|
|
Word: 0x2518f000, Form: ExtFormPredicateFFRRead, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: RDFFR (predicated) as PRDFFR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PRDFFR", Summary: "Read the first-fault register to a predicate whole",
|
|
Word: 0x2519f000, Form: ExtFormPredicateOne, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: RDFFR (unpredicated) as PRDFFR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PRDFFRS", Summary: "Read the first-fault register to a predicate, zeroing, setting the flags",
|
|
Word: 0x2558f000, Form: ExtFormPredicateFFRRead, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: RDFFRS as PRDFFRS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWRFFR", Summary: "Write the first-fault register from a predicate",
|
|
Word: 0x25289000, Form: ExtFormPredicateWrite, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: WRFFR as PWRFFR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PREV", Summary: "Reverse the elements of a predicate",
|
|
Word: 0x05344000, Form: ExtFormPredicateMove, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: REV (predicate) as PREV; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "SETFFR", Summary: "Set the first-fault register to all true",
|
|
Word: 0x252c9000, Form: ExtFormNone, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: SETFFR; inst_gen.go + arm64sveenc.s"},
|
|
|
|
// While compares: build a predicate from a scalar loop condition.
|
|
{Name: "PWHILEGE", Summary: "Build a predicate while the signed greater-or-equal comparison holds",
|
|
Word: 0x25201000, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: WHILEGE as PWHILEGE; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWHILEGT", Summary: "Build a predicate while the signed greater comparison holds",
|
|
Word: 0x25201010, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: WHILEGT as PWHILEGT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWHILEHI", Summary: "Build a predicate while the unsigned higher comparison holds",
|
|
Word: 0x25201810, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: WHILEHI as PWHILEHI; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWHILEHS", Summary: "Build a predicate while the unsigned higher-or-same comparison holds",
|
|
Word: 0x25201800, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: WHILEHS as PWHILEHS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWHILELE", Summary: "Build a predicate while the signed less-or-equal comparison holds",
|
|
Word: 0x25201410, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: WHILELE as PWHILELE; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWHILELO", Summary: "Build a predicate while the unsigned lower comparison holds",
|
|
Word: 0x25201c00, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: WHILELO as PWHILELO; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWHILELS", Summary: "Build a predicate while the unsigned lower-or-same comparison holds",
|
|
Word: 0x25201c10, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: WHILELS as PWHILELS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWHILELT", Summary: "Build a predicate while the signed less comparison holds",
|
|
Word: 0x25201400, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: WHILELT as PWHILELT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWHILERW", Summary: "Build a predicate over a read-write region",
|
|
Word: 0x25203010, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: PWHILERW (SVE2.1); inst_gen.go + arm64sveenc.s"},
|
|
{Name: "PWHILEWR", Summary: "Build a predicate over a write region",
|
|
Word: 0x25203000, Form: ExtFormWhile, Size: extSizeBHSD, Feature: ExtFeatureSVE,
|
|
Ref: "ARM DDI 0487J: PWHILEWR (SVE2.1); inst_gen.go + arm64sveenc.s"},
|
|
|
|
// --- the SVE2.1 Z-alias permutations, copies and unary forms -------------
|
|
//
|
|
// The Z-prefixed names are the toolchain corpus spellings of the SVE2.1
|
|
// alias families: the unary and binary predicated forms, the immediate
|
|
// aliases, the vector permutations and selects, and the register-copy
|
|
// forms. Provenance as above: the toolchain encoding table and its
|
|
// generated corpus agree with the manual layouts, and the golden test
|
|
// pins every corpus line of each covered class.
|
|
{Name: "ZABS", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x0416a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZABS; inst_gen.go + arm64sveenc.s"}, {Name: "ZREVB", Summary: "Reverse byte order within elements, predicated",
|
|
Word: 0x05248000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZREVB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREVB", Summary: "Reverse byte order within elements, zeroing",
|
|
Word: 0x0524a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZREVB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREVH", Summary: "Reverse halfword order within elements, predicated",
|
|
Word: 0x05a58000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZREVH; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREVH", Summary: "Reverse halfword order within elements, zeroing",
|
|
Word: 0x05a5a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZREVH; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSXTB", Summary: "Sign-extend bytes to the element width, predicated",
|
|
Word: 0x0410a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZSXTB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSXTB", Summary: "Sign-extend bytes to the element width, zeroing",
|
|
Word: 0x0400a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZSXTB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSXTH", Summary: "Sign-extend halfwords to the element width, predicated",
|
|
Word: 0x0492a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZSXTH; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSXTH", Summary: "Sign-extend halfwords to the element width, zeroing",
|
|
Word: 0x0482a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZSXTH; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUXTB", Summary: "Zero-extend bytes to the element width, predicated",
|
|
Word: 0x0411a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZUXTB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUXTB", Summary: "Zero-extend bytes to the element width, zeroing",
|
|
Word: 0x0401a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZUXTB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUXTH", Summary: "Zero-extend halfwords to the element width, predicated",
|
|
Word: 0x0493a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZUXTH; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUXTH", Summary: "Zero-extend halfwords to the element width, zeroing",
|
|
Word: 0x0483a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1,
|
|
Ref: "ARM DDI 0487J SVE2.1: ZUXTH; inst_gen.go + arm64sveenc.s"},
|
|
|
|
{Name: "ZABS", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x0406a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZABS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZADD", Summary: "Z-alias of the predicated binary form, source copy spelled",
|
|
Word: 0x04000000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZADD; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZADD", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x04200000, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZADD; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZADD", Summary: "Z-alias of the immediate form, destination copy spelled",
|
|
Word: 0x2520c000, Form: ExtFormZImmediateSource, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZADD; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZAND", Summary: "Z-alias of the unpredicated three-vector form, locked to .D",
|
|
Word: 0x04203000, Form: ExtFormVectorsZm, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZAND; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZAND", Summary: "Z-alias of the predicated binary form, source copy spelled",
|
|
Word: 0x041a0000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZAND; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZBIC", Summary: "Z-alias of the unpredicated three-vector form, locked to .D",
|
|
Word: 0x04e03000, Form: ExtFormVectorsZm, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZBIC; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZBIC", Summary: "Z-alias of the predicated binary form, source copy spelled",
|
|
Word: 0x041b0000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZBIC; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZCLS", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x0418a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCLS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZCLS", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x0408a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCLS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZCLZ", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x0419a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCLZ; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZCLZ", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x0409a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCLZ; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZCNT", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x041aa000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCNT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZCNT", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x040aa000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCNT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZCOMPACT", Summary: "Compact or expand over a governing predicate",
|
|
Word: 0x05218000, Form: ExtFormZGov, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZCOMPACT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZDUP", Summary: "Copy or insert a general register, .D locked",
|
|
Word: 0x05e03800, Form: ExtFormZFromGeneral, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZDUP; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZEOR", Summary: "Z-alias of the unpredicated three-vector form, locked to .D",
|
|
Word: 0x04a03000, Form: ExtFormVectorsZm, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZEOR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZEOR", Summary: "Z-alias of the predicated binary form, source copy spelled",
|
|
Word: 0x04190000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZEOR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZEXPAND", Summary: "Compact or expand over a governing predicate",
|
|
Word: 0x05318000, Form: ExtFormZGov, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZEXPAND; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZINSR", Summary: "Copy or insert a general register, .D locked",
|
|
Word: 0x05e43800, Form: ExtFormZFromGeneral, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZINSR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZLASTA", Summary: "Last active element into a register, .D locked",
|
|
Word: 0x05e0a000, Form: ExtFormZLastReg, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZLASTA; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZLASTB", Summary: "Last active element into a register, .D locked",
|
|
Word: 0x05e1a000, Form: ExtFormZLastReg, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZLASTB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZMOVPRFX", Summary: "Z-alias of the predicated form, either qualifier, one encoding",
|
|
Word: 0x04102000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualAny, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZMOVPRFX; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREVD", Summary: "Reverse the order of quadwords, zeroing",
|
|
Word: 0x052ea000, Form: ExtFormZUnary, PgQual: ExtQualZeroing, Arr: ExtArrQ, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZREVD; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREVW", Summary: "Reverse word order within doublewords, zeroing",
|
|
Word: 0x05e6a000, Form: ExtFormZUnary, PgQual: ExtQualZeroing, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZREVW; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSXTW", Summary: "Sign-extend words to doublewords, zeroing",
|
|
Word: 0x04c4a000, Form: ExtFormZUnary, PgQual: ExtQualZeroing, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSXTW; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUXTW", Summary: "Zero-extend words to doublewords, zeroing",
|
|
Word: 0x04c5a000, Form: ExtFormZUnary, PgQual: ExtQualZeroing, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUXTW; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZMOVPRFX", Summary: "MOVPRFX prefix spelling without arrangements",
|
|
Word: 0x0420bc00, Form: ExtFormZMoveBare, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZMOVPRFX; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZNEG", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x0417a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZNEG; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZNEG", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x0407a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZNEG; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZNOT", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x041ea000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZNOT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZNOT", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x040ea000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZNOT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZORR", Summary: "Z-alias of the unpredicated three-vector form, locked to .D",
|
|
Word: 0x04603000, Form: ExtFormVectorsZm, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZORR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZORR", Summary: "Z-alias of the predicated binary form, source copy spelled",
|
|
Word: 0x04180000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZORR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZRBIT", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x05278000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZRBIT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZRBIT", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x0527a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZRBIT; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREV", Summary: "Reverse the elements of a vector",
|
|
Word: 0x05383800, Form: ExtFormZMove, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZREV; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREVD", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x052e8000, Form: ExtFormZUnary, PgQual: ExtQualMerging, Arr: ExtArrQ, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZREVD; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREVD", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x052ea000, Form: ExtFormZUnary, PgQual: ExtQualZeroing, Arr: ExtArrQ, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZREVD; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREVW", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x05e68000, Form: ExtFormZUnary, PgQual: ExtQualMerging, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZREVW; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZREVW", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x05e6a000, Form: ExtFormZUnary, PgQual: ExtQualZeroing, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZREVW; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSEL", Summary: "Select vector elements by a predicate",
|
|
Word: 0x0520c000, Form: ExtFormZSelect, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSEL; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSQABS", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x4408a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSQABS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSQABS", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x440aa000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSQABS; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSQNEG", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x4409a000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSQNEG; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSQNEG", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x440ba000, Form: ExtFormZUnary, Size: extSizeBHSD, PgQual: ExtQualZeroing, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSQNEG; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSUB", Summary: "Z-alias of the predicated binary form, source copy spelled",
|
|
Word: 0x04010000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSUB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSUB", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x04200400, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSUB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSUB", Summary: "Z-alias of the immediate form, destination copy spelled",
|
|
Word: 0x2521c000, Form: ExtFormZImmediateSource, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSUB; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSUBR", Summary: "Z-alias of the predicated binary form, source copy spelled",
|
|
Word: 0x04030000, Form: ExtFormZPredicatedSource, Size: extSizeBHSD, PgQual: ExtQualMerging, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSUBR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSUBR", Summary: "Z-alias of the immediate form, destination copy spelled",
|
|
Word: 0x2523c000, Form: ExtFormZImmediateSource, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSUBR; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSUNPKHI", Summary: "Unpack a byte vector into a wider one",
|
|
Word: 0x05313800, Form: ExtFormZUnpack, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSUNPKHI; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSUNPKLO", Summary: "Unpack a byte vector into a wider one",
|
|
Word: 0x05303800, Form: ExtFormZUnpack, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSUNPKLO; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSXTW", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x04d4a000, Form: ExtFormZUnary, PgQual: ExtQualMerging, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSXTW; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZSXTW", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x04c4a000, Form: ExtFormZUnary, PgQual: ExtQualZeroing, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZSXTW; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZTBX", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x05202c00, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZTBX; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZTBXQ", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x05203400, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZTBXQ; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZTRN1", Summary: "Z-alias of the unpredicated three-vector form, locked to .Q",
|
|
Word: 0x05a01800, Form: ExtFormVectorsZm, Arr: ExtArrQ, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZTRN1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZTRN1", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x05207000, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZTRN1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZTRN2", Summary: "Z-alias of the unpredicated three-vector form, locked to .Q",
|
|
Word: 0x05a01c00, Form: ExtFormVectorsZm, Arr: ExtArrQ, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZTRN2; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZTRN2", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x05207400, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZTRN2; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUUNPKHI", Summary: "Unpack a byte vector into a wider one",
|
|
Word: 0x05333800, Form: ExtFormZUnpack, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUUNPKHI; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUUNPKLO", Summary: "Unpack a byte vector into a wider one",
|
|
Word: 0x05323800, Form: ExtFormZUnpack, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUUNPKLO; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUXTW", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x04d5a000, Form: ExtFormZUnary, PgQual: ExtQualMerging, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUXTW; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUXTW", Summary: "Z-alias of the predicated form, over a governing predicate",
|
|
Word: 0x04c5a000, Form: ExtFormZUnary, PgQual: ExtQualZeroing, Arr: ExtArrD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUXTW; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUZP1", Summary: "Z-alias of the unpredicated three-vector form, locked to .Q",
|
|
Word: 0x05a00800, Form: ExtFormVectorsZm, Arr: ExtArrQ, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUZP1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUZP1", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x05206800, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUZP1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUZP2", Summary: "Z-alias of the unpredicated three-vector form, locked to .Q",
|
|
Word: 0x05a00c00, Form: ExtFormVectorsZm, Arr: ExtArrQ, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUZP2; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUZP2", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x05206c00, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUZP2; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUZPQ1", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x4400e800, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUZPQ1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZUZPQ2", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x4400ec00, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZUZPQ2; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZZIP1", Summary: "Z-alias of the unpredicated three-vector form, locked to .Q",
|
|
Word: 0x05a00000, Form: ExtFormVectorsZm, Arr: ExtArrQ, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZZIP1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZZIP1", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x05206000, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZZIP1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZZIP2", Summary: "Z-alias of the unpredicated three-vector form, locked to .Q",
|
|
Word: 0x05a00400, Form: ExtFormVectorsZm, Arr: ExtArrQ, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZZIP2; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZZIP2", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x05206400, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZZIP2; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZZIPQ1", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x4400e000, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZZIPQ1; inst_gen.go + arm64sveenc.s"},
|
|
{Name: "ZZIPQ2", Summary: "Z-alias of the unpredicated three-vector form",
|
|
Word: 0x4400e400, Form: ExtFormVectorsZm, Size: extSizeBHSD, Feature: ExtFeatureSVE2p1, Ref: "ARM DDI 0487J SVE2.1: ZZIPQ2; inst_gen.go + arm64sveenc.s"},
|
|
}
|
|
|
|
// Extensions returns the extended-instruction layer registered for a, outside
|
|
// the generated tables. An architecture whose extended layer is not built
|
|
// yet returns nothing: the mechanism is ordinary code, not a build tag, and
|
|
// it simply offers no instruction where none is registered.
|
|
func Extensions(a Arch) []ExtInstr {
|
|
switch a {
|
|
case AMD64:
|
|
return amd64Extensions
|
|
case ARM64:
|
|
return arm64Extensions
|
|
default:
|
|
return nil
|
|
}
|
|
}
|