rexcode/arm32: operands that no field carries, and three forms with the wrong shape

VSHLL's widest form shifts by exactly the element size. No field holds
that amount -- the size is a fixed bit of the form, so the shift is too
-- and the form printed no shift at all, which reads as a different
instruction. VCADD and VCMLA name their rotation in degrees, 90 and 270
for one and all four quadrants for the other; both printed the raw
field, so every rotation read as `#0`. VSEL is an unconditional word
that still names a condition, in bits 21:20 and spelled on the
mnemonic; it printed a bare `#0` operand instead and no condition. Only
four conditions can be named and not in their usual order, so they get
a small table.

The shift amount had five bits, which cannot hold 32 -- the amount LSR
and ASR reach through a zero field. It silently wrapped back to zero,
which is why the previous commit's fix for those did not take. Memory
had a spare bit and the register operand had two.

Three forms were shaped wrong outright. VDUP from a GPR puts Vd in bits
19:16 with D at bit 7, not where NEON usually puts it, so it named a
register sixteen too high. VCVTA, VCVTN, VCVTP and VCVTM to a 32-bit
integer land in an S register whatever the source width, and the F64
forms had them landing in a D. VFMAL and VFMSL multiply pairs of
half-precision values, so their sources are half the width of the
destination -- S registers into a D, D registers into a Q -- and they
carried no data type at all. VJCVT likewise: it converts F64 to a
signed 32-bit integer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018UmHLRF11EoWwNWCJ7JGaA
This commit is contained in:
Brendan Punsky
2026-08-29 00:46:58 -04:00
committed by Flāvius
parent 9964798390
commit fae03b995c
10 changed files with 111 additions and 88 deletions

View File

@@ -157,7 +157,10 @@ find_and_decode :: proc(word: u32, mode: Mode, ilen: u32, inst: ^Instruction, in
inst.dt = e.dt
// Cond: A32 entries with bits[31:28] variable in mask take cond from word
if mode == .A32 && (e.mask >> 28) == 0 {
if e.flags.cond_in_21 {
// Four conditions only, and not in their usual order.
inst.cond = VSEL_CONDITIONS[(word >> 20) & 3]
} else if mode == .A32 && (e.mask >> 28) == 0 {
inst.cond = u8((word >> 28) & 0xF)
} else {
inst.cond = 14 // AL / unconditional
@@ -547,6 +550,11 @@ unpack_operand :: proc(word: u32, enc: Operand_Encoding, ot: Operand_Type) -> Op
return op_imm(i64((word >> 18) & 0xF))
// ---- Saturate / bit field ----
case .NEON_SHLL_8: return op_imm(8)
case .NEON_SHLL_16: return op_imm(16)
case .NEON_SHLL_32: return op_imm(32)
case .NEON_ROT_2: return op_imm(((word >> 24) & 1) != 0 ? 270 : 90)
case .NEON_ROT_4: return op_imm(i64(((word >> 20) & 3) * 90))
case .VFP_FBITS:
// The fixed-point width is 16 or 32 by the sx bit, and the fraction
// is that less imm4:i -- so the widest fraction encodes as zero.
@@ -678,6 +686,10 @@ table_run_length :: #force_inline proc "contextless" (e: Operand_Encoding) -> u8
return 1
}
// The conditions VSEL can name, in the order bits 21:20 give them.
@(private="file")
VSEL_CONDITIONS := [4]u8{0, 6, 10, 12} // EQ, VS, GE, GT
// Typical-case estimate of the instruction count for `data`.
@(require_results)
decode_estimate_instruction_count :: #force_inline proc "contextless" (data: []u8) -> int {

View File

@@ -661,6 +661,12 @@ pack_operand_inline :: #force_inline proc(
case .IT_MASK: return u32(op.immediate) & 0xFF
case .CPS_IFLAGS: return u32(op.immediate) & 0x1FF
case .HINT_FIELD: return u32(op.immediate) & 0xFF
case .NEON_SHLL_8, .NEON_SHLL_16, .NEON_SHLL_32:
return 0 // the amount is the form's element size; no field carries it
case .NEON_ROT_2:
return (op.immediate == 270 ? u32(1) : 0) << 24
case .NEON_ROT_4:
return ((u32(op.immediate) / 90) & 3) << 20
case .VFP_FBITS:
// sx is a fixed bit of the form, so the width comes from its pattern.
width: u32 = ((form.bits >> 7) & 1) != 0 ? 32 : 16

View File

@@ -156,7 +156,9 @@ Encoding_Flags :: bit_field u8 {
writes_pc: bool | 1,
thumb32: bool | 1, // T32 32-bit form (vs 16-bit). Ignored for A32.
deprecated: bool | 1,
_: u8 | 1,
// VSEL and friends are unconditional words that still name a condition,
// in bits 21:20 rather than 31:28, and spell it on the mnemonic.
cond_in_21: bool | 1,
}
// ---- Operand types ----------------------------------------------------------
@@ -412,6 +414,12 @@ Operand_Encoding :: enum u8 {
// ---- Saturate ----
VFP_FBITS, // VCVT fixed-point fraction bits: width - (imm4:i)
// VSHLL's widest form shifts by exactly the element size, which no field
// carries -- the size is a fixed bit of the form, so the amount is too.
NEON_SHLL_8, NEON_SHLL_16, NEON_SHLL_32,
// Complex-arithmetic rotations, named in degrees. VCADD has two, in bit
// 24; VCMLA has four, in bits 21:20.
NEON_ROT_2, NEON_ROT_4,
SAT_IMM5, // bits 20-16: SSAT/SSAT16 saturate-to width, less one
SAT_IMM5_T32, // Thumb-2 signed saturate amount, less one
SAT_IMM5_U, // bits 20-16: USAT/USAT16 width, which is not biased

View File

@@ -758,8 +758,8 @@ inst_vpush_slist :: #force_inline proc "contextless" (regs: u16) -> In
emit_vpush_slist :: #force_inline proc(instructions: ^[dynamic]Instruction, regs: u16) { append(instructions, inst_vpush_slist(regs)) }
inst_vpop_slist :: #force_inline proc "contextless" (regs: u16) -> Instruction { return Instruction{mnemonic = .VPOP, operand_count = 1, mode = .A32, cond = 14, length = 4, ops = {op_reg_list(regs), {}, {}, {}}} }
emit_vpop_slist :: #force_inline proc(instructions: ^[dynamic]Instruction, regs: u16) { append(instructions, inst_vpop_slist(regs)) }
inst_vsel_s_s_s_cond :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .VSEL, operand_count = 4, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), op_imm(imm)}} }
emit_vsel_s_s_s_cond :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register, imm: i64) { append(instructions, inst_vsel_s_s_s_cond(dst, src, src2, imm)) }
inst_vsel_s_s_s :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .VSEL, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
emit_vsel_s_s_s :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register) { append(instructions, inst_vsel_s_s_s(dst, src, src2)) }
inst_vmaxnm_s_s_s :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .VMAXNM, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
emit_vmaxnm_s_s_s :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register) { append(instructions, inst_vmaxnm_s_s_s(dst, src, src2)) }
inst_vminnm_s_s_s :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .VMINNM, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
@@ -959,9 +959,7 @@ emit_vshrn_d_q_imm :: #force_inline proc(instructions: ^[dynamic]Instruc
inst_vrshrn_d_q_imm :: #force_inline proc "contextless" (dst: Register, src: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .VRSHRN, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_imm(imm), {}}} }
emit_vrshrn_d_q_imm :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, imm: i64) { append(instructions, inst_vrshrn_d_q_imm(dst, src, imm)) }
inst_vshll_q_d_imm :: #force_inline proc "contextless" (dst: Register, src: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .VSHLL, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_imm(imm), {}}} }
inst_vshll_q_d :: #force_inline proc "contextless" (dst: Register, src: Register) -> Instruction { return Instruction{mnemonic = .VSHLL, operand_count = 2, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), {}, {}}} }
emit_vshll_q_d_imm :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, imm: i64) { append(instructions, inst_vshll_q_d_imm(dst, src, imm)) }
emit_vshll_q_d :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register) { append(instructions, inst_vshll_q_d(dst, src)) }
inst_vcls_d_d :: #force_inline proc "contextless" (dst: Register, src: Register) -> Instruction { return Instruction{mnemonic = .VCLS, operand_count = 2, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), {}, {}}} }
emit_vcls_d_d :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register) { append(instructions, inst_vcls_d_d(dst, src)) }
inst_vclz_d_d :: #force_inline proc "contextless" (dst: Register, src: Register) -> Instruction { return Instruction{mnemonic = .VCLZ, operand_count = 2, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), {}, {}}} }
@@ -1054,10 +1052,10 @@ inst_vdot_d_d_d :: #force_inline proc "contextless" (dst: Register, s
emit_vdot_d_d_d :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register) { append(instructions, inst_vdot_d_d_d(dst, src, src2)) }
inst_vmmla_q_q_q :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .VMMLA, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
emit_vmmla_q_q_q :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register) { append(instructions, inst_vmmla_q_q_q(dst, src, src2)) }
inst_vfmal_d_d_d :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .VFMAL, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
emit_vfmal_d_d_d :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register) { append(instructions, inst_vfmal_d_d_d(dst, src, src2)) }
inst_vfmsl_d_d_d :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .VFMSL, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
emit_vfmsl_d_d_d :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register) { append(instructions, inst_vfmsl_d_d_d(dst, src, src2)) }
inst_vfmal_d_s_s :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .VFMAL, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
emit_vfmal_d_s_s :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register) { append(instructions, inst_vfmal_d_s_s(dst, src, src2)) }
inst_vfmsl_d_s_s :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register) -> Instruction { return Instruction{mnemonic = .VFMSL, operand_count = 3, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), {}}} }
emit_vfmsl_d_s_s :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register) { append(instructions, inst_vfmsl_d_s_s(dst, src, src2)) }
inst_vcmla_d_d_d_imm :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register, imm: i64) -> Instruction { return Instruction{mnemonic = .VCMLA, operand_count = 4, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_reg(src2), op_imm(imm)}} }
inst_vcmla_d_d_dlane_imm :: #force_inline proc "contextless" (dst: Register, src: Register, src2: Register, lane: u8, imm: i64) -> Instruction { return Instruction{mnemonic = .VCMLA, operand_count = 4, mode = .A32, cond = 14, length = 4, ops = {op_reg(dst), op_reg(src), op_dpr_lane(src2, lane), op_imm(imm)}} }
emit_vcmla_d_d_d_imm :: #force_inline proc(instructions: ^[dynamic]Instruction, dst: Register, src: Register, src2: Register, imm: i64) { append(instructions, inst_vcmla_d_d_d_imm(dst, src, src2, imm)) }
@@ -2001,8 +1999,8 @@ inst_vpush :: inst_vpush_slist
emit_vpush :: emit_vpush_slist
inst_vpop :: inst_vpop_slist
emit_vpop :: emit_vpop_slist
inst_vsel :: inst_vsel_s_s_s_cond
emit_vsel :: emit_vsel_s_s_s_cond
inst_vsel :: inst_vsel_s_s_s
emit_vsel :: emit_vsel_s_s_s
inst_vmaxnm :: inst_vmaxnm_s_s_s
emit_vmaxnm :: emit_vmaxnm_s_s_s
inst_vminnm :: inst_vminnm_s_s_s
@@ -2167,8 +2165,8 @@ inst_vshrn :: inst_vshrn_d_q_imm
emit_vshrn :: emit_vshrn_d_q_imm
inst_vrshrn :: inst_vrshrn_d_q_imm
emit_vrshrn :: emit_vrshrn_d_q_imm
inst_vshll :: proc{ inst_vshll_q_d_imm, inst_vshll_q_d }
emit_vshll :: proc{ emit_vshll_q_d_imm, emit_vshll_q_d }
inst_vshll :: inst_vshll_q_d_imm
emit_vshll :: emit_vshll_q_d_imm
inst_vcls :: inst_vcls_d_d
emit_vcls :: emit_vcls_d_d
inst_vclz :: inst_vclz_d_d
@@ -2251,10 +2249,10 @@ inst_vdot :: inst_vdot_d_d_d
emit_vdot :: emit_vdot_d_d_d
inst_vmmla :: inst_vmmla_q_q_q
emit_vmmla :: emit_vmmla_q_q_q
inst_vfmal :: inst_vfmal_d_d_d
emit_vfmal :: emit_vfmal_d_d_d
inst_vfmsl :: inst_vfmsl_d_d_d
emit_vfmsl :: emit_vfmsl_d_d_d
inst_vfmal :: inst_vfmal_d_s_s
emit_vfmal :: emit_vfmal_d_s_s
inst_vfmsl :: inst_vfmsl_d_s_s
emit_vfmsl :: emit_vfmsl_d_s_s
inst_vcmla :: proc{ inst_vcmla_d_d_d_imm, inst_vcmla_d_d_dlane_imm }
emit_vcmla :: proc{ emit_vcmla_d_d_d_imm, emit_vcmla_d_d_dlane_imm }
inst_vcadd :: inst_vcadd_d_d_d_imm

View File

@@ -69,11 +69,10 @@ Memory :: bit_field u64 {
base: Register | 15, // GPR base register
index: Register | 15, // GPR, or Register(0) for imm-only forms
shift_type: Shift_Type | 4,
shift_amt: u8 | 5, // 0..31 immediate shift
shift_amt: u8 | 6, // 0..32 -- LSR and ASR reach 32 through a zero field
mode: Index_Mode | 2,
sign: i8 | 3, // +1 or -1 (U bit)
disp: i32 | 19, // immediate displacement (sign-extended)
// 1 bit spare
}
#assert(size_of(Memory) == 8)
@@ -112,12 +111,12 @@ Operand :: struct #packed {
using _: bit_field u32 {
reg: Register | 15,
shift_type: Shift_Type | 4, // GPR_SHIFTED; .LSL/0 when plain
shift_amt: u8 | 5, // 0..31, or the Rs index for RSR
shift_amt: u8 | 6, // 0..32, or the Rs index for RSR
lane: u8 | 5, // SIMD lane for DPR_ELEM / QPR_ELEM
// Whether `lane` means anything. Lane 0 is a real index -- `d0[0]`
// is not `d0` -- so it cannot be spelled by lane == 0.
has_lane: bool | 1,
// 2 bits spare
// 1 bit spare
},
mem: Memory,
immediate: i64,

View File

@@ -1588,19 +1588,19 @@ ENCODING_TABLE := #partial [Mnemonic][]Encoding{
// ARMv8: VCVTA/N/P/M (rounding-mode FP-to-int) - cond=1111 (unconditional class)
.VCVTA = {
{.VCVTA, {.SPR, .SPR, .NONE, .NONE}, {.VD_S, .VM_S, .NONE, .NONE}, 0xFEBC0A40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F32}},
{.VCVTA, {.DPR, .DPR, .NONE, .NONE}, {.VD_D, .VM_D, .NONE, .NONE}, 0xFEBC0B40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F64}},
{.VCVTA, {.SPR, .DPR, .NONE, .NONE}, {.VD_S, .VM_D, .NONE, .NONE}, 0xFEBC0B40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F64}},
},
.VCVTN = {
{.VCVTN, {.SPR, .SPR, .NONE, .NONE}, {.VD_S, .VM_S, .NONE, .NONE}, 0xFEBD0A40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F32}},
{.VCVTN, {.DPR, .DPR, .NONE, .NONE}, {.VD_D, .VM_D, .NONE, .NONE}, 0xFEBD0B40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F64}},
{.VCVTN, {.SPR, .DPR, .NONE, .NONE}, {.VD_S, .VM_D, .NONE, .NONE}, 0xFEBD0B40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F64}},
},
.VCVTP = {
{.VCVTP, {.SPR, .SPR, .NONE, .NONE}, {.VD_S, .VM_S, .NONE, .NONE}, 0xFEBE0A40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F32}},
{.VCVTP, {.DPR, .DPR, .NONE, .NONE}, {.VD_D, .VM_D, .NONE, .NONE}, 0xFEBE0B40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F64}},
{.VCVTP, {.SPR, .DPR, .NONE, .NONE}, {.VD_S, .VM_D, .NONE, .NONE}, 0xFEBE0B40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F64}},
},
.VCVTM = {
{.VCVTM, {.SPR, .SPR, .NONE, .NONE}, {.VD_S, .VM_S, .NONE, .NONE}, 0xFEBF0A40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F32}},
{.VCVTM, {.DPR, .DPR, .NONE, .NONE}, {.VD_D, .VM_D, .NONE, .NONE}, 0xFEBF0B40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F64}},
{.VCVTM, {.SPR, .DPR, .NONE, .NONE}, {.VD_S, .VM_D, .NONE, .NONE}, 0xFEBF0B40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.U32, .F64}},
},
// VMRS / VMSR (access FPSCR + friends as GPR)
@@ -1648,8 +1648,8 @@ ENCODING_TABLE := #partial [Mnemonic][]Encoding{
},
.VSEL = {
// VSEL<cond>.F32/F64 Sd, Sn, Sm -- cond field at bits 21-20 + 7
{.VSEL, {.SPR, .SPR, .SPR, .COND}, {.VD_S, .VN_S, .VM_S, .NONE}, 0xFE000A00, 0xFF800F50, .V8, .A32, {cond_in_28=false}, {.F32, .NONE}},
{.VSEL, {.DPR, .DPR, .DPR, .COND}, {.VD_D, .VN_D, .VM_D, .NONE}, 0xFE000B00, 0xFF800F50, .V8, .A32, {cond_in_28=false}, {.F64, .NONE}},
{.VSEL, {.SPR, .SPR, .SPR, .NONE}, {.VD_S, .VN_S, .VM_S, .NONE}, 0xFE000A00, 0xFF800F50, .V8, .A32, {cond_in_28=false, cond_in_21=true}, {.F32, .NONE}},
{.VSEL, {.DPR, .DPR, .DPR, .NONE}, {.VD_D, .VN_D, .VM_D, .NONE}, 0xFE000B00, 0xFF800F50, .V8, .A32, {cond_in_28=false, cond_in_21=true}, {.F64, .NONE}},
},
.VRINTA = {
{.VRINTA, {.SPR, .SPR, .NONE, .NONE}, {.VD_S, .VM_S, .NONE, .NONE}, 0xFEB80A40, 0xFFBF0FD0, .V8, .A32, {cond_in_28=false}, {.F32, .NONE}},
@@ -1692,7 +1692,7 @@ ENCODING_TABLE := #partial [Mnemonic][]Encoding{
{.VRINTX, {.QPR, .QPR, .NONE, .NONE}, {.VD_Q, .VM_Q, .NONE, .NONE}, 0xFFBA04C0, 0xFFBB0FD1, .MVE_FP, .T32, {thumb32=true, cond_in_28=false}, {.F32, .NONE}},
},
// VJCVT (ARMv8.3): F64 -> S32 with JS-style rounding
.VJCVT = { {.VJCVT, {.SPR, .DPR, .NONE, .NONE}, {.VD_S, .VM_D, .NONE, .NONE}, 0x0EB90BC0, 0x0FBF0FD0, .V8, .A32, {}, {}} },
.VJCVT = { {.VJCVT, {.SPR, .DPR, .NONE, .NONE}, {.VD_S, .VM_D, .NONE, .NONE}, 0x0EB90BC0, 0x0FBF0FD0, .V8, .A32, {}, {.S32, .F64}} },
// ---- VFP F16 scalar arithmetic (FEAT_FP16) ----
// Uses coproc 9 (cp_num = 1001) instead of 10/11 used by F32/F64.
@@ -2233,8 +2233,8 @@ ENCODING_TABLE := #partial [Mnemonic][]Encoding{
// Variant: vector D[lane] form (1111 0011 1011 imm4 Vd 1100 0 Q M 0 Vm)
// We list the common scalar/Rt form for V_8B/V_16B/V_4H/V_8H/V_2S/V_4S.
// (encoder picks based on operand kinds)
{.VDUP, {.DPR, .GPR, .NONE, .NONE}, {.VD_D, .RT_A32, .NONE, .NONE}, 0x0EC00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8, .NONE}},
{.VDUP, {.QPR, .GPR, .NONE, .NONE}, {.VD_Q, .RT_A32, .NONE, .NONE}, 0x0EE00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8, .NONE}},
{.VDUP, {.DPR, .GPR, .NONE, .NONE}, {.VN_D, .RT_A32, .NONE, .NONE}, 0x0EC00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8, .NONE}},
{.VDUP, {.QPR, .GPR, .NONE, .NONE}, {.VN_Q, .RT_A32, .NONE, .NONE}, 0x0EE00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8, .NONE}},
// VDUP from vector lane (.D form): 1111 0011 1011 imm4 Vd 1100 0 Q M 0 Vm
{.VDUP, {.DPR, .DPR_ELEM, .NONE, .NONE}, {.VD_D, .NEON_VM_SCALAR_32, .NONE, .NONE}, 0xF3B00C00, 0xFFB00FD0, .NEON, .A32, {cond_in_28=false}, {}},
{.VDUP, {.QPR, .DPR_ELEM, .NONE, .NONE}, {.VD_Q, .NEON_VM_SCALAR_32, .NONE, .NONE}, 0xF3B00C40, 0xFFB00FD0, .NEON, .A32, {cond_in_28=false}, {}},
@@ -2548,9 +2548,9 @@ ENCODING_TABLE := #partial [Mnemonic][]Encoding{
// imm6 encodes sh + size: 001sss for sh<8, 01sss for sh<16, 1sss for sh<32
{.VSHLL, {.QPR, .DPR, .IMM, .NONE}, {.VD_Q, .VM_D, .NEON_SHIFT_IMM6, .NONE}, 0xF2800A10, 0xFE800FD0, .NEON, .A32, {cond_in_28=false}, {.I16, .NONE}},
// VSHLL by max (#size) variant: 1111 0011 1 D 11 size 10 Vd 0011 0 0 M 0 Vm
{.VSHLL, {.QPR, .DPR, .NONE, .NONE}, {.VD_Q, .VM_D, .NONE, .NONE}, 0xF3B20300, 0xFFBF0FD0, .NEON, .A32, {cond_in_28=false}, {.I8, .NONE}},
{.VSHLL, {.QPR, .DPR, .NONE, .NONE}, {.VD_Q, .VM_D, .NONE, .NONE}, 0xF3B60300, 0xFFBF0FD0, .NEON, .A32, {cond_in_28=false}, {.I16, .NONE}},
{.VSHLL, {.QPR, .DPR, .NONE, .NONE}, {.VD_Q, .VM_D, .NONE, .NONE}, 0xF3BA0300, 0xFFBF0FD0, .NEON, .A32, {cond_in_28=false}, {.I32, .NONE}},
{.VSHLL, {.QPR, .DPR, .IMM, .NONE}, {.VD_Q, .VM_D, .NEON_SHLL_8, .NONE}, 0xF3B20300, 0xFFBF0FD0, .NEON, .A32, {cond_in_28=false}, {.I8, .NONE}},
{.VSHLL, {.QPR, .DPR, .IMM, .NONE}, {.VD_Q, .VM_D, .NEON_SHLL_16, .NONE}, 0xF3B60300, 0xFFBF0FD0, .NEON, .A32, {cond_in_28=false}, {.I16, .NONE}},
{.VSHLL, {.QPR, .DPR, .IMM, .NONE}, {.VD_Q, .VM_D, .NEON_SHLL_32, .NONE}, 0xF3BA0300, 0xFFBF0FD0, .NEON, .A32, {cond_in_28=false}, {.I32, .NONE}},
},
.VSHRN = {
// 1111 0010 1 D imm6 Vd 1000 0 0 M 1 Vm
@@ -2753,26 +2753,26 @@ ENCODING_TABLE := #partial [Mnemonic][]Encoding{
// VCADD: rotation in bit 24 only (2 values: 90, 270 deg)
.VCMLA = {
// Mask 0xFC800F10 leaves bits 24:23 variable for rotation operand
{.VCMLA, {.DPR, .DPR, .DPR, .IMM}, {.VD_D, .VN_D, .VM_D, .NONE}, 0xFC200800, 0xFC800F10, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCMLA, {.QPR, .QPR, .QPR, .IMM}, {.VD_Q, .VN_Q, .VM_Q, .NONE}, 0xFC200840, 0xFC800F50, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCMLA, {.DPR, .DPR, .DPR_ELEM, .IMM}, {.VD_D, .VN_D, .NEON_VM_SCALAR_32, .NONE}, 0xFE000800, 0xFFB00F10, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCMLA, {.QPR, .QPR, .DPR_ELEM, .IMM}, {.VD_Q, .VN_Q, .NEON_VM_SCALAR_32, .NONE}, 0xFE000840, 0xFFB00F50, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCMLA, {.DPR, .DPR, .DPR, .IMM}, {.VD_D, .VN_D, .VM_D, .NEON_ROT_4}, 0xFC200800, 0xFC800F10, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCMLA, {.QPR, .QPR, .QPR, .IMM}, {.VD_Q, .VN_Q, .VM_Q, .NEON_ROT_4}, 0xFC200840, 0xFC800F50, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCMLA, {.DPR, .DPR, .DPR_ELEM, .IMM}, {.VD_D, .VN_D, .NEON_VM_SCALAR_32, .NEON_ROT_4}, 0xFE000800, 0xFFB00F10, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCMLA, {.QPR, .QPR, .DPR_ELEM, .IMM}, {.VD_Q, .VN_Q, .NEON_VM_SCALAR_32, .NEON_ROT_4}, 0xFE000840, 0xFFB00F50, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCMLA, {.QPR, .QPR, .QPR, .IMM}, {.VD_Q, .VN_Q, .VM_Q, .MVE_ROT_CMLA}, 0xFC200840, 0xFE611FF1, .MVE_FP, .T32, {thumb32=true, cond_in_28=false}, {.F16, .NONE}},
},
.VCADD = {
// Mask 0xFE800F10 leaves bit 24 variable for rotation operand (90 or 270)
{.VCADD, {.DPR, .DPR, .DPR, .IMM}, {.VD_D, .VN_D, .VM_D, .NONE}, 0xFC800800, 0xFE800F10, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCADD, {.QPR, .QPR, .QPR, .IMM}, {.VD_Q, .VN_Q, .VM_Q, .NONE}, 0xFC800840, 0xFE800F50, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCADD, {.DPR, .DPR, .DPR, .IMM}, {.VD_D, .VN_D, .VM_D, .NEON_ROT_2}, 0xFC800800, 0xFE800F10, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VCADD, {.QPR, .QPR, .QPR, .IMM}, {.VD_Q, .VN_Q, .VM_Q, .NEON_ROT_2}, 0xFC800840, 0xFE800F50, .FCMA, .A32, {cond_in_28=false}, {.F16, .NONE}},
},
// FEAT_FHM (ARMv8.2): FP16 fused multiply-add long
.VFMAL = {
{.VFMAL, {.DPR, .DPR, .DPR, .NONE}, {.VD_D, .VN_D, .VM_D, .NONE}, 0xFC200810, 0xFFB00F10, .FHM, .A32, {cond_in_28=false}, {}},
{.VFMAL, {.QPR, .QPR, .QPR, .NONE}, {.VD_Q, .VN_Q, .VM_Q, .NONE}, 0xFC200850, 0xFFB00F50, .FHM, .A32, {cond_in_28=false}, {}},
{.VFMAL, {.DPR, .SPR, .SPR, .NONE}, {.VD_D, .VN_S, .VM_S, .NONE}, 0xFC200810, 0xFFB00F10, .FHM, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VFMAL, {.QPR, .DPR, .DPR, .NONE}, {.VD_Q, .VN_D, .VM_D, .NONE}, 0xFC200850, 0xFFB00F50, .FHM, .A32, {cond_in_28=false}, {.F16, .NONE}},
},
.VFMSL = {
{.VFMSL, {.DPR, .DPR, .DPR, .NONE}, {.VD_D, .VN_D, .VM_D, .NONE}, 0xFCA00810, 0xFFB00F10, .FHM, .A32, {cond_in_28=false}, {}},
{.VFMSL, {.QPR, .QPR, .QPR, .NONE}, {.VD_Q, .VN_Q, .VM_Q, .NONE}, 0xFCA00850, 0xFFB00F50, .FHM, .A32, {cond_in_28=false}, {}},
{.VFMSL, {.DPR, .SPR, .SPR, .NONE}, {.VD_D, .VN_S, .VM_S, .NONE}, 0xFCA00810, 0xFFB00F10, .FHM, .A32, {cond_in_28=false}, {.F16, .NONE}},
{.VFMSL, {.QPR, .DPR, .DPR, .NONE}, {.VD_Q, .VN_D, .VM_D, .NONE}, 0xFCA00850, 0xFFB00F50, .FHM, .A32, {cond_in_28=false}, {.F16, .NONE}},
},
// FEAT_BF16 (ARMv8.6): BFloat16 arithmetic and conversion

View File

@@ -723,9 +723,9 @@ DECODE_ENTRIES := [1663]lib.Decode_Entry{
{ .VRSQRTE, {.QPR,.QPR,.NONE,.NONE}, {.VD_Q,.VM_Q,.NONE,.NONE}, 0xF3BB04C0, 0xFFBF0FD0, .NEON, .A32, {}, {.U32,.NONE} },
{ .VRSQRTE, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xF3BB0480, 0xFFBF0FD0, .NEON, .A32, {}, {.U32,.NONE} },
{ .VRSQRTE, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xF3BB0580, 0xFFBF0FD0, .NEON, .A32, {}, {.F32,.NONE} },
{ .VSHLL, {.QPR,.DPR,.NONE,.NONE}, {.VD_Q,.VM_D,.NONE,.NONE}, 0xF3BA0300, 0xFFBF0FD0, .NEON, .A32, {}, {.I32,.NONE} },
{ .VSHLL, {.QPR,.DPR,.NONE,.NONE}, {.VD_Q,.VM_D,.NONE,.NONE}, 0xF3B60300, 0xFFBF0FD0, .NEON, .A32, {}, {.I16,.NONE} },
{ .VSHLL, {.QPR,.DPR,.NONE,.NONE}, {.VD_Q,.VM_D,.NONE,.NONE}, 0xF3B20300, 0xFFBF0FD0, .NEON, .A32, {}, {.I8,.NONE} },
{ .VSHLL, {.QPR,.DPR,.IMM,.NONE}, {.VD_Q,.VM_D,.NEON_SHLL_32,.NONE}, 0xF3BA0300, 0xFFBF0FD0, .NEON, .A32, {}, {.I32,.NONE} },
{ .VSHLL, {.QPR,.DPR,.IMM,.NONE}, {.VD_Q,.VM_D,.NEON_SHLL_16,.NONE}, 0xF3B60300, 0xFFBF0FD0, .NEON, .A32, {}, {.I16,.NONE} },
{ .VSHLL, {.QPR,.DPR,.IMM,.NONE}, {.VD_Q,.VM_D,.NEON_SHLL_8,.NONE}, 0xF3B20300, 0xFFBF0FD0, .NEON, .A32, {}, {.I8,.NONE} },
{ .VCLS, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xF3B80400, 0xFFBF0FD0, .NEON, .A32, {}, {.S32,.NONE} },
{ .VCLS, {.QPR,.QPR,.NONE,.NONE}, {.VD_Q,.VM_Q,.NONE,.NONE}, 0xF3B40440, 0xFFBF0FD0, .NEON, .A32, {}, {.S16,.NONE} },
{ .VCLS, {.QPR,.QPR,.NONE,.NONE}, {.VD_Q,.VM_Q,.NONE,.NONE}, 0xF3B00440, 0xFFBF0FD0, .NEON, .A32, {}, {.S8,.NONE} },
@@ -1010,14 +1010,14 @@ DECODE_ENTRIES := [1663]lib.Decode_Entry{
{ .LDC, {.COPROC_NUM,.COPROC_REG,.MEM,.NONE}, {.COPROC_NUM_FIELD,.COPROC_CRN_FIELD,.MEM_IMM8_OFFSET,.NONE}, 0x0C100000, 0x0F100000, .BASE, .A32, {}, {.NONE,.NONE} },
{ .VSDOT, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200D40, 0xFFB00F50, .DOT, .A32, {}, {.S8,.NONE} },
{ .VUDOT, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200D50, 0xFFB00F50, .DOT, .A32, {}, {.U8,.NONE} },
{ .VFMAL, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200850, 0xFFB00F50, .FHM, .A32, {}, {.NONE,.NONE} },
{ .VFMAL, {.QPR,.DPR,.DPR,.NONE}, {.VD_Q,.VN_D,.VM_D,.NONE}, 0xFC200850, 0xFFB00F50, .FHM, .A32, {}, {.F16,.NONE} },
{ .VSMMLA, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200C40, 0xFFB00F50, .V8, .A32, {}, {.S8,.NONE} },
{ .VUMMLA, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200C50, 0xFFB00F50, .V8, .A32, {}, {.U8,.NONE} },
{ .VSDOT, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFC200D00, 0xFFB00F10, .DOT, .A32, {}, {.S8,.NONE} },
{ .VUDOT, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFC200D10, 0xFFB00F10, .DOT, .A32, {}, {.U8,.NONE} },
{ .VFMAL, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFC200810, 0xFFB00F10, .FHM, .A32, {}, {.NONE,.NONE} },
{ .VCMLA, {.QPR,.QPR,.QPR,.IMM}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200840, 0xFC800F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.DPR,.DPR,.DPR,.IMM}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFC200800, 0xFC800F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VFMAL, {.DPR,.SPR,.SPR,.NONE}, {.VD_D,.VN_S,.VM_S,.NONE}, 0xFC200810, 0xFFB00F10, .FHM, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.QPR,.QPR,.QPR,.IMM}, {.VD_Q,.VN_Q,.VM_Q,.NEON_ROT_4}, 0xFC200840, 0xFC800F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.DPR,.DPR,.DPR,.IMM}, {.VD_D,.VN_D,.VM_D,.NEON_ROT_4}, 0xFC200800, 0xFC800F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VFMA, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC300850, 0xFFB00F50, .BF16, .A32, {}, {.BF16,.NONE} },
{ .VMOV, {.SPR,.SPR,.GPR,.GPR}, {.VM_S,.NONE,.RT_A32,.RT2_A32}, 0x0C400A10, 0x0FF00FD0, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .VMOV, {.DPR,.GPR,.GPR,.NONE}, {.VM_D,.RT_A32,.RT2_A32,.NONE}, 0x0C400B10, 0x0FF00FD0, .VFPV2, .A32, {}, {.NONE,.NONE} },
@@ -1027,17 +1027,17 @@ DECODE_ENTRIES := [1663]lib.Decode_Entry{
{ .VMOV, {.GPR,.GPR,.SPR,.SPR}, {.RT_A32,.RT2_A32,.VM_S,.NONE}, 0x0C500A10, 0x0FF00FD0, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .MRRC2, {.COPROC_NUM,.IMM_COPROC_OP,.GPR,.GPR}, {.COPROC_NUM_FIELD,.COPROC_OPC_MCRR,.RT_A32,.RT2_A32}, 0xFC500000, 0xFFF00000, .V6, .A32, {}, {.NONE,.NONE} },
{ .MRRC, {.COPROC_NUM,.IMM_COPROC_OP,.GPR,.GPR}, {.COPROC_NUM_FIELD,.COPROC_OPC_MCRR,.RT_A32,.RT2_A32}, 0x0C500000, 0x0FF00000, .V6, .A32, {}, {.NONE,.NONE} },
{ .VCADD, {.QPR,.QPR,.QPR,.IMM}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC800840, 0xFE800F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCADD, {.DPR,.DPR,.DPR,.IMM}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFC800800, 0xFE800F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCADD, {.QPR,.QPR,.QPR,.IMM}, {.VD_Q,.VN_Q,.VM_Q,.NEON_ROT_2}, 0xFC800840, 0xFE800F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCADD, {.DPR,.DPR,.DPR,.IMM}, {.VD_D,.VN_D,.VM_D,.NEON_ROT_2}, 0xFC800800, 0xFE800F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VSTM, {.GPR,.DPR_LIST,.NONE,.NONE}, {.RN_A32,.VFP_D_LIST,.NONE,.NONE}, 0x0C800B00, 0x0F900F00, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .VSTM, {.GPR,.SPR_LIST,.NONE,.NONE}, {.RN_A32,.VFP_S_LIST,.NONE,.NONE}, 0x0C800A00, 0x0F900F00, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .VLDM, {.GPR,.DPR_LIST,.NONE,.NONE}, {.RN_A32,.VFP_D_LIST,.NONE,.NONE}, 0x0C900B00, 0x0F900F00, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .VLDM, {.GPR,.SPR_LIST,.NONE,.NONE}, {.RN_A32,.VFP_S_LIST,.NONE,.NONE}, 0x0C900A00, 0x0F900F00, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .VFMSL, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFCA00850, 0xFFB00F50, .FHM, .A32, {}, {.NONE,.NONE} },
{ .VFMSL, {.QPR,.DPR,.DPR,.NONE}, {.VD_Q,.VN_D,.VM_D,.NONE}, 0xFCA00850, 0xFFB00F50, .FHM, .A32, {}, {.F16,.NONE} },
{ .VUSMMLA, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFCA00C40, 0xFFB00F50, .V8, .A32, {}, {.S8,.NONE} },
{ .VSUDOT, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFCA00D50, 0xFFB00F50, .V8, .A32, {}, {.NONE,.NONE} },
{ .VUSDOT, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFCA00D40, 0xFFB00F50, .V8, .A32, {}, {.S8,.NONE} },
{ .VFMSL, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFCA00810, 0xFFB00F10, .FHM, .A32, {}, {.NONE,.NONE} },
{ .VFMSL, {.DPR,.SPR,.SPR,.NONE}, {.VD_D,.VN_S,.VM_S,.NONE}, 0xFCA00810, 0xFFB00F10, .FHM, .A32, {}, {.F16,.NONE} },
{ .VUSDOT, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFCA00D00, 0xFFB00F10, .V8, .A32, {}, {.S8,.NONE} },
{ .VPOP, {.SPR_LIST,.NONE,.NONE,.NONE}, {.VFP_S_LIST,.NONE,.NONE,.NONE}, 0x0CBD0A00, 0x0FFF0F00, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .VPOP, {.DPR_LIST,.NONE,.NONE,.NONE}, {.VFP_D_LIST,.NONE,.NONE,.NONE}, 0x0CBD0B00, 0x0FFF0F00, .VFPV2, .A32, {}, {.NONE,.NONE} },
@@ -1050,10 +1050,10 @@ DECODE_ENTRIES := [1663]lib.Decode_Entry{
{ .VMOV, {.SPR,.GPR,.NONE,.NONE}, {.VN_S,.RT_A32,.NONE,.NONE}, 0x0E000A10, 0x0FF00F7F, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .VMOV, {.DPR_ELEM,.GPR,.NONE,.NONE}, {.VMOV_LANE_32,.RT_A32,.NONE,.NONE}, 0x0E000B10, 0x0FD00F7F, .VFPV2, .A32, {}, {.SZ32,.NONE} },
{ .VMOV, {.DPR_ELEM,.GPR,.NONE,.NONE}, {.VMOV_LANE_16,.RT_A32,.NONE,.NONE}, 0x0E000B30, 0x0FD00F3F, .VFPV2, .A32, {}, {.SZ16,.NONE} },
{ .VCMLA, {.QPR,.QPR,.DPR_ELEM,.IMM}, {.VD_Q,.VN_Q,.NEON_VM_SCALAR_32,.NONE}, 0xFE000840, 0xFFB00F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.DPR,.DPR,.DPR_ELEM,.IMM}, {.VD_D,.VN_D,.NEON_VM_SCALAR_32,.NONE}, 0xFE000800, 0xFFB00F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VSEL, {.DPR,.DPR,.DPR,.COND}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFE000B00, 0xFF800F50, .V8, .A32, {}, {.F64,.NONE} },
{ .VSEL, {.SPR,.SPR,.SPR,.COND}, {.VD_S,.VN_S,.VM_S,.NONE}, 0xFE000A00, 0xFF800F50, .V8, .A32, {}, {.F32,.NONE} },
{ .VCMLA, {.QPR,.QPR,.DPR_ELEM,.IMM}, {.VD_Q,.VN_Q,.NEON_VM_SCALAR_32,.NEON_ROT_4}, 0xFE000840, 0xFFB00F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.DPR,.DPR,.DPR_ELEM,.IMM}, {.VD_D,.VN_D,.NEON_VM_SCALAR_32,.NEON_ROT_4}, 0xFE000800, 0xFFB00F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VSEL, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFE000B00, 0xFF800F50, .V8, .A32, {}, {.F64,.NONE} },
{ .VSEL, {.SPR,.SPR,.SPR,.NONE}, {.VD_S,.VN_S,.VM_S,.NONE}, 0xFE000A00, 0xFF800F50, .V8, .A32, {}, {.F32,.NONE} },
{ .VMLA, {.SPR,.SPR,.SPR,.NONE}, {.VD_S,.VN_S,.VM_S,.NONE}, 0x0E000900, 0x0FB00F50, .HALF_FP, .A32, {}, {.F16,.NONE} },
{ .VMLS, {.SPR,.SPR,.SPR,.NONE}, {.VD_S,.VN_S,.VM_S,.NONE}, 0x0E000940, 0x0FB00F50, .HALF_FP, .A32, {}, {.F16,.NONE} },
{ .VMLA, {.SPR,.SPR,.SPR,.NONE}, {.VD_S,.VN_S,.VM_S,.NONE}, 0x0E000A00, 0x0FB00B50, .VFPV2, .A32, {}, {.F32,.NONE} },
@@ -1115,13 +1115,13 @@ DECODE_ENTRIES := [1663]lib.Decode_Entry{
{ .VCMP, {.DPR,.IMM,.NONE,.NONE}, {.VD_D,.IMPL,.NONE,.NONE}, 0x0EB50B40, 0x0FBF0FFF, .VFPV2, .A32, {}, {.F64,.NONE} },
{ .VCMPE, {.DPR,.IMM,.NONE,.NONE}, {.VD_D,.IMPL,.NONE,.NONE}, 0x0EB50BC0, 0x0FBF0FFF, .VFPV2, .A32, {}, {.F64,.NONE} },
{ .VCMPE, {.SPR,.IMM,.NONE,.NONE}, {.VD_S,.IMPL,.NONE,.NONE}, 0x0EB50AC0, 0x0FBF0FFF, .VFPV2, .A32, {}, {.F32,.NONE} },
{ .VCVTA, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xFEBC0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTA, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0xFEBC0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTA, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0xFEBC0A40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F32} },
{ .VCVTN, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0xFEBD0A40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F32} },
{ .VCVTN, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xFEBD0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTN, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0xFEBD0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTP, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0xFEBE0A40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F32} },
{ .VCVTP, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xFEBE0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTM, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xFEBF0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTP, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0xFEBE0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTM, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0xFEBF0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTM, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0xFEBF0A40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F32} },
{ .VRINTA, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xFEB80B40, 0xFFBF0FD0, .V8, .A32, {}, {.F64,.NONE} },
{ .VRINTA, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0xFEB80A40, 0xFFBF0FD0, .V8, .A32, {}, {.F32,.NONE} },
@@ -1193,12 +1193,12 @@ DECODE_ENTRIES := [1663]lib.Decode_Entry{
{ .VRINTZ, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0x0EB60AC0, 0x0FBF0FD0, .V8, .A32, {}, {.F32,.NONE} },
{ .VRINTX, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0x0EB70A40, 0x0FBF0FD0, .V8, .A32, {}, {.F32,.NONE} },
{ .VRINTX, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0x0EB70B40, 0x0FBF0FD0, .V8, .A32, {}, {.F64,.NONE} },
{ .VJCVT, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0x0EB90BC0, 0x0FBF0FD0, .V8, .A32, {}, {.NONE,.NONE} },
{ .VJCVT, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0x0EB90BC0, 0x0FBF0FD0, .V8, .A32, {}, {.S32,.F64} },
{ .VMOV, {.DPR,.IMM8,.NONE,.NONE}, {.VD_D,.VFP_IMM8,.NONE,.NONE}, 0x0EB00B00, 0x0FB00FF0, .VFPV3, .A32, {}, {.F64,.NONE} },
{ .VMOV, {.SPR,.IMM8,.NONE,.NONE}, {.VD_S,.VFP_IMM8,.NONE,.NONE}, 0x0EB00A00, 0x0FB00FF0, .VFPV3, .A32, {}, {.F32,.NONE} },
{ .VDUP, {.DPR,.GPR,.NONE,.NONE}, {.VD_D,.RT_A32,.NONE,.NONE}, 0x0EC00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8,.NONE} },
{ .VDUP, {.DPR,.GPR,.NONE,.NONE}, {.VN_D,.RT_A32,.NONE,.NONE}, 0x0EC00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8,.NONE} },
{ .VMSR, {.GPR,.NONE,.NONE,.NONE}, {.RT_A32,.NONE,.NONE,.NONE}, 0x0EE10A10, 0x0FFF0FFF, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .VDUP, {.QPR,.GPR,.NONE,.NONE}, {.VD_Q,.RT_A32,.NONE,.NONE}, 0x0EE00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8,.NONE} },
{ .VDUP, {.QPR,.GPR,.NONE,.NONE}, {.VN_Q,.RT_A32,.NONE,.NONE}, 0x0EE00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8,.NONE} },
{ .VMRS, {.GPR,.NONE,.NONE,.NONE}, {.RT_A32,.NONE,.NONE,.NONE}, 0x0EF10A10, 0x0FFF0FFF, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .SVC, {.IMM,.NONE,.NONE,.NONE}, {.A32_IMM24,.NONE,.NONE,.NONE}, 0x0F000000, 0x0F000000, .BASE, .A32, {}, {.NONE,.NONE} },
{ .SG, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0xE97FE97F, 0xFFFFFFFF, .V8M_SE, .T32, {thumb32=true}, {.NONE,.NONE} },

View File

@@ -1097,16 +1097,16 @@ ENCODE_FORMS := [1663]lib.Encoding{
{ .VCVTT, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0x0EB30AC0, 0x0FBF0FD0, .VFPV3, .A32, {}, {.F16,.F32} },
// .VCVTA
{ .VCVTA, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0xFEBC0A40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F32} },
{ .VCVTA, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xFEBC0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTA, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0xFEBC0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
// .VCVTN
{ .VCVTN, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0xFEBD0A40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F32} },
{ .VCVTN, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xFEBD0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTN, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0xFEBD0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
// .VCVTP
{ .VCVTP, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0xFEBE0A40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F32} },
{ .VCVTP, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xFEBE0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTP, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0xFEBE0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
// .VCVTM
{ .VCVTM, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0xFEBF0A40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F32} },
{ .VCVTM, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xFEBF0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
{ .VCVTM, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0xFEBF0B40, 0xFFBF0FD0, .V8, .A32, {}, {.U32,.F64} },
// .VCVTR
{ .VCVTR, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0x0EBD0A40, 0x0FBF0FD0, .VFPV2, .A32, {}, {.S32,.F32} },
{ .VCVTR, {.SPR,.SPR,.NONE,.NONE}, {.VD_S,.VM_S,.NONE,.NONE}, 0x0EBC0A40, 0x0FBF0FD0, .VFPV2, .A32, {}, {.U32,.F32} },
@@ -1169,8 +1169,8 @@ ENCODE_FORMS := [1663]lib.Encoding{
{ .VPOP, {.SPR_LIST,.NONE,.NONE,.NONE}, {.VFP_S_LIST,.NONE,.NONE,.NONE}, 0x0CBD0A00, 0x0FFF0F00, .VFPV2, .A32, {}, {.NONE,.NONE} },
{ .VPOP, {.DPR_LIST,.NONE,.NONE,.NONE}, {.VFP_D_LIST,.NONE,.NONE,.NONE}, 0x0CBD0B00, 0x0FFF0F00, .VFPV2, .A32, {}, {.NONE,.NONE} },
// .VSEL
{ .VSEL, {.SPR,.SPR,.SPR,.COND}, {.VD_S,.VN_S,.VM_S,.NONE}, 0xFE000A00, 0xFF800F50, .V8, .A32, {}, {.F32,.NONE} },
{ .VSEL, {.DPR,.DPR,.DPR,.COND}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFE000B00, 0xFF800F50, .V8, .A32, {}, {.F64,.NONE} },
{ .VSEL, {.SPR,.SPR,.SPR,.NONE}, {.VD_S,.VN_S,.VM_S,.NONE}, 0xFE000A00, 0xFF800F50, .V8, .A32, {}, {.F32,.NONE} },
{ .VSEL, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFE000B00, 0xFF800F50, .V8, .A32, {}, {.F64,.NONE} },
// .VMAXNM
{ .VMAXNM, {.SPR,.SPR,.SPR,.NONE}, {.VD_S,.VN_S,.VM_S,.NONE}, 0xFE800A00, 0xFFB00B50, .V8, .A32, {}, {.F32,.NONE} },
{ .VMAXNM, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFE800B00, 0xFFB00B50, .V8, .A32, {}, {.F64,.NONE} },
@@ -1720,9 +1720,9 @@ ENCODE_FORMS := [1663]lib.Encoding{
{ .VRSHRN, {.DPR,.QPR,.IMM,.NONE}, {.VD_D,.VM_Q,.NEON_SHIFT_IMM6,.NONE}, 0xF2800850, 0xFE800FD0, .NEON, .A32, {}, {.I16,.NONE} },
// .VSHLL
{ .VSHLL, {.QPR,.DPR,.IMM,.NONE}, {.VD_Q,.VM_D,.NEON_SHIFT_IMM6,.NONE}, 0xF2800A10, 0xFE800FD0, .NEON, .A32, {}, {.I16,.NONE} },
{ .VSHLL, {.QPR,.DPR,.NONE,.NONE}, {.VD_Q,.VM_D,.NONE,.NONE}, 0xF3B20300, 0xFFBF0FD0, .NEON, .A32, {}, {.I8,.NONE} },
{ .VSHLL, {.QPR,.DPR,.NONE,.NONE}, {.VD_Q,.VM_D,.NONE,.NONE}, 0xF3B60300, 0xFFBF0FD0, .NEON, .A32, {}, {.I16,.NONE} },
{ .VSHLL, {.QPR,.DPR,.NONE,.NONE}, {.VD_Q,.VM_D,.NONE,.NONE}, 0xF3BA0300, 0xFFBF0FD0, .NEON, .A32, {}, {.I32,.NONE} },
{ .VSHLL, {.QPR,.DPR,.IMM,.NONE}, {.VD_Q,.VM_D,.NEON_SHLL_8,.NONE}, 0xF3B20300, 0xFFBF0FD0, .NEON, .A32, {}, {.I8,.NONE} },
{ .VSHLL, {.QPR,.DPR,.IMM,.NONE}, {.VD_Q,.VM_D,.NEON_SHLL_16,.NONE}, 0xF3B60300, 0xFFBF0FD0, .NEON, .A32, {}, {.I16,.NONE} },
{ .VSHLL, {.QPR,.DPR,.IMM,.NONE}, {.VD_Q,.VM_D,.NEON_SHLL_32,.NONE}, 0xF3BA0300, 0xFFBF0FD0, .NEON, .A32, {}, {.I32,.NONE} },
// .VCLS
{ .VCLS, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xF3B00400, 0xFFBF0FD0, .NEON, .A32, {}, {.S8,.NONE} },
{ .VCLS, {.DPR,.DPR,.NONE,.NONE}, {.VD_D,.VM_D,.NONE,.NONE}, 0xF3B40400, 0xFFBF0FD0, .NEON, .A32, {}, {.S16,.NONE} },
@@ -1788,8 +1788,8 @@ ENCODE_FORMS := [1663]lib.Encoding{
{ .VZIP, {.QPR,.QPR,.NONE,.NONE}, {.VD_Q,.VM_Q,.NONE,.NONE}, 0xF3B601C0, 0xFFBF0FD0, .NEON, .A32, {}, {.SZ16,.NONE} },
{ .VZIP, {.QPR,.QPR,.NONE,.NONE}, {.VD_Q,.VM_Q,.NONE,.NONE}, 0xF3BA01C0, 0xFFBF0FD0, .NEON, .A32, {}, {.SZ32,.NONE} },
// .VDUP
{ .VDUP, {.DPR,.GPR,.NONE,.NONE}, {.VD_D,.RT_A32,.NONE,.NONE}, 0x0EC00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8,.NONE} },
{ .VDUP, {.QPR,.GPR,.NONE,.NONE}, {.VD_Q,.RT_A32,.NONE,.NONE}, 0x0EE00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8,.NONE} },
{ .VDUP, {.DPR,.GPR,.NONE,.NONE}, {.VN_D,.RT_A32,.NONE,.NONE}, 0x0EC00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8,.NONE} },
{ .VDUP, {.QPR,.GPR,.NONE,.NONE}, {.VN_Q,.RT_A32,.NONE,.NONE}, 0x0EE00B10, 0x0FF00FD0, .NEON, .A32, {}, {.SZ8,.NONE} },
{ .VDUP, {.DPR,.DPR_ELEM,.NONE,.NONE}, {.VD_D,.NEON_VM_SCALAR_32,.NONE,.NONE}, 0xF3B00C00, 0xFFB00FD0, .NEON, .A32, {}, {.NONE,.NONE} },
{ .VDUP, {.QPR,.DPR_ELEM,.NONE,.NONE}, {.VD_Q,.NEON_VM_SCALAR_32,.NONE,.NONE}, 0xF3B00C40, 0xFFB00FD0, .NEON, .A32, {}, {.NONE,.NONE} },
{ .VDUP, {.QPR,.GPR,.NONE,.NONE}, {.VD_Q,.RT_T32,.NONE,.NONE}, 0xEE800B10, 0xFF900F5F, .MVE_INT, .T32, {thumb32=true}, {.SZ32,.NONE} },
@@ -1880,7 +1880,7 @@ ENCODE_FORMS := [1663]lib.Encoding{
// .SHA256SU1
{ .SHA256SU1, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xF3200C40, 0xFFB00F50, .CRYPTO, .A32, {}, {.SZ32,.NONE} },
// .VJCVT
{ .VJCVT, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0x0EB90BC0, 0x0FBF0FD0, .V8, .A32, {}, {.NONE,.NONE} },
{ .VJCVT, {.SPR,.DPR,.NONE,.NONE}, {.VD_S,.VM_D,.NONE,.NONE}, 0x0EB90BC0, 0x0FBF0FD0, .V8, .A32, {}, {.S32,.F64} },
// .VSDOT
{ .VSDOT, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFC200D00, 0xFFB00F10, .DOT, .A32, {}, {.S8,.NONE} },
{ .VSDOT, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200D40, 0xFFB00F50, .DOT, .A32, {}, {.S8,.NONE} },
@@ -1897,20 +1897,20 @@ ENCODE_FORMS := [1663]lib.Encoding{
// .VMMLA
{ .VMMLA, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC000C40, 0xFFB00F50, .BF16, .A32, {}, {.BF16,.NONE} },
// .VFMAL
{ .VFMAL, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFC200810, 0xFFB00F10, .FHM, .A32, {}, {.NONE,.NONE} },
{ .VFMAL, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200850, 0xFFB00F50, .FHM, .A32, {}, {.NONE,.NONE} },
{ .VFMAL, {.DPR,.SPR,.SPR,.NONE}, {.VD_D,.VN_S,.VM_S,.NONE}, 0xFC200810, 0xFFB00F10, .FHM, .A32, {}, {.F16,.NONE} },
{ .VFMAL, {.QPR,.DPR,.DPR,.NONE}, {.VD_Q,.VN_D,.VM_D,.NONE}, 0xFC200850, 0xFFB00F50, .FHM, .A32, {}, {.F16,.NONE} },
// .VFMSL
{ .VFMSL, {.DPR,.DPR,.DPR,.NONE}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFCA00810, 0xFFB00F10, .FHM, .A32, {}, {.NONE,.NONE} },
{ .VFMSL, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFCA00850, 0xFFB00F50, .FHM, .A32, {}, {.NONE,.NONE} },
{ .VFMSL, {.DPR,.SPR,.SPR,.NONE}, {.VD_D,.VN_S,.VM_S,.NONE}, 0xFCA00810, 0xFFB00F10, .FHM, .A32, {}, {.F16,.NONE} },
{ .VFMSL, {.QPR,.DPR,.DPR,.NONE}, {.VD_Q,.VN_D,.VM_D,.NONE}, 0xFCA00850, 0xFFB00F50, .FHM, .A32, {}, {.F16,.NONE} },
// .VCMLA
{ .VCMLA, {.DPR,.DPR,.DPR,.IMM}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFC200800, 0xFC800F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.QPR,.QPR,.QPR,.IMM}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200840, 0xFC800F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.DPR,.DPR,.DPR_ELEM,.IMM}, {.VD_D,.VN_D,.NEON_VM_SCALAR_32,.NONE}, 0xFE000800, 0xFFB00F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.QPR,.QPR,.DPR_ELEM,.IMM}, {.VD_Q,.VN_Q,.NEON_VM_SCALAR_32,.NONE}, 0xFE000840, 0xFFB00F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.DPR,.DPR,.DPR,.IMM}, {.VD_D,.VN_D,.VM_D,.NEON_ROT_4}, 0xFC200800, 0xFC800F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.QPR,.QPR,.QPR,.IMM}, {.VD_Q,.VN_Q,.VM_Q,.NEON_ROT_4}, 0xFC200840, 0xFC800F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.DPR,.DPR,.DPR_ELEM,.IMM}, {.VD_D,.VN_D,.NEON_VM_SCALAR_32,.NEON_ROT_4}, 0xFE000800, 0xFFB00F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.QPR,.QPR,.DPR_ELEM,.IMM}, {.VD_Q,.VN_Q,.NEON_VM_SCALAR_32,.NEON_ROT_4}, 0xFE000840, 0xFFB00F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCMLA, {.QPR,.QPR,.QPR,.IMM}, {.VD_Q,.VN_Q,.VM_Q,.MVE_ROT_CMLA}, 0xFC200840, 0xFE611FF1, .MVE_FP, .T32, {thumb32=true}, {.F16,.NONE} },
// .VCADD
{ .VCADD, {.DPR,.DPR,.DPR,.IMM}, {.VD_D,.VN_D,.VM_D,.NONE}, 0xFC800800, 0xFE800F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCADD, {.QPR,.QPR,.QPR,.IMM}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC800840, 0xFE800F50, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCADD, {.DPR,.DPR,.DPR,.IMM}, {.VD_D,.VN_D,.VM_D,.NEON_ROT_2}, 0xFC800800, 0xFE800F10, .FCMA, .A32, {}, {.F16,.NONE} },
{ .VCADD, {.QPR,.QPR,.QPR,.IMM}, {.VD_Q,.VN_Q,.VM_Q,.NEON_ROT_2}, 0xFC800840, 0xFE800F50, .FCMA, .A32, {}, {.F16,.NONE} },
// .VSMMLA
{ .VSMMLA, {.QPR,.QPR,.QPR,.NONE}, {.VD_Q,.VN_Q,.VM_Q,.NONE}, 0xFC200C40, 0xFFB00F50, .V8, .A32, {}, {.S8,.NONE} },
// .VUMMLA