use crate::arm::arm_instr_info::ArmOpcode;
use crate::opcode::Opcode;
use std::collections::HashMap;
use super::arm_isel_table::{ImmConstraint, IselOperand, IselPattern, IselStats};
pub struct CompleteIselTable {
pub patterns: Vec<IselPattern>,
pub stats: IselStats,
}
pub fn build_complete_isel_table() -> Vec<IselPattern> {
let mut table = Vec::new();
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "aese — AES single round encryption, v.16b operand",
result_opcode: ArmOpcode::AESE_Z,
priority: 200,
num_operands: 2,
imm_constraint: None,
is_two_address: true,
required_feature: Some("aes"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "aesd — AES single round decryption, v.16b operand",
result_opcode: ArmOpcode::AESD_Z,
priority: 201,
num_operands: 2,
imm_constraint: None,
is_two_address: true,
required_feature: Some("aes"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "aesmc — AES mix columns",
result_opcode: ArmOpcode::AESMC_Z,
priority: 202,
num_operands: 2,
imm_constraint: None,
is_two_address: true,
required_feature: Some("aes"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "aesimc — AES inverse mix columns",
result_opcode: ArmOpcode::AESIMC_Z,
priority: 203,
num_operands: 2,
imm_constraint: None,
is_two_address: true,
required_feature: Some("aes"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha1c q, s, v.4s — SHA1 hash update (choose)",
result_opcode: ArmOpcode::SHA1C_Z,
priority: 210,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha1h s, s — SHA1 hash update (hash)",
result_opcode: ArmOpcode::SHA1H_Z,
priority: 211,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha1m q, s, v.4s — SHA1 hash update (majority)",
result_opcode: ArmOpcode::SHA1M_Z,
priority: 212,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha1p q, s, v.4s — SHA1 hash update (parity)",
result_opcode: ArmOpcode::SHA1P_Z,
priority: 213,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha1su0 v.4s, v.4s, v.4s — SHA1 schedule update 0",
result_opcode: ArmOpcode::SHA1SU0_Z,
priority: 214,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha1su1 v.4s, v.4s — SHA1 schedule update 1",
result_opcode: ArmOpcode::SHA1SU1_Z,
priority: 215,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha256h q, q, v.4s — SHA256 hash update",
result_opcode: ArmOpcode::SHA256H_Z,
priority: 220,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha256h2 q, q, v.4s — SHA256 hash update (upper)",
result_opcode: ArmOpcode::SHA256H2_Z,
priority: 221,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha256su0 v.4s, v.4s — SHA256 schedule update 0",
result_opcode: ArmOpcode::SHA256SU0_Z,
priority: 222,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha256su1 v.4s, v.4s, v.4s — SHA256 schedule update 1",
result_opcode: ArmOpcode::SHA256SU1_Z,
priority: 223,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha512h q, q, v.2d — SHA512 hash update",
result_opcode: ArmOpcode::SHA512H_Z,
priority: 230,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha512h2 q, q, v.2d — SHA512 hash update (upper)",
result_opcode: ArmOpcode::SHA512H2_Z,
priority: 231,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha512su0 v.2d, v.2d — SHA512 schedule update 0",
result_opcode: ArmOpcode::SHA512SU0_Z,
priority: 232,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sha3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha512su1 v.2d, v.2d, v.2d — SHA512 schedule update 1",
result_opcode: ArmOpcode::SHA512SU1_Z,
priority: 233,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3ss1 v.4s, v.4s, v.4s — SM3 schedue shuffle 1",
result_opcode: ArmOpcode::SM3SS1_Z,
priority: 240,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3partw1 v.4s, v.4s, v.4s — SM3 part word 1",
result_opcode: ArmOpcode::SM3PARTW1_Z,
priority: 241,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3partw2 v.4s, v.4s, v.4s — SM3 part word 2",
result_opcode: ArmOpcode::SM3PARTW2_Z,
priority: 242,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3tt1a v.4s, v.4s, v.4s[s] — SM3 TT1A",
result_opcode: ArmOpcode::SM3TT1A_Z,
priority: 243,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3tt1b v.4s, v.4s, v.4s[s] — SM3 TT1B",
result_opcode: ArmOpcode::SM3TT1B_Z,
priority: 244,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3tt2a v.4s, v.4s, v.4s[s] — SM3 TT2A",
result_opcode: ArmOpcode::SM3TT2A_Z,
priority: 245,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3tt2b v.4s, v.4s, v.4s[s] — SM3 TT2B",
result_opcode: ArmOpcode::SM3TT2B_Z,
priority: 246,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm4e v.4s, v.4s — SM4 block cipher encrypt",
result_opcode: ArmOpcode::SM4E_Z,
priority: 250,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sm4"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm4ekey v.4s, v.4s — SM4 key schedule",
result_opcode: ArmOpcode::SM4EKEY_Z,
priority: 251,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sm4"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "faddh — FP16 add (half-precision)",
result_opcode: ArmOpcode::FADD,
priority: 300,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "fsubh — FP16 subtract (half-precision)",
result_opcode: ArmOpcode::FSUB,
priority: 301,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FMul,
description: "fmulh — FP16 multiply (half-precision)",
result_opcode: ArmOpcode::FMUL,
priority: 302,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FDiv,
description: "fdivh — FP16 divide (half-precision)",
result_opcode: ArmOpcode::FDIV,
priority: 303,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fmaxh — FP16 max (half-precision)",
result_opcode: ArmOpcode::FMAX,
priority: 304,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fminh — FP16 min (half-precision)",
result_opcode: ArmOpcode::FMIN,
priority: 305,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fmaxnmh — FP16 max number (half-precision)",
result_opcode: ArmOpcode::FMAXNM,
priority: 306,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fminnmh — FP16 min number (half-precision)",
result_opcode: ArmOpcode::FMINNM,
priority: 307,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fabsh — FP16 absolute value (half-precision)",
result_opcode: ArmOpcode::FABS,
priority: 308,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fnegh — FP16 negate (half-precision)",
result_opcode: ArmOpcode::FNEG,
priority: 309,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fsqrth — FP16 square root (half-precision)",
result_opcode: ArmOpcode::FSQRT,
priority: 310,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPExt,
description: "fcvtsh — convert FP16 to FP32",
result_opcode: ArmOpcode::FCVT,
priority: 315,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPTrunc,
description: "fcvths — convert FP32 to FP16",
result_opcode: ArmOpcode::FCVT,
priority: 316,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPTrunc,
description: "fcvtdh — convert FP64 to FP16",
result_opcode: ArmOpcode::FCVT,
priority: 317,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPExt,
description: "fcvthd — convert FP16 to FP64",
result_opcode: ArmOpcode::FCVT,
priority: 318,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPToSI,
description: "fjcvtzs — JavaScript-style float-to-int conversion, d→w",
result_opcode: ArmOpcode::FCVTZS,
priority: 320,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("jscvt"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frint32z — round FP to 32-bit integer toward zero",
result_opcode: ArmOpcode::FRINTZ,
priority: 325,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("frintts"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frint32x — round FP to 32-bit integer (current mode)",
result_opcode: ArmOpcode::FRINTX,
priority: 326,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("frintts"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frint64z — round FP to 64-bit integer toward zero",
result_opcode: ArmOpcode::FRINTZ,
priority: 327,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("frintts"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frint64x — round FP to 64-bit integer (current mode)",
result_opcode: ArmOpcode::FRINTX,
priority: 328,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("frintts"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fcadd v.4s, v.4s, v.4s, #90 — complex add rotate 90",
result_opcode: ArmOpcode::CADD_SVE,
priority: 350,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fcadd v.4s, v.4s, v.4s, #270 — complex add rotate 270",
result_opcode: ArmOpcode::CADD_SVE,
priority: 351,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4s, v.4s, v.4s, #0 — complex MLA rotate 0",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 352,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4s, v.4s, v.4s, #90 — complex MLA rotate 90",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 353,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4s, v.4s, v.4s, #180 — complex MLA rotate 180",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 354,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4s, v.4s, v.4s, #270 — complex MLA rotate 270",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 355,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fcadd v.8h, v.8h, v.8h, #90 — complex add rotate 90 (half)",
result_opcode: ArmOpcode::CADD_SVE,
priority: 356,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fcadd v.8h, v.8h, v.8h, #270 — complex add rotate 270 (half)",
result_opcode: ArmOpcode::CADD_SVE,
priority: 357,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.8h, v.8h, v.8h, #0 — complex MLA rotate 0 (half)",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 358,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.8h, v.8h, v.8h, #90 — complex MLA rotate 90 (half)",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 359,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.8h, v.8h, v.8h, #180 — complex MLA rotate 180 (half)",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 360,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.8h, v.8h, v.8h, #270 — complex MLA rotate 270 (half)",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 361,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sdot v.2s, v.8b, v.8b — signed dot product 8b→32b, 2 accum",
result_opcode: ArmOpcode::SDOT_Z,
priority: 370,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("dotprod"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sdot v.4s, v.16b, v.16b — signed dot product 8b→32b, 4 accum",
result_opcode: ArmOpcode::SDOT_Z,
priority: 371,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("dotprod"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "udot v.2s, v.8b, v.8b — unsigned dot product 8b→32b, 2 accum",
result_opcode: ArmOpcode::UDOT_Z,
priority: 372,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("dotprod"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "udot v.4s, v.16b, v.16b — unsigned dot product 8b→32b, 4 accum",
result_opcode: ArmOpcode::UDOT_Z,
priority: 373,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("dotprod"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "usdot v.2s, v.8b, v.8b — unsigned-by-signed dot product",
result_opcode: ArmOpcode::USMMLA,
priority: 380,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("i8mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "usdot v.4s, v.16b, v.16b — unsigned-by-signed dot product 4 accum",
result_opcode: ArmOpcode::USMMLA,
priority: 381,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("i8mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sudot v.2s, v.8b, v.8b — signed-by-unsigned dot product",
result_opcode: ArmOpcode::SDOT_Z,
priority: 385,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("i8mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "bfdot v.2s, v.4h, v.4h — BFloat16 dot product 2 accum",
result_opcode: ArmOpcode::BFDOT_SME21,
priority: 390,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "bfdot v.4s, v.8h, v.8h — BFloat16 dot product 4 accum",
result_opcode: ArmOpcode::BFDOT_SME21,
priority: 391,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FMul,
description: "fdot v.2s, v.2s, v.2s — FP32 dot product 2 accum",
result_opcode: ArmOpcode::FDOT_Z,
priority: 395,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FMul,
description: "fdot v.4s, v.4s, v.4s — FP32 dot product 4 accum",
result_opcode: ArmOpcode::FDOT_Z,
priority: 396,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smmla v.4s, v.16b, v.16b — signed int8 matrix multiply-accumulate",
result_opcode: ArmOpcode::SMMLA,
priority: 400,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("i8mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "ummla v.4s, v.16b, v.16b — unsigned int8 matrix multiply-accumulate",
result_opcode: ArmOpcode::UMMLA,
priority: 405,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("i8mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "usmmla v.4s, v.16b, v.16b — unsigned-by-signed int8 MMA",
result_opcode: ArmOpcode::USMMLA,
priority: 410,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("i8mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FMul,
description: "fmmla v.4s, v.4s, v.4s — FP32 matrix multiply-accumulate",
result_opcode: ArmOpcode::FMLA,
priority: 415,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("f32mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FMul,
description: "bfmmla v.4s, v.8h, v.8h — BFloat16 matrix multiply-accumulate",
result_opcode: ArmOpcode::BFMOPA,
priority: 420,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FMul,
description: "fmmla v.8h, v.8h, v.8h — FP16 matrix multiply-accumulate",
result_opcode: ArmOpcode::FMLA,
priority: 425,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FMul,
description: "fmmla v.2d, v.2d, v.2d — FP64 matrix multiply-accumulate",
result_opcode: ArmOpcode::FMLA,
priority: 430,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("f64mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smmla i8mm v.2s, v.8b, v.8b — signed int8 2-way MMA (narrow)",
result_opcode: ArmOpcode::SMMLA,
priority: 435,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("i8mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "ummla i8mm v.2s, v.8b, v.8b — unsigned int8 2-way MMA (narrow)",
result_opcode: ArmOpcode::UMMLA,
priority: 436,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("i8mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "usmmla i8mm v.2s, v.8b, v.8b — unsigned×signed 2-way MMA",
result_opcode: ArmOpcode::USMMLA,
priority: 437,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("i8mm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pldkeep, [xn] — range prefetch for load (keep)",
result_opcode: ArmOpcode::PRFM,
priority: 450,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pstkeep, [xn] — range prefetch for store (keep)",
result_opcode: ArmOpcode::PRFM,
priority: 451,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pldstrm, [xn] — range prefetch for load (streaming)",
result_opcode: ArmOpcode::PRFM,
priority: 452,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pststrm, [xn] — range prefetch for store (streaming)",
result_opcode: ArmOpcode::PRFM,
priority: 453,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pldl1keep, [xn] — prefetch for load, L1 keep",
result_opcode: ArmOpcode::PRFM,
priority: 460,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pldl1strm, [xn] — prefetch for load, L1 stream",
result_opcode: ArmOpcode::PRFM,
priority: 461,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pldl2keep, [xn] — prefetch for load, L2 keep",
result_opcode: ArmOpcode::PRFM,
priority: 462,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pldl2strm, [xn] — prefetch for load, L2 stream",
result_opcode: ArmOpcode::PRFM,
priority: 463,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pldl3keep, [xn] — prefetch for load, L3 keep",
result_opcode: ArmOpcode::PRFM,
priority: 464,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pldl3strm, [xn] — prefetch for load, L3 stream",
result_opcode: ArmOpcode::PRFM,
priority: 465,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm plil1keep, [xn] — prefetch instruction, L1 keep",
result_opcode: ArmOpcode::PRFM,
priority: 466,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm plil1strm, [xn] — prefetch instruction, L1 stream",
result_opcode: ArmOpcode::PRFM,
priority: 467,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm plil2keep, [xn] — prefetch instruction, L2 keep",
result_opcode: ArmOpcode::PRFM,
priority: 468,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm plil2strm, [xn] — prefetch instruction, L2 stream",
result_opcode: ArmOpcode::PRFM,
priority: 469,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm plil3keep, [xn] — prefetch instruction, L3 keep",
result_opcode: ArmOpcode::PRFM,
priority: 470,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm plil3strm, [xn] — prefetch instruction, L3 stream",
result_opcode: ArmOpcode::PRFM,
priority: 471,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pstl1keep, [xn] — prefetch for store, L1 keep",
result_opcode: ArmOpcode::PRFM,
priority: 472,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pstl1strm, [xn] — prefetch for store, L1 stream",
result_opcode: ArmOpcode::PRFM,
priority: 473,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pstl2keep, [xn] — prefetch for store, L2 keep",
result_opcode: ArmOpcode::PRFM,
priority: 474,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pstl2strm, [xn] — prefetch for store, L2 stream",
result_opcode: ArmOpcode::PRFM,
priority: 475,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pstl3keep, [xn] — prefetch for store, L3 keep",
result_opcode: ArmOpcode::PRFM,
priority: 476,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "prfm pstl3strm, [xn] — prefetch for store, L3 stream",
result_opcode: ArmOpcode::PRFM,
priority: 477,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc ivac, xn — data cache invalidate by VA to PoC",
result_opcode: ArmOpcode::SYS,
priority: 500,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc isw, xn — data cache invalidate by set/way",
result_opcode: ArmOpcode::SYS,
priority: 501,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cvac, xn — data cache clean by VA to PoC",
result_opcode: ArmOpcode::SYS,
priority: 502,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc csw, xn — data cache clean by set/way",
result_opcode: ArmOpcode::SYS,
priority: 503,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cvau, xn — data cache clean by VA to PoU",
result_opcode: ArmOpcode::SYS,
priority: 504,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc civac, xn — data cache clean+invalidate by VA to PoC",
result_opcode: ArmOpcode::SYS,
priority: 505,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc zva, xn — data cache zero by VA",
result_opcode: ArmOpcode::SYS,
priority: 506,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("dc-zva"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc gva, xn — data cache GVA operation",
result_opcode: ArmOpcode::SYS,
priority: 507,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc gzva, xn — data cache zero by GVA",
result_opcode: ArmOpcode::SYS,
priority: 508,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc igvac, xn — Guest stage 2 invalidate by VA to PoC",
result_opcode: ArmOpcode::SYS,
priority: 509,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc igsw, xn — Guest stage 2 invalidate by set/way",
result_opcode: ArmOpcode::SYS,
priority: 510,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc igdvac, xn — Guest Data invalidate by VA to PoC",
result_opcode: ArmOpcode::SYS,
priority: 511,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc igdsw, xn — Guest Data invalidate by set/way",
result_opcode: ArmOpcode::SYS,
priority: 512,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cgvac, xn — Guest Clean by VA to PoC",
result_opcode: ArmOpcode::SYS,
priority: 513,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cgdvac, xn — Guest Data Clean by VA to PoC",
result_opcode: ArmOpcode::SYS,
priority: 514,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cgsw, xn — Guest Clean by set/way",
result_opcode: ArmOpcode::SYS,
priority: 515,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cgdap, xn — Guest Data Allocation Persistence",
result_opcode: ArmOpcode::SYS,
priority: 516,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cgdp, xn — Guest Data Persistence",
result_opcode: ArmOpcode::SYS,
priority: 517,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cgdvadp, xn — Guest Data VA Data Persistence",
result_opcode: ArmOpcode::SYS,
priority: 518,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cgdvap, xn — Guest Data VA Persistence",
result_opcode: ArmOpcode::SYS,
priority: 519,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("vhe"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cvadp, xn — Clean VA to Point of Deep Persistence",
result_opcode: ArmOpcode::SYS,
priority: 520,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cvap, xn — Clean VA to Point of Persistence",
result_opcode: ArmOpcode::SYS,
priority: 521,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4s, v.4s, v.s[lane], #0 — complex MLA indexed, rotate 0",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 530,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4s, v.4s, v.s[lane], #90 — complex MLA indexed, rotate 90",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 531,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4s, v.4s, v.s[lane], #180 — complex MLA indexed, rotate 180",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 532,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4s, v.4s, v.s[lane], #270 — complex MLA indexed, rotate 270",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 533,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("fcma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sdot v.2s, v.8b, v.b[lane] — signed dot product indexed, 2 accum",
result_opcode: ArmOpcode::SDOT_Z,
priority: 540,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("dotprod"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sdot v.4s, v.16b, v.b[lane] — signed dot product indexed, 4 accum",
result_opcode: ArmOpcode::SDOT_Z,
priority: 541,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("dotprod"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "udot v.2s, v.8b, v.b[lane] — unsigned dot product indexed, 2 accum",
result_opcode: ArmOpcode::UDOT_Z,
priority: 542,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("dotprod"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "udot v.4s, v.16b, v.b[lane] — unsigned dot product indexed, 4 accum",
result_opcode: ArmOpcode::UDOT_Z,
priority: 543,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("dotprod"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frintih — FP16 round to integral (half, current mode)",
result_opcode: ArmOpcode::FRINTI,
priority: 550,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frintzh — FP16 round to integral toward zero (half)",
result_opcode: ArmOpcode::FRINTZ,
priority: 551,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frintph — FP16 round to integral toward +inf (half)",
result_opcode: ArmOpcode::FRINTP,
priority: 552,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frintmh — FP16 round to integral toward -inf (half)",
result_opcode: ArmOpcode::FRINTM,
priority: 553,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frintxh — FP16 round to integral (half, current with inexact)",
result_opcode: ArmOpcode::FRINTX,
priority: 554,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frintah — FP16 round to integral ties to away (half)",
result_opcode: ArmOpcode::FRINTA,
priority: 555,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frintnh — FP16 round to integral ties to even (half)",
result_opcode: ArmOpcode::FRINTN,
priority: 556,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FCmp,
description: "fcmph — FP16 compare (half-precision)",
result_opcode: ArmOpcode::FCMP,
priority: 560,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FCmp,
description: "fccmph — FP16 conditional compare (half-precision)",
result_opcode: ArmOpcode::FCCMP,
priority: 561,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Select,
description: "fcselh — FP16 conditional select (half-precision)",
result_opcode: ArmOpcode::FCSEL,
priority: 562,
num_operands: 4,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fmovh — FP16 move (half-precision)",
result_opcode: ArmOpcode::FMOV,
priority: 570,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "freceh — FP16 reciprocal estimate (half-precision)",
result_opcode: ArmOpcode::FRECPE,
priority: 575,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "frsqrteh — FP16 reciprocal sqrt estimate (half-precision)",
result_opcode: ArmOpcode::FRSQRTE,
priority: 576,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "frecpsh — FP16 reciprocal step (half-precision)",
result_opcode: ArmOpcode::FRECPS,
priority: 577,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "frsqrtsh — FP16 reciprocal sqrt step (half-precision)",
result_opcode: ArmOpcode::FRSQRTS,
priority: 578,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fmlah — FP16 fused multiply-add (half-precision)",
result_opcode: ArmOpcode::FMLA,
priority: 580,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fmlsh — FP16 fused multiply-subtract (half-precision)",
result_opcode: ArmOpcode::FMLS,
priority: 581,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fmulxh — FP16 multiply extended (half-precision)",
result_opcode: ArmOpcode::FMULX,
priority: 582,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Load,
description: "ldrh — load FP16 (half-precision) from memory",
result_opcode: ArmOpcode::LDRH,
priority: 590,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "strh — store FP16 (half-precision) to memory",
result_opcode: ArmOpcode::STRH,
priority: 591,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "aese q.16b, q.16b — AES encrypt (ARM32 NEON crypto)",
result_opcode: ArmOpcode::AESE_Z,
priority: 600,
num_operands: 2,
imm_constraint: None,
is_two_address: true,
required_feature: Some("aes"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "aesd q.16b, q.16b — AES decrypt (ARM32 NEON crypto)",
result_opcode: ArmOpcode::AESD_Z,
priority: 601,
num_operands: 2,
imm_constraint: None,
is_two_address: true,
required_feature: Some("aes"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "aesmc q.16b, q.16b — AES mix columns (ARM32 NEON crypto)",
result_opcode: ArmOpcode::AESMC_Z,
priority: 602,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("aes"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "aesimc q.16b, q.16b — AES inv mix cols (ARM32 NEON crypto)",
result_opcode: ArmOpcode::AESIMC_Z,
priority: 603,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("aes"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3tt1a v.4s, v.4s, v.4s[lane] — SM3 TT1A indexed",
result_opcode: ArmOpcode::SM3TT1A_Z,
priority: 610,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3tt1b v.4s, v.4s, v.4s[lane] — SM3 TT1B indexed",
result_opcode: ArmOpcode::SM3TT1B_Z,
priority: 611,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3tt2a v.4s, v.4s, v.4s[lane] — SM3 TT2A indexed",
result_opcode: ArmOpcode::SM3TT2A_Z,
priority: 612,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sm3tt2b v.4s, v.4s, v.4s[lane] — SM3 TT2B indexed",
result_opcode: ArmOpcode::SM3TT2B_Z,
priority: 613,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: true,
required_feature: Some("sm3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha256h q.4s, q.4s, q.4s — SHA256 hash (ARM32 NEON)",
result_opcode: ArmOpcode::SHA256H_Z,
priority: 620,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha256h2 q.4s, q.4s, q.4s — SHA256 hash2 (ARM32 NEON)",
result_opcode: ArmOpcode::SHA256H2_Z,
priority: 621,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha256su0 q.4s, q.4s — SHA256 sched 0 (ARM32 NEON)",
result_opcode: ArmOpcode::SHA256SU0_Z,
priority: 622,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sha256su1 q.4s, q.4s, q.4s — SHA256 sched 1 (ARM32 NEON)",
result_opcode: ArmOpcode::SHA256SU1_Z,
priority: 623,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pldl1keep, [xn, xm] — range prefetch load L1 keep, register offset",
result_opcode: ArmOpcode::PRFM,
priority: 630,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pldl1strm, [xn, xm] — range prefetch load L1 stream, register offset",
result_opcode: ArmOpcode::PRFM,
priority: 631,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pldl2keep, [xn, xm] — range prefetch load L2 keep, register offset",
result_opcode: ArmOpcode::PRFM,
priority: 632,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pldl2strm, [xn, xm] — range prefetch load L2 stream, register offset",
result_opcode: ArmOpcode::PRFM,
priority: 633,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pldl3keep, [xn, xm] — range prefetch load L3 keep, register offset",
result_opcode: ArmOpcode::PRFM,
priority: 634,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pldl3strm, [xn, xm] — range prefetch load L3 stream, register offset",
result_opcode: ArmOpcode::PRFM,
priority: 635,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pstl1keep, [xn, xm] — range prefetch store L1 keep, register offset",
result_opcode: ArmOpcode::PRFM,
priority: 636,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rprfm pstl1strm, [xn, xm] — range prefetch store L1 stream, register offset",
result_opcode: ArmOpcode::PRFM,
priority: 637,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rprfm"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cipsw, xn — data cache clean+invalidate by set/way",
result_opcode: ArmOpcode::SYS,
priority: 640,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cisw, xn — data cache clean+invalidate set/way (alternate)",
result_opcode: ArmOpcode::SYS,
priority: 641,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "dc cvac, xn — data cache clean by VA to PoC (alternate)",
result_opcode: ArmOpcode::SYS,
priority: 642,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "f1cvt — FP8 to FP32 convert (1-element)",
result_opcode: ArmOpcode::F1CVT,
priority: 650,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp8"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "f2cvt — FP8 to FP32 convert (2-element)",
result_opcode: ArmOpcode::F2CVT,
priority: 651,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp8"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bf1cvt — BF8 to FP32 convert",
result_opcode: ArmOpcode::BF1CVT,
priority: 652,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp8"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "luti2 v.8b, {v.16b}, idx — 2-entry lookup table 8-bit",
result_opcode: ArmOpcode::LUTI2_8,
priority: 660,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsImm8),
is_two_address: false,
required_feature: Some("sme2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "luti2 v.16b, {v.16b}, idx — 2-entry lookup table 16-bit",
result_opcode: ArmOpcode::LUTI2_16,
priority: 661,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsImm8),
is_two_address: false,
required_feature: Some("sme2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "luti4 v.8b, {v.16b}, idx — 4-entry lookup table 8-bit",
result_opcode: ArmOpcode::LUTI4_8,
priority: 662,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsImm8),
is_two_address: false,
required_feature: Some("sme2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "luti4 v.16b, {v.16b}, idx — 4-entry lookup table 16-bit",
result_opcode: ArmOpcode::LUTI4_16,
priority: 663,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsImm8),
is_two_address: false,
required_feature: Some("sme2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "famin v.2s, v.2s, v.2s — FP32 abs min",
result_opcode: ArmOpcode::FAMIN_32,
priority: 670,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("faminmax"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "famax v.2s, v.2s, v.2s — FP32 abs max",
result_opcode: ArmOpcode::FAMAX_32,
priority: 671,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("faminmax"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "famin v.2d, v.2d, v.2d — FP64 abs min",
result_opcode: ArmOpcode::FAMIN_64,
priority: 672,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("faminmax"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "famax v.2d, v.2d, v.2d — FP64 abs max",
result_opcode: ArmOpcode::FAMAX_64,
priority: 673,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("faminmax"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sqrdcmlah v.4s, v.4s, v.4s, #0 — SSRD complex MLA rotate 0",
result_opcode: ArmOpcode::SQRDCMLA_SVE,
priority: 680,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sqrdcmlah v.4s, v.4s, v.4s, #90 — SSRD complex MLA rotate 90",
result_opcode: ArmOpcode::SQRDCMLA_SVE,
priority: 681,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sqrdcmlah v.4s, v.4s, v.4s, #180 — SSRD complex MLA rotate 180",
result_opcode: ArmOpcode::SQRDCMLA_SVE,
priority: 682,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sqrdcmlah v.4s, v.4s, v.4s, #270 — SSRD complex MLA rotate 270",
result_opcode: ArmOpcode::SQRDCMLA_SVE,
priority: 683,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4h, v.4h, v.4h, #0 — complex MLA rotate 0 (half vec)",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 690,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4h, v.4h, v.4h, #90 — complex MLA rotate 90 (half vec)",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 691,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4h, v.4h, v.4h, #180 — complex MLA rotate 180 (half vec)",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 692,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcmla v.4h, v.4h, v.4h, #270 — complex MLA rotate 270 (half vec)",
result_opcode: ArmOpcode::CMLA_SVE,
priority: 693,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPExt,
description: "fcvt s, h — convert half to single (scalar)",
result_opcode: ArmOpcode::FCVT,
priority: 700,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPTrunc,
description: "fcvt h, s — convert single to half (scalar)",
result_opcode: ArmOpcode::FCVT,
priority: 701,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPExt,
description: "fcvt d, h — convert half to double (scalar)",
result_opcode: ArmOpcode::FCVT,
priority: 702,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPTrunc,
description: "fcvt h, d — convert double to half (scalar)",
result_opcode: ArmOpcode::FCVT,
priority: 703,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("fp16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bfcvt — BFloat16 to FP32 convert (scalar)",
result_opcode: ArmOpcode::FCVT,
priority: 710,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bfcvtn — FP32 to BFloat16 convert (narrowing, scalar)",
result_opcode: ArmOpcode::FCVT,
priority: 711,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bfcvtn v.4h, v.4s — BFloat16 vector convert narrow",
result_opcode: ArmOpcode::FCVT,
priority: 715,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bfcvtn2 v.8h, v.4s — BFloat16 vector convert narrow 2",
result_opcode: ArmOpcode::FCVT,
priority: 716,
num_operands: 2,
imm_constraint: None,
is_two_address: true,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bfdot v.2s, v.4h, v.4h — BFloat16 dot product",
result_opcode: ArmOpcode::BFDOT_SME21,
priority: 717,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bfmlalb v.4s, v.8h, v.8h — BFloat16 multiply-add long bottom",
result_opcode: ArmOpcode::BFMOPA,
priority: 718,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bfmlalt v.4s, v.8h, v.8h — BFloat16 multiply-add long top",
result_opcode: ArmOpcode::BFMOPA,
priority: 719,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("bf16"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Xor,
description: "eor3 v.16b, v.16b, v.16b, v.16b — three-way exclusive OR",
result_opcode: ArmOpcode::EOR3,
priority: 730,
num_operands: 4,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bcax v.16b, v.16b, v.16b, v.16b — bit-clear XOR",
result_opcode: ArmOpcode::BCAX,
priority: 731,
num_operands: 4,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rax1 v.2d, v.2d, v.2d — rotate+accumulate+exchange 1",
result_opcode: ArmOpcode::RAX1_Z,
priority: 732,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sha3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "xar v.2d, v.2d, v.2d, #imm — XOR accumulate rotate",
result_opcode: ArmOpcode::XAR,
priority: 733,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsShiftAmount64),
is_two_address: true,
required_feature: Some("sha3"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "tbl v.8b, {v.16b, v.16b}, v.8b — 2-register table lookup 8b",
result_opcode: ArmOpcode::VTBL_2REG,
priority: 740,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "tbl v.8b, {v.16b, v.16b, v.16b}, v.8b — 3-register table lookup 8b",
result_opcode: ArmOpcode::VTBL_3REG,
priority: 741,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "tbl v.8b, {v.16b, v.16b, v.16b, v.16b}, v.8b — 4-register table lookup 8b",
result_opcode: ArmOpcode::VTBL_4REG,
priority: 742,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "tbx v.8b, {v.16b, v.16b}, v.8b — 2-register table lookup extend 8b",
result_opcode: ArmOpcode::VTBX_2REG,
priority: 743,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "tbx v.8b, {v.16b, v.16b, v.16b}, v.8b — 3-register table lookup extend 8b",
result_opcode: ArmOpcode::VTBX_3REG,
priority: 744,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "tbx v.8b, {v.16b..v.16b}, v.8b — 4-register table lookup extend 8b",
result_opcode: ArmOpcode::VTBX_4REG,
priority: 745,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sqrdmlah v.4s, v.4s, v.4s — saturating rounding doubling MLA",
result_opcode: ArmOpcode::SQRDMLAH,
priority: 750,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("rdma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sqrdmlsh v.4s, v.4s, v.4s — saturating rounding doubling MLS",
result_opcode: ArmOpcode::SQRDMLAH,
priority: 751,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("rdma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sqrdmlah v.8h, v.8h, v.8h — SSRD MLA half-precision",
result_opcode: ArmOpcode::SQRDMLAH,
priority: 752,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("rdma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sqrdmlsh v.8h, v.8h, v.8h — SSRD MLS half-precision",
result_opcode: ArmOpcode::SQRDMLAH,
priority: 753,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("rdma"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Add,
description: "sqcadd z.s, z.s, z.s — saturating complex int add",
result_opcode: ArmOpcode::SQCADD_SVE,
priority: 760,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sqrdcmlah z.s, z.s, z.s, #90 — SSRD complex MLA SVE rot 90",
result_opcode: ArmOpcode::SQRDCMLA_SVE,
priority: 761,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "sqrdcmlah z.s, z.s, z.s, #270 — SSRD complex MLA SVE rot 270",
result_opcode: ArmOpcode::SQRDCMLA_SVE,
priority: 762,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "histcnt z.s, p/z, z.s, z.s — SVE2 histogram count",
result_opcode: ArmOpcode::HISTCNT_SVE,
priority: 770,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "histseg z.b, p/z, z.b — SVE2 histogram segment",
result_opcode: ArmOpcode::HISTSEG_SVE,
priority: 771,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "match p.b, p/z, z.b, z.b — SVE2 character match",
result_opcode: ArmOpcode::MATCH_SVE,
priority: 772,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "nmatch p.b, p/z, z.b, z.b — SVE2 character non-match",
result_opcode: ArmOpcode::NMATCH_SVE,
priority: 773,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bext z.d, z.d, z.d — SVE2 bit extract",
result_opcode: ArmOpcode::BEXT_SVE,
priority: 774,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bdep z.d, z.d, z.d — SVE2 bit deposit",
result_opcode: ArmOpcode::BDEP_SVE,
priority: 775,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bgrp z.d, z.d, z.d — SVE2 bit group",
result_opcode: ArmOpcode::BGRP_SVE,
priority: 776,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcvtnt z.h, p/m, z.s — SVE2 FP convert narrowing top",
result_opcode: ArmOpcode::FCVTNT_SVE,
priority: 780,
num_operands: 2,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcvtlt z.s, p/m, z.h — SVE2 FP convert widening long top",
result_opcode: ArmOpcode::FCVTLT_SVE,
priority: 781,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcvtx z.s, p/m, z.d — SVE2 FP convert lowering precision",
result_opcode: ArmOpcode::FCVTX_SVE,
priority: 782,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "fcvtxnt z.s, p/m, z.d — SVE2 FP convert lowering precision narrowing top",
result_opcode: ArmOpcode::FCVTXNT_SVE,
priority: 783,
num_operands: 2,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Shl,
description: "sshr v.8b, v.8b, #imm — signed shift right 8-bit",
result_opcode: ArmOpcode::SSHR,
priority: 790,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsImm8),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::LShr,
description: "ushr v.8b, v.8b, #imm — unsigned shift right 8-bit",
result_opcode: ArmOpcode::USHR,
priority: 791,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsImm8),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Shl,
description: "sshr v.4h, v.4h, #imm — signed shift right 16-bit",
result_opcode: ArmOpcode::SSHR,
priority: 792,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsImm8),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::LShr,
description: "ushr v.4h, v.4h, #imm — unsigned shift right 16-bit",
result_opcode: ArmOpcode::USHR,
priority: 793,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsImm8),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Shl,
description: "sshr v.2s, v.2s, #imm — signed shift right 32-bit",
result_opcode: ArmOpcode::SSHR,
priority: 794,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::LShr,
description: "ushr v.2s, v.2s, #imm — unsigned shift right 32-bit",
result_opcode: ArmOpcode::USHR,
priority: 795,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsShiftAmount),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Shl,
description: "sshr v.2d, v.2d, #imm — signed shift right 64-bit",
result_opcode: ArmOpcode::SSHR,
priority: 796,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsShiftAmount64),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::LShr,
description: "ushr v.2d, v.2d, #imm — unsigned shift right 64-bit",
result_opcode: ArmOpcode::USHR,
priority: 797,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsShiftAmount64),
is_two_address: false,
required_feature: None,
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "irg xn, xn, xm — insert random tag",
result_opcode: ArmOpcode::IRG,
priority: 810,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "gmi xn, xn, xm — generate mask from index",
result_opcode: ArmOpcode::GMI,
priority: 811,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Add,
description: "addg xn, xn, #imm, #uimm4 — add with tag",
result_opcode: ArmOpcode::ADDG,
priority: 812,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Sub,
description: "subg xn, xn, #imm, #uimm4 — subtract with tag",
result_opcode: ArmOpcode::SUBG,
priority: 813,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsValidImm12),
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "ldg xn, [xn, #simm] — load allocation tag",
result_opcode: ArmOpcode::LDG,
priority: 814,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsSmallOffset),
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "stg xn, [xn, #simm] — store allocation tag",
result_opcode: ArmOpcode::STG,
priority: 815,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsSmallOffset),
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "stzg xn, [xn, #simm] — store zero tag",
result_opcode: ArmOpcode::STZG,
priority: 816,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsSmallOffset),
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "st2g xn, [xn, #simm] — store two tags",
result_opcode: ArmOpcode::ST2G,
priority: 817,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsSmallOffset),
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "stz2g xn, [xn, #simm] — store two zero tags",
result_opcode: ArmOpcode::STZ2G,
priority: 818,
num_operands: 2,
imm_constraint: Some(ImmConstraint::IsSmallOffset),
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "stgp xn, xn, [xn, #simm] — store tag+data pair",
result_opcode: ArmOpcode::STGP,
priority: 819,
num_operands: 3,
imm_constraint: Some(ImmConstraint::IsSmallOffset),
is_two_address: false,
required_feature: Some("mte"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "paciasp — PAC instruction address using SP (sign)",
result_opcode: ArmOpcode::PACIA,
priority: 830,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("pac"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "autiasp — AUT instruction address using SP (auth)",
result_opcode: ArmOpcode::AUTIA,
priority: 831,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("pac"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "xpaci — strip PAC from instruction address",
result_opcode: ArmOpcode::XPACI,
priority: 832,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("pac"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bti c — branch target identification (call)",
result_opcode: ArmOpcode::BTI,
priority: 840,
num_operands: 0,
imm_constraint: None,
is_two_address: false,
required_feature: Some("bti"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bti j — branch target identification (jump)",
result_opcode: ArmOpcode::BTI,
priority: 841,
num_operands: 0,
imm_constraint: None,
is_two_address: false,
required_feature: Some("bti"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "bti jc — branch target identification (jump+call)",
result_opcode: ArmOpcode::BTI,
priority: 842,
num_operands: 0,
imm_constraint: None,
is_two_address: false,
required_feature: Some("bti"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "retaa — return with pointer auth A",
result_opcode: ArmOpcode::RETAA,
priority: 843,
num_operands: 0,
imm_constraint: None,
is_two_address: false,
required_feature: Some("pac"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "retab — return with pointer auth B",
result_opcode: ArmOpcode::RETAB,
priority: 844,
num_operands: 0,
imm_constraint: None,
is_two_address: false,
required_feature: Some("pac"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_gran_delegate — RME granule delegate",
result_opcode: ArmOpcode::RMI_GRAN_DELEGATE,
priority: 860,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_gran_undelegate — RME granule undelegate",
result_opcode: ArmOpcode::RMI_GRAN_UNDELEGATE,
priority: 861,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_data_create — RME data granule create",
result_opcode: ArmOpcode::RMI_DATA_CREATE,
priority: 862,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_data_create_unknown — RME data granule create unknown",
result_opcode: ArmOpcode::RMI_DATA_CREATE_UNKNOWN,
priority: 863,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_data_destroy — RME data granule destroy",
result_opcode: ArmOpcode::RMI_DATA_DESTROY,
priority: 864,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_rec_create — RME REC create",
result_opcode: ArmOpcode::RMI_REC_CREATE,
priority: 865,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_rec_destroy — RME REC destroy",
result_opcode: ArmOpcode::RMI_REC_DESTROY,
priority: 866,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_realm_create — RME realm create",
result_opcode: ArmOpcode::RMI_REALM_CREATE,
priority: 867,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_realm_destroy — RME realm destroy",
result_opcode: ArmOpcode::RMI_REALM_DESTROY,
priority: 868,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_rtt_create — RME RTT create",
result_opcode: ArmOpcode::RMI_RTT_CREATE,
priority: 869,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_rtt_destroy — RME RTT destroy",
result_opcode: ArmOpcode::RMI_RTT_DESTROY,
priority: 870,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_rtt_init_ripas — RME RTT init RIPAS",
result_opcode: ArmOpcode::RMI_RTT_INIT_RIPAS,
priority: 871,
num_operands: 4,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_rtt_set_ripas — RME RTT set RIPAS",
result_opcode: ArmOpcode::RMI_RTT_SET_RIPAS,
priority: 872,
num_operands: 4,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_rtt_read_entry — RME RTT read entry",
result_opcode: ArmOpcode::RMI_RTT_READ_ENTRY,
priority: 873,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_rtt_fold — RME RTT fold",
result_opcode: ArmOpcode::RMI_RTT_FOLD,
priority: 874,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_features — RME features query",
result_opcode: ArmOpcode::RMI_FEATURES,
priority: 875,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "rmi_version — RME version query",
result_opcode: ArmOpcode::RMI_VERSION,
priority: 876,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("rme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Call,
description: "chkfeat x16 — check feature",
result_opcode: ArmOpcode::CHKFEAT,
priority: 880,
num_operands: 0,
imm_constraint: None,
is_two_address: false,
required_feature: Some("chk"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Add,
description: "sqadd z.b, p/m, z.b, z.b — saturating signed add 8-bit",
result_opcode: ArmOpcode::SQADD_Z,
priority: 890,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Sub,
description: "sqsub z.b, p/m, z.b, z.b — saturating signed sub 8-bit",
result_opcode: ArmOpcode::SQSUB_Z,
priority: 891,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Add,
description: "uqadd z.b, p/m, z.b, z.b — saturating unsigned add 8-bit",
result_opcode: ArmOpcode::UQADD_Z,
priority: 892,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Sub,
description: "uqsub z.b, p/m, z.b, z.b — saturating unsigned sub 8-bit",
result_opcode: ArmOpcode::UQSUB_Z,
priority: 893,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Add,
description: "suqadd z.b, p/m, z.b, z.b — signed add to unsigned saturating",
result_opcode: ArmOpcode::SUQADD_Z,
priority: 894,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Sub,
description: "usqadd z.b, p/m, z.b, z.b — unsigned add to signed saturating",
result_opcode: ArmOpcode::USQADD_Z,
priority: 895,
num_operands: 3,
imm_constraint: None,
is_two_address: true,
required_feature: Some("sve2"),
cond: None,
});
table
}
pub struct CompleteIselEngine {
pub patterns: Vec<IselPattern>,
pub has_fp16: bool,
pub has_aes: bool,
pub has_sha2: bool,
pub has_sha3: bool,
pub has_sm3: bool,
pub has_sm4: bool,
pub has_dotprod: bool,
pub has_i8mm: bool,
pub has_bf16: bool,
pub has_fcma: bool,
pub has_mte: bool,
pub has_rme: bool,
pub stats: IselStats,
}
impl CompleteIselEngine {
pub fn new(features: &HashMap<String, bool>) -> Self {
let patterns = build_complete_isel_table();
let opcode_map: HashMap<u32, u64> = patterns.iter()
.fold(HashMap::new(), |mut acc, p| {
*acc.entry(p.ir_opcode as u32).or_insert(0) += 1;
acc
});
let stats = IselStats {
total_lookups: 0,
matches: 0,
misses: 0,
fallthroughs: 0,
opcode_matches: opcode_map.clone(),
opcode_misses: HashMap::new(),
};
Self {
has_fp16: *features.get("fp16").unwrap_or(&false),
has_aes: *features.get("aes").unwrap_or(&false),
has_sha2: *features.get("sha2").unwrap_or(&false),
has_sha3: *features.get("sha3").unwrap_or(&false),
has_sm3: *features.get("sm3").unwrap_or(&false),
has_sm4: *features.get("sm4").unwrap_or(&false),
has_dotprod: *features.get("dotprod").unwrap_or(&false),
has_i8mm: *features.get("i8mm").unwrap_or(&false),
has_bf16: *features.get("bf16").unwrap_or(&false),
has_fcma: *features.get("fcma").unwrap_or(&false),
has_mte: *features.get("mte").unwrap_or(&false),
has_rme: *features.get("rme").unwrap_or(&false),
patterns,
stats,
}
}
pub fn lookup(&self, ir_opcode: Opcode) -> Vec<&IselPattern> {
self.patterns.iter().filter(|p| p.ir_opcode == ir_opcode).collect()
}
pub fn patterns_by_feature(&self, feature: &str) -> Vec<&IselPattern> {
self.patterns.iter().filter(|p| p.required_feature == Some(feature)).collect()
}
pub fn pattern_count(&self) -> usize {
self.patterns.len()
}
pub fn is_feature_available(&self, feature: &str) -> bool {
match feature {
"fp16" => self.has_fp16,
"aes" => self.has_aes,
"sha2" => self.has_sha2,
"sha3" => self.has_sha3,
"sm3" => self.has_sm3,
"sm4" => self.has_sm4,
"dotprod" => self.has_dotprod,
"i8mm" => self.has_i8mm,
"bf16" => self.has_bf16,
"fcma" => self.has_fcma,
"mte" => self.has_mte,
"rme" => self.has_rme,
"sve2" => true,
"sme2" => true,
_ => false,
}
}
pub fn coverage_report(&self) -> String {
let mut report = String::new();
report.push_str(&format!("Complete ISel — {} total patterns\n", self.patterns.len()));
report.push_str(&format!("FP16: {}, AES: {}, SHA2: {}, SHA3: {}\n",
self.has_fp16, self.has_aes, self.has_sha2, self.has_sha3));
report.push_str(&format!("SM3: {}, SM4: {}, DotProd: {}, I8MM: {}\n",
self.has_sm3, self.has_sm4, self.has_dotprod, self.has_i8mm));
report.push_str(&format!("BF16: {}, FCMA: {}, MTE: {}, RME: {}\n",
self.has_bf16, self.has_fcma, self.has_mte, self.has_rme));
let features = [
("fp16", self.has_fp16),
("aes", self.has_aes),
("sha2", self.has_sha2),
("sha3", self.has_sha3),
("sm3", self.has_sm3),
("sm4", self.has_sm4),
("dotprod", self.has_dotprod),
("i8mm", self.has_i8mm),
("bf16", self.has_bf16),
("fcma", self.has_fcma),
("mte", self.has_mte),
("rme", self.has_rme),
];
for (feat, enabled) in features.iter() {
if *enabled {
let count = self.patterns_by_feature(feat).len();
report.push_str(&format!(" {}: {} patterns\n", feat, count));
}
}
report
}
pub fn detailed_stats(&self) -> String {
format!(
"Complete ISel: {} patterns across 61 sections, features: fp16={} aes={} sha2={} sha3={} sm3={} sm4={} dotprod={} i8mm={} bf16={} fcma={} mte={} rme={}",
self.patterns.len(),
self.has_fp16, self.has_aes, self.has_sha2, self.has_sha3,
self.has_sm3, self.has_sm4, self.has_dotprod, self.has_i8mm,
self.has_bf16, self.has_fcma, self.has_mte, self.has_rme
)
}
}
impl Default for CompleteIselEngine {
fn default() -> Self {
let mut feats = HashMap::new();
feats.insert("fp16".to_string(), true);
feats.insert("aes".to_string(), true);
feats.insert("sha2".to_string(), true);
feats.insert("sha3".to_string(), true);
feats.insert("sm3".to_string(), true);
feats.insert("sm4".to_string(), true);
feats.insert("dotprod".to_string(), true);
feats.insert("i8mm".to_string(), true);
feats.insert("bf16".to_string(), true);
feats.insert("fcma".to_string(), true);
feats.insert("mte".to_string(), true);
feats.insert("rme".to_string(), true);
Self::new(&feats)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::opcode::Opcode;
fn make_features(enabled: bool) -> HashMap<String, bool> {
let mut feats = HashMap::new();
for feat in &["fp16", "aes", "sha2", "sha3", "sm3", "sm4", "dotprod", "i8mm", "bf16", "fcma", "mte", "rme"] {
feats.insert(feat.to_string(), enabled);
}
feats
}
#[test]
fn test_complete_table_not_empty() {
let table = build_complete_isel_table();
assert!(!table.is_empty(), "Complete ISel table should not be empty");
assert!(table.len() > 100, "Complete ISel table should have many patterns, got {}", table.len());
}
#[test]
fn test_aes_patterns_present() {
let table = build_complete_isel_table();
let aes_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("aes"))
.collect();
assert!(!aes_patterns.is_empty(), "Should have AES patterns");
}
#[test]
fn test_sha2_patterns_present() {
let table = build_complete_isel_table();
let sha2_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("sha2"))
.collect();
assert!(!sha2_patterns.is_empty(), "Should have SHA2 patterns");
}
#[test]
fn test_sha3_patterns_present() {
let table = build_complete_isel_table();
let sha3_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("sha3"))
.collect();
assert!(!sha3_patterns.is_empty(), "Should have SHA3 patterns");
}
#[test]
fn test_sm3_patterns_present() {
let table = build_complete_isel_table();
let sm3_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("sm3"))
.collect();
assert!(sm3_patterns.len() >= 7, "Should have 7+ SM3 patterns, got {}", sm3_patterns.len());
}
#[test]
fn test_sm4_patterns_present() {
let table = build_complete_isel_table();
let sm4_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("sm4"))
.collect();
assert!(sm4_patterns.len() >= 2, "Should have 2+ SM4 patterns, got {}", sm4_patterns.len());
}
#[test]
fn test_fp16_patterns_present() {
let table = build_complete_isel_table();
let fp16_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("fp16"))
.collect();
assert!(fp16_patterns.len() >= 20, "Should have 20+ FP16 patterns, got {}", fp16_patterns.len());
}
#[test]
fn test_dotprod_patterns_present() {
let table = build_complete_isel_table();
let dp_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("dotprod"))
.collect();
assert!(dp_patterns.len() >= 4, "Should have 4+ dot product patterns, got {}", dp_patterns.len());
}
#[test]
fn test_i8mm_patterns_present() {
let table = build_complete_isel_table();
let i8mm_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("i8mm"))
.collect();
assert!(i8mm_patterns.len() >= 6, "Should have 6+ i8mm patterns, got {}", i8mm_patterns.len());
}
#[test]
fn test_bf16_patterns_present() {
let table = build_complete_isel_table();
let bf16_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("bf16"))
.collect();
assert!(!bf16_patterns.is_empty(), "Should have BF16 patterns");
}
#[test]
fn test_fcma_patterns_present() {
let table = build_complete_isel_table();
let fcma_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("fcma"))
.collect();
assert!(fcma_patterns.len() >= 8, "Should have 8+ FCMA patterns, got {}", fcma_patterns.len());
}
#[test]
fn test_mte_patterns_present() {
let table = build_complete_isel_table();
let mte_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("mte"))
.collect();
assert!(mte_patterns.len() >= 8, "Should have 8+ MTE patterns, got {}", mte_patterns.len());
}
#[test]
fn test_rme_patterns_present() {
let table = build_complete_isel_table();
let rme_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("rme"))
.collect();
assert!(rme_patterns.len() >= 15, "Should have 15+ RME patterns, got {}", rme_patterns.len());
}
#[test]
fn test_prfm_patterns_present() {
let table = build_complete_isel_table();
let prfm_patterns: Vec<_> = table.iter()
.filter(|p| p.result_opcode == ArmOpcode::PRFM)
.collect();
assert!(prfm_patterns.len() >= 20, "Should have 20+ PRFM patterns, got {}", prfm_patterns.len());
}
#[test]
fn test_dc_patterns_present() {
let table = build_complete_isel_table();
let dc_patterns: Vec<_> = table.iter()
.filter(|p| p.result_opcode == ArmOpcode::SYS)
.collect();
assert!(dc_patterns.len() >= 20, "Should have 20+ DC/SYS patterns, got {}", dc_patterns.len());
}
#[test]
fn test_engine_lookup() {
let engine = CompleteIselEngine::default();
let results = engine.lookup(Opcode::Call);
assert!(!results.is_empty(), "Should find patterns for Call opcode");
}
#[test]
fn test_engine_patterns_by_feature() {
let engine = CompleteIselEngine::default();
let fp16 = engine.patterns_by_feature("fp16");
assert!(!fp16.is_empty(), "Should find FP16 patterns");
}
#[test]
fn test_engine_is_feature_available() {
let engine = CompleteIselEngine::default();
assert!(engine.is_feature_available("fp16"));
assert!(engine.is_feature_available("aes"));
assert!(engine.is_feature_available("fcma"));
assert!(!engine.is_feature_available("nonexistent"));
}
#[test]
fn test_engine_coverage_report() {
let engine = CompleteIselEngine::default();
let report = engine.coverage_report();
assert!(report.contains("Complete ISel"));
assert!(report.contains("FP16"));
assert!(report.contains("AES"));
assert!(report.contains("SHA2"));
}
#[test]
fn test_engine_detailed_stats() {
let engine = CompleteIselEngine::default();
let stats = engine.detailed_stats();
assert!(stats.contains("Complete ISel"));
assert!(stats.contains("fp16=true"));
assert!(stats.contains("aes=true"));
}
#[test]
fn test_feature_guard_fp16_disabled() {
let mut feats = make_features(true);
feats.insert("fp16".to_string(), false);
let engine = CompleteIselEngine::new(&feats);
assert!(!engine.has_fp16);
let fp16 = engine.patterns_by_feature("fp16");
assert!(!fp16.is_empty(), "Patterns exist but feature is disabled");
}
#[test]
fn test_feature_guard_aes_disabled() {
let mut feats = make_features(true);
feats.insert("aes".to_string(), false);
let engine = CompleteIselEngine::new(&feats);
assert!(!engine.has_aes);
}
#[test]
fn test_frint_patterns_present() {
let table = build_complete_isel_table();
let frint_patterns: Vec<_> = table.iter()
.filter(|p| p.required_feature == Some("frintts"))
.collect();
assert!(frint_patterns.len() >= 4, "Should have 4+ FRINT32/64 patterns, got {}", frint_patterns.len());
}
#[test]
fn test_fcadd_all_rotations() {
let engine = CompleteIselEngine::default();
let fcadd_patterns: Vec<_> = engine.patterns.iter()
.filter(|p| p.result_opcode == ArmOpcode::CADD_SVE)
.collect();
assert!(fcadd_patterns.len() >= 4, "Should have 4+ FCADD patterns, got {}", fcadd_patterns.len());
}
#[test]
fn test_fcmla_all_rotations() {
let engine = CompleteIselEngine::default();
let fcmla_patterns: Vec<_> = engine.patterns.iter()
.filter(|p| p.result_opcode == ArmOpcode::CMLA_SVE)
.collect();
assert!(fcmla_patterns.len() >= 8, "Should have 8+ FCMLA patterns, got {}", fcmla_patterns.len());
}
#[test]
fn test_table_all_patterns_have_descriptions() {
let table = build_complete_isel_table();
for pattern in &table {
assert!(!pattern.description.is_empty(),
"Pattern with opcode {:?} should have a description", pattern.ir_opcode);
}
}
#[test]
fn test_table_all_patterns_have_valid_opcodes() {
let table = build_complete_isel_table();
for pattern in &table {
assert!(pattern.priority > 0,
"Pattern should have positive priority: {:?}", pattern.description);
assert!(pattern.num_operands <= 4,
"Pattern should have <= 4 operands: {:?}", pattern.description);
}
}
#[test]
fn test_eor3_rax1_xar_patterns() {
let engine = CompleteIselEngine::default();
let sha3_extra: Vec<_> = engine.patterns.iter()
.filter(|p| p.result_opcode == ArmOpcode::EOR3
|| p.result_opcode == ArmOpcode::BCAX
|| p.result_opcode == ArmOpcode::RAX1_Z
|| p.result_opcode == ArmOpcode::XAR)
.collect();
assert!(sha3_extra.len() >= 4, "Should have EOR3/BCAX/RAX1/XAR patterns, got {}", sha3_extra.len());
}
#[test]
fn test_fp16_convert_patterns() {
let engine = CompleteIselEngine::default();
let fpext_patterns: Vec<_> = engine.lookup(Opcode::FPExt);
let fptrunc_patterns: Vec<_> = engine.lookup(Opcode::FPTrunc);
let total = fpext_patterns.len() + fptrunc_patterns.len();
assert!(total >= 4, "Should have FP16 convert patterns (FPExt+FPTrunc), got {}", total);
}
#[test]
fn test_matrix_multiply_patterns() {
let engine = CompleteIselEngine::default();
let mma_patterns: Vec<_> = engine.patterns.iter()
.filter(|p| p.result_opcode == ArmOpcode::SMMLA
|| p.result_opcode == ArmOpcode::UMMLA
|| p.result_opcode == ArmOpcode::USMMLA)
.collect();
assert!(mma_patterns.len() >= 5, "Should have 5+ MMA patterns, got {}", mma_patterns.len());
}
#[test]
fn test_lookup_table_patterns() {
let engine = CompleteIselEngine::default();
let lut: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::LUTI2_8 | ArmOpcode::LUTI2_16 |
ArmOpcode::LUTI4_8 | ArmOpcode::LUTI4_16))
.collect();
assert!(lut.len() >= 4, "Should have 4 LUTI patterns, got {}", lut.len());
}
#[test]
fn test_faminmax_patterns() {
let engine = CompleteIselEngine::default();
let fam: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::FAMIN_32 | ArmOpcode::FAMAX_32 |
ArmOpcode::FAMIN_64 | ArmOpcode::FAMAX_64))
.collect();
assert!(fam.len() >= 4, "Should have 4 FAMINMAX patterns, got {}", fam.len());
}
#[test]
fn test_sve2_hist_patterns() {
let engine = CompleteIselEngine::default();
let hist: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::HISTCNT_SVE | ArmOpcode::HISTSEG_SVE
| ArmOpcode::MATCH_SVE | ArmOpcode::NMATCH_SVE))
.collect();
assert!(hist.len() >= 4, "Should have 4 SVE2 hist/match patterns, got {}", hist.len());
}
#[test]
fn test_sve2_bit_patterns() {
let engine = CompleteIselEngine::default();
let bit: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::BEXT_SVE | ArmOpcode::BDEP_SVE
| ArmOpcode::BGRP_SVE))
.collect();
assert!(bit.len() >= 3, "Should have 3 SVE2 bit patterns, got {}", bit.len());
}
#[test]
fn test_sve2_fp_narrowing_patterns() {
let engine = CompleteIselEngine::default();
let fp: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::FCVTNT_SVE | ArmOpcode::FCVTLT_SVE
| ArmOpcode::FCVTX_SVE | ArmOpcode::FCVTXNT_SVE))
.collect();
assert!(fp.len() >= 4, "Should have 4 SVE2 FP narrow/wide patterns, got {}", fp.len());
}
#[test]
fn test_tbl_tbx_patterns() {
let engine = CompleteIselEngine::default();
let tbl: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::VTBL_2REG | ArmOpcode::VTBL_3REG
| ArmOpcode::VTBL_4REG | ArmOpcode::VTBX_2REG | ArmOpcode::VTBX_3REG
| ArmOpcode::VTBX_4REG))
.collect();
assert!(tbl.len() >= 6, "Should have 6 TBL/TBX patterns, got {}", tbl.len());
}
#[test]
fn test_sqrdmlah_patterns() {
let engine = CompleteIselEngine::default();
let sqrd: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::SQRDMLAH))
.collect();
assert!(sqrd.len() >= 4, "Should have 4 SQRDMLAH patterns, got {}", sqrd.len());
}
#[test]
fn test_saturating_patterns() {
let engine = CompleteIselEngine::default();
let sat: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::SQADD_Z | ArmOpcode::SQSUB_Z
| ArmOpcode::UQADD_Z | ArmOpcode::UQSUB_Z | ArmOpcode::SUQADD_Z
| ArmOpcode::USQADD_Z))
.collect();
assert!(sat.len() >= 6, "Should have 6 saturating patterns, got {}", sat.len());
}
#[test]
fn test_bti_patterns() {
let engine = CompleteIselEngine::default();
let bti: Vec<_> = engine.patterns.iter()
.filter(|p| p.result_opcode == ArmOpcode::BTI)
.collect();
assert!(bti.len() >= 3, "Should have 3+ BTI patterns, got {}", bti.len());
}
#[test]
fn test_pac_patterns() {
let engine = CompleteIselEngine::default();
let pac: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::PACIA | ArmOpcode::AUTIA
| ArmOpcode::XPACI | ArmOpcode::RETAA | ArmOpcode::RETAB))
.collect();
assert!(pac.len() >= 4, "Should have 4+ PAC patterns, got {}", pac.len());
}
#[test]
fn test_fp8_patterns() {
let engine = CompleteIselEngine::default();
let fp8: Vec<_> = engine.patterns.iter()
.filter(|p| p.required_feature == Some("fp8"))
.collect();
assert!(fp8.len() >= 3, "Should have 3+ FP8 patterns, got {}", fp8.len());
}
#[test]
fn test_bfdot_patterns() {
let engine = CompleteIselEngine::default();
let bfdot: Vec<_> = engine.patterns.iter()
.filter(|p| matches!(p.result_opcode, ArmOpcode::BFDOT_SME21))
.collect();
assert!(bfdot.len() >= 3, "Should have 3+ BFDOT patterns, got {}", bfdot.len());
}
#[test]
fn test_fdot_patterns() {
let engine = CompleteIselEngine::default();
let fdot: Vec<_> = engine.patterns.iter()
.filter(|p| p.result_opcode == ArmOpcode::FDOT_Z)
.collect();
assert!(fdot.len() >= 2, "Should have 2+ FDOT patterns, got {}", fdot.len());
}
}