use crate::arm::arm_instr_info::ArmOpcode;
use crate::opcode::Opcode;
use std::collections::HashMap;
use super::arm_isel_table::{AArch64AddrMode, ImmConstraint, IselOperand, IselPattern, IselStats};
pub struct SVEIselTable {
pub patterns: Vec<IselPattern>,
pub stats: IselStats,
}
pub fn sve_isel_table() -> Vec<IselPattern> {
let mut table = Vec::new();
table.push(IselPattern {
ir_opcode: Opcode::Add,
description: "add z.s, p/m, z.s, z.s — SVE predicated int add 32-bit",
result_opcode: ArmOpcode::ADD_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Add,
description: "add z.d, p/m, z.d, z.d — SVE predicated int add 64-bit",
result_opcode: ArmOpcode::ADD_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Sub,
description: "sub z.s, p/m, z.s, z.s — SVE predicated int sub 32-bit",
result_opcode: ArmOpcode::SUB_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Sub,
description: "sub z.d, p/m, z.d, z.d — SVE predicated int sub 64-bit",
result_opcode: ArmOpcode::SUB_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "mul z.s, p/m, z.s, z.s — SVE predicated int mul 32-bit",
result_opcode: ArmOpcode::MUL_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "mul z.d, p/m, z.d, z.d — SVE predicated int mul 64-bit",
result_opcode: ArmOpcode::MUL_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fadd z.s, p/m, z.s, z.s — SVE predicated FP add 32-bit",
result_opcode: ArmOpcode::FADD_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fadd z.d, p/m, z.d, z.d — SVE predicated FP add 64-bit",
result_opcode: ArmOpcode::FADD_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "fsub z.s, p/m, z.s, z.s — SVE predicated FP sub 32-bit",
result_opcode: ArmOpcode::FSUB_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "fsub z.d, p/m, z.d, z.d — SVE predicated FP sub 64-bit",
result_opcode: ArmOpcode::FSUB_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FMul,
description: "fmul z.s, p/m, z.s, z.s — SVE predicated FP mul 32-bit",
result_opcode: ArmOpcode::FMUL_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FMul,
description: "fmul z.d, p/m, z.d, z.d — SVE predicated FP mul 64-bit",
result_opcode: ArmOpcode::FMUL_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FDiv,
description: "fdiv z.s, p/m, z.s, z.s — SVE predicated FP div 32-bit",
result_opcode: ArmOpcode::FDIV_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FDiv,
description: "fdiv z.d, p/m, z.d, z.d — SVE predicated FP div 64-bit",
result_opcode: ArmOpcode::FDIV_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "fmax z.s, p/m, z.s, z.s — SVE predicated FP max 32-bit",
result_opcode: ArmOpcode::FMAX_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "fmax z.d, p/m, z.d, z.d — SVE predicated FP max 64-bit",
result_opcode: ArmOpcode::FMAX_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "fmin z.s, p/m, z.s, z.s — SVE predicated FP min 32-bit",
result_opcode: ArmOpcode::FMIN_Z,
priority: 102,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "fmin z.d, p/m, z.d, z.d — SVE predicated FP min 64-bit",
result_opcode: ArmOpcode::FMIN_Z,
priority: 103,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smax z.s, p/m, z.s, z.s — SVE predicated signed max 32-bit",
result_opcode: ArmOpcode::SMAX_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smax z.d, p/m, z.d, z.d — SVE predicated signed max 64-bit",
result_opcode: ArmOpcode::SMAX_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smin z.s, p/m, z.s, z.s — SVE predicated signed min 32-bit",
result_opcode: ArmOpcode::SMIN_Z,
priority: 102,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smin z.d, p/m, z.d, z.d — SVE predicated signed min 64-bit",
result_opcode: ArmOpcode::SMIN_Z,
priority: 103,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "umax z.s, p/m, z.s, z.s — SVE predicated unsigned max 32-bit",
result_opcode: ArmOpcode::UMAX_Z,
priority: 104,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "umax z.d, p/m, z.d, z.d — SVE predicated unsigned max 64-bit",
result_opcode: ArmOpcode::UMAX_Z,
priority: 105,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "umin z.s, p/m, z.s, z.s — SVE predicated unsigned min 32-bit",
result_opcode: ArmOpcode::UMIN_Z,
priority: 106,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "umin z.d, p/m, z.d, z.d — SVE predicated unsigned min 64-bit",
result_opcode: ArmOpcode::UMIN_Z,
priority: 107,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmpeq p.s, p/z, z.s, z.s — SVE int compare equal 32-bit",
result_opcode: ArmOpcode::CMPEQ_P,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmpeq p.d, p/z, z.d, z.d — SVE int compare equal 64-bit",
result_opcode: ArmOpcode::CMPEQ_P,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmpgt p.s, p/z, z.s, z.s — SVE int signed greater-than 32-bit",
result_opcode: ArmOpcode::CMPGT_P,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmpgt p.d, p/z, z.d, z.d — SVE int signed greater-than 64-bit",
result_opcode: ArmOpcode::CMPGT_P,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmpge p.s, p/z, z.s, z.s — SVE int signed greater-equal 32-bit",
result_opcode: ArmOpcode::CMPGE_P,
priority: 104,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmpge p.d, p/z, z.d, z.d — SVE int signed greater-equal 64-bit",
result_opcode: ArmOpcode::CMPGE_P,
priority: 105,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmphi p.s, p/z, z.s, z.s — SVE int unsigned higher 32-bit",
result_opcode: ArmOpcode::CMPHI_P,
priority: 106,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmphi p.d, p/z, z.d, z.d — SVE int unsigned higher 64-bit",
result_opcode: ArmOpcode::CMPHI_P,
priority: 107,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmphs p.s, p/z, z.s, z.s — SVE int unsigned higher-or-same 32-bit",
result_opcode: ArmOpcode::CMPHS_P,
priority: 108,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "cmphs p.d, p/z, z.d, z.d — SVE int unsigned higher-or-same 64-bit",
result_opcode: ArmOpcode::CMPHS_P,
priority: 109,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FCmp,
description: "fcmeq p.s, p/z, z.s, z.s — SVE FP compare equal 32-bit",
result_opcode: ArmOpcode::FCMEQ_P,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FCmp,
description: "fcmeq p.d, p/z, z.d, z.d — SVE FP compare equal 64-bit",
result_opcode: ArmOpcode::FCMEQ_P,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FCmp,
description: "fcmgt p.s, p/z, z.s, z.s — SVE FP compare greater-than 32-bit",
result_opcode: ArmOpcode::FCMGT_P,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FCmp,
description: "fcmgt p.d, p/z, z.d, z.d — SVE FP compare greater-than 64-bit",
result_opcode: ArmOpcode::FCMGT_P,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FCmp,
description: "fcmge p.s, p/z, z.s, z.s — SVE FP compare greater-equal 32-bit",
result_opcode: ArmOpcode::FCMGE_P,
priority: 104,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FCmp,
description: "fcmge p.d, p/z, z.d, z.d — SVE FP compare greater-equal 64-bit",
result_opcode: ArmOpcode::FCMGE_P,
priority: 105,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Add,
description: "addv s, p, z.s — SVE add across vector 32-bit",
result_opcode: ArmOpcode::ADDV_Z,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Add,
description: "addv d, p, z.d — SVE add across vector 64-bit",
result_opcode: ArmOpcode::ADDV_Z,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smaxv s, p, z.s — SVE signed max across vector 32-bit",
result_opcode: ArmOpcode::SMAXV_Z,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smaxv d, p, z.d — SVE signed max across vector 64-bit",
result_opcode: ArmOpcode::SMAXV_Z,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "umaxv s, p, z.s — SVE unsigned max across vector 32-bit",
result_opcode: ArmOpcode::UMAXV_Z,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "umaxv d, p, z.d — SVE unsigned max across vector 64-bit",
result_opcode: ArmOpcode::UMAXV_Z,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "sminv s, p, z.s — SVE signed min across vector 32-bit",
result_opcode: ArmOpcode::SMINV_Z,
priority: 104,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "uminv s, p, z.s — SVE unsigned min across vector 32-bit",
result_opcode: ArmOpcode::UMINV_Z,
priority: 105,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "faddv s, p, z.s — SVE FP add across vector 32-bit",
result_opcode: ArmOpcode::FADDV_Z,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "faddv d, p, z.d — SVE FP add across vector 64-bit",
result_opcode: ArmOpcode::FADDV_Z,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fmaxv s, p, z.s — SVE FP max across vector 32-bit",
result_opcode: ArmOpcode::FMAXV_Z,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fminv s, p, z.s — SVE FP min across vector 32-bit",
result_opcode: ArmOpcode::FMINV_Z,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fmaxnmv s, p, z.s — SVE FP IEEE max across vector 32-bit",
result_opcode: ArmOpcode::FMAXNMV_Z,
priority: 104,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fminnmv s, p, z.s — SVE FP IEEE min across vector 32-bit",
result_opcode: ArmOpcode::FMINNMV_Z,
priority: 105,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Load,
description: "ld1b z.b, p/z, [x] — SVE load bytes",
result_opcode: ArmOpcode::LD1B_Z,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Load,
description: "ld1h z.h, p/z, [x] — SVE load halfwords",
result_opcode: ArmOpcode::LD1H_Z,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Load,
description: "ld1w z.s, p/z, [x] — SVE load words",
result_opcode: ArmOpcode::LD1W_Z,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Load,
description: "ld1d z.d, p/z, [x] — SVE load doublewords",
result_opcode: ArmOpcode::LD1D_Z,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "st1b z.b, p, [x] — SVE store bytes",
result_opcode: ArmOpcode::ST1B_Z,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "st1h z.h, p, [x] — SVE store halfwords",
result_opcode: ArmOpcode::ST1H_Z,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "st1w z.s, p, [x] — SVE store words",
result_opcode: ArmOpcode::ST1W_Z,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "st1d z.d, p, [x] — SVE store doublewords",
result_opcode: ArmOpcode::ST1D_Z,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Load,
description: "ld1w z.s, p/z, [x, z.s, uxtw #2] — SVE gather words scaled 32-bit index",
result_opcode: ArmOpcode::LD1W_GATHER_Z,
priority: 110,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Load,
description: "ld1d z.d, p/z, [x, z.d, lsl #3] — SVE gather doublewords scaled 64-bit index",
result_opcode: ArmOpcode::LD1D_GATHER_Z,
priority: 111,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "st1w z.s, p, [x, z.s, uxtw #2] — SVE scatter words scaled 32-bit index",
result_opcode: ArmOpcode::ST1W_SCATTER_Z,
priority: 112,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "st1d z.d, p, [x, z.d, lsl #3] — SVE scatter doublewords scaled 64-bit index",
result_opcode: ArmOpcode::ST1D_SCATTER_Z,
priority: 113,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ShuffleVector,
description: "tbl z.s, z.s, z.s — SVE table lookup 32-bit",
result_opcode: ArmOpcode::TBL_Z,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ShuffleVector,
description: "zip1 z.s, z.s, z.s — SVE interleave lo 32-bit",
result_opcode: ArmOpcode::ZIP1_Z,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ShuffleVector,
description: "zip2 z.s, z.s, z.s — SVE interleave hi 32-bit",
result_opcode: ArmOpcode::ZIP2_Z,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ShuffleVector,
description: "uzp1 z.s, z.s, z.s — SVE deinterleave lo 32-bit",
result_opcode: ArmOpcode::UZP1_Z,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ShuffleVector,
description: "uzp2 z.s, z.s, z.s — SVE deinterleave hi 32-bit",
result_opcode: ArmOpcode::UZP2_Z,
priority: 104,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ShuffleVector,
description: "trn1 z.s, z.s, z.s — SVE transpose lo 32-bit",
result_opcode: ArmOpcode::TRN1_Z,
priority: 105,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ShuffleVector,
description: "trn2 z.s, z.s, z.s — SVE transpose hi 32-bit",
result_opcode: ArmOpcode::TRN2_Z,
priority: 106,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ShuffleVector,
description: "rev z.s, p/m, z.s — SVE reverse elements 32-bit",
result_opcode: ArmOpcode::REV_Z,
priority: 107,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::SExt,
description: "sunpklo z.h, z.b — SVE unsigned unpack lo",
result_opcode: ArmOpcode::SUNPKLO_Z,
priority: 108,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::SExt,
description: "sunpkhi z.h, z.b — SVE unsigned unpack hi",
result_opcode: ArmOpcode::SUNPKHI_Z,
priority: 109,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ZExt,
description: "uunpklo z.h, z.b — SVE unsigned unpack lo",
result_opcode: ArmOpcode::UUNPKLO_Z,
priority: 110,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ZExt,
description: "uunpkhi z.h, z.b — SVE unsigned unpack hi",
result_opcode: ArmOpcode::UUNPKHI_Z,
priority: 111,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::InsertElement,
description: "dup z.s, x — SVE broadcast scalar to vector 32-bit",
result_opcode: ArmOpcode::DUP_Z,
priority: 100,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::InsertElement,
description: "dup z.d, x — SVE broadcast scalar to vector 64-bit",
result_opcode: ArmOpcode::DUP_Z,
priority: 101,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::InsertElement,
description: "index z.s, x, x — SVE create index vector 32-bit",
result_opcode: ArmOpcode::INDEX_Z,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::InsertElement,
description: "index z.d, x, x — SVE create index vector 64-bit",
result_opcode: ArmOpcode::INDEX_Z,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::And,
description: "and p.b, p/z, p.b, p.b — SVE predicate AND",
result_opcode: ArmOpcode::AND_P,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Or,
description: "orr p.b, p/z, p.b, p.b — SVE predicate ORR",
result_opcode: ArmOpcode::ORR_P,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Xor,
description: "eor p.b, p/z, p.b, p.b — SVE predicate EOR",
result_opcode: ArmOpcode::EOR_P,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::And,
description: "bic p.b, p/z, p.b, p.b — SVE predicate BIC",
result_opcode: ArmOpcode::BIC_P,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::And,
description: "ptrue p.s — SVE all-true predicate 32-bit elements",
result_opcode: ArmOpcode::PTRUE,
priority: 110,
num_operands: 0,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::And,
description: "ptest p.b, p.b — SVE test predicate",
result_opcode: ArmOpcode::PTEST,
priority: 111,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "whilelt p.s, x, x — SVE while less-than predicate 32-bit",
result_opcode: ArmOpcode::WHILELT,
priority: 120,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "whilele p.s, x, x — SVE while less-or-equal predicate 32-bit",
result_opcode: ArmOpcode::WHILELE,
priority: 121,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "whilegt p.s, x, x — SVE while greater-than predicate 32-bit",
result_opcode: ArmOpcode::WHILEGT,
priority: 122,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::ICmp,
description: "whilege p.s, x, x — SVE while greater-or-equal predicate 32-bit",
result_opcode: ArmOpcode::WHILEGE,
priority: 123,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fmopa za.s, p/m, z.s, z.s — SME FP outer product accumulate 32-bit",
result_opcode: ArmOpcode::FMOPA,
priority: 200,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FAdd,
description: "fmops za.s, p/m, z.s, z.s — SME FP outer product single 32-bit",
result_opcode: ArmOpcode::FMOPS,
priority: 201,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smopa za.s, p/m, z.b, z.b — SME signed outer product accumulate",
result_opcode: ArmOpcode::SMOPA,
priority: 202,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Mul,
description: "smops za.s, p/m, z.b, z.b — SME signed outer product single",
result_opcode: ArmOpcode::SMOPS,
priority: 203,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "zero {za} — SME clear ZA array",
result_opcode: ArmOpcode::ZERO_ZA,
priority: 200,
num_operands: 0,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "str za.s, [x] — SME store ZA tile",
result_opcode: ArmOpcode::STR_ZA,
priority: 201,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Load,
description: "ldr za.s, [x] — SME load ZA tile",
result_opcode: ArmOpcode::LDR_ZA,
priority: 202,
num_operands: 1,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Load,
description: "mova z.s, p/m, za.s[w12, 0:1] — SME MOVA tile to vector",
result_opcode: ArmOpcode::MOVA_ZA,
priority: 200,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Store,
description: "mova za.s[w12, 0:1], p/m, z.s — SME MOVA vector to tile",
result_opcode: ArmOpcode::MOVA_ZA,
priority: 201,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sme"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::SIToFP,
description: "scvtf z.s, p/m, z.s — SVE signed int to float 32-bit",
result_opcode: ArmOpcode::SCVTF_Z,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::UIToFP,
description: "ucvtf z.s, p/m, z.s — SVE unsigned int to float 32-bit",
result_opcode: ArmOpcode::UCVTF_Z,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPToSI,
description: "fcvtzs z.s, p/m, z.s — SVE float to signed int 32-bit",
result_opcode: ArmOpcode::FCVTZS_Z,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPToUI,
description: "fcvtzu z.s, p/m, z.s — SVE float to unsigned int 32-bit",
result_opcode: ArmOpcode::FCVTZU_Z,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FPExt,
description: "fcvt z.d, p/m, z.s — SVE FP widen 32→64-bit",
result_opcode: ArmOpcode::FCVT_Z,
priority: 104,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Sub,
description: "abs z.s, p/m, z.s — SVE int absolute value 32-bit",
result_opcode: ArmOpcode::ABS_Z,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Sub,
description: "neg z.s, p/m, z.s — SVE int negate 32-bit",
result_opcode: ArmOpcode::NEG_Z,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "fabs z.s, p/m, z.s — SVE FP absolute value 32-bit",
result_opcode: ArmOpcode::FABS_Z,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "fneg z.s, p/m, z.s — SVE FP negate 32-bit",
result_opcode: ArmOpcode::FNEG_Z,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FDiv,
description: "fsqrt z.s, p/m, z.s — SVE FP sqrt 32-bit",
result_opcode: ArmOpcode::FSQRT_Z,
priority: 104,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "frintz z.s, p/m, z.s — SVE FP round toward zero 32-bit",
result_opcode: ArmOpcode::FRINTZ_Z,
priority: 105,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "frintm z.s, p/m, z.s — SVE FP round toward minus infinity 32-bit",
result_opcode: ArmOpcode::FRINTM_Z,
priority: 106,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "frintp z.s, p/m, z.s — SVE FP round toward plus infinity 32-bit",
result_opcode: ArmOpcode::FRINTP_Z,
priority: 107,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::FSub,
description: "frintn z.s, p/m, z.s — SVE FP round to nearest even 32-bit",
result_opcode: ArmOpcode::FRINTN_Z,
priority: 108,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::And,
description: "and z.d, z.d, z.d — SVE bitwise AND 64-bit",
result_opcode: ArmOpcode::AND_Z,
priority: 100,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Or,
description: "orr z.d, z.d, z.d — SVE bitwise ORR 64-bit",
result_opcode: ArmOpcode::ORR_Z,
priority: 101,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Xor,
description: "eor z.d, z.d, z.d — SVE bitwise EOR 64-bit",
result_opcode: ArmOpcode::EOR_Z,
priority: 102,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::And,
description: "bic z.d, z.d, z.d — SVE bitwise BIC 64-bit",
result_opcode: ArmOpcode::BIC_Z,
priority: 103,
num_operands: 2,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::Shl,
description: "lsl z.s, p/m, z.s, z.s — SVE shift left variable 32-bit",
result_opcode: ArmOpcode::LSL_Z,
priority: 100,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::LShr,
description: "lsr z.s, p/m, z.s, z.s — SVE shift right variable 32-bit",
result_opcode: ArmOpcode::LSR_Z,
priority: 101,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table.push(IselPattern {
ir_opcode: Opcode::AShr,
description: "asr z.s, p/m, z.s, z.s — SVE arithmetic shift right variable 32-bit",
result_opcode: ArmOpcode::ASR_Z,
priority: 102,
num_operands: 3,
imm_constraint: None,
is_two_address: false,
required_feature: Some("sve"),
cond: None,
});
table
}
pub struct SVEIselEngine {
pub patterns: Vec<IselPattern>,
pub has_sve: bool,
pub has_sme: bool,
pub stats: IselStats,
}
impl SVEIselEngine {
pub fn new(has_sve: bool, has_sme: bool) -> Self {
let mut patterns = sve_isel_table();
patterns.sort_by_key(|p| p.priority);
Self {
patterns,
has_sve,
has_sme,
stats: IselStats::new(),
}
}
pub fn lookup(
&mut self,
ir_opcode: Opcode,
_operands: &[IselOperand],
_imm_value: Option<i64>,
) -> Option<(ArmOpcode, &IselPattern)> {
let opcode_id = ir_opcode as u32;
for pattern in &self.patterns {
if pattern.ir_opcode == ir_opcode {
if let Some(feat) = pattern.required_feature {
match feat {
"sve" if !self.has_sve => continue,
"sme" if !self.has_sme => continue,
_ => {}
}
}
if let Some(constraint) = &pattern.imm_constraint {
if let Some(val) = _imm_value {
if !super::arm_isel_table::evaluate_imm_constraint(constraint, val, true) {
continue;
}
} else {
continue;
}
}
self.stats.record_match(opcode_id);
return Some((pattern.result_opcode, pattern));
}
}
self.stats.record_miss(opcode_id);
None
}
pub fn patterns_for(&self, ir_opcode: Opcode) -> Vec<&IselPattern> {
self.patterns
.iter()
.filter(|p| p.ir_opcode == ir_opcode)
.collect()
}
pub fn coverage_report(&self, all_opcodes: &[Opcode]) -> String {
let covered: std::collections::HashSet<_> =
self.patterns.iter().map(|p| p.ir_opcode as u32).collect();
let uncovered: Vec<_> = all_opcodes
.iter()
.filter(|op| !covered.contains(&(**op as u32)))
.collect();
format!(
"SVE/SME ISel Coverage: {}/{} opcodes covered ({} uncovered: {:?})",
covered.len(),
all_opcodes.len(),
uncovered.len(),
uncovered
)
}
}
impl Default for SVEIselEngine {
fn default() -> Self {
Self::new(false, false)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sve_table_not_empty() {
let table = sve_isel_table();
assert!(!table.is_empty());
assert!(table.len() >= 50, "Expected at least 50 SVE patterns");
}
#[test]
fn test_sve_lookup_add() {
let mut engine = SVEIselEngine::new(true, false);
let result = engine.lookup(Opcode::Add, &[], None);
assert!(result.is_some());
assert_eq!(result.unwrap().0, ArmOpcode::ADD_Z);
}
#[test]
fn test_sve_lookup_fadd() {
let mut engine = SVEIselEngine::new(true, false);
let result = engine.lookup(Opcode::FAdd, &[], None);
assert!(result.is_some());
assert_eq!(result.unwrap().0, ArmOpcode::FADD_Z);
}
#[test]
fn test_sme_lookup_fmopa() {
let mut engine = SVEIselEngine::new(true, true);
let result = engine.lookup(Opcode::FAdd, &[], None);
assert!(result.is_some());
}
#[test]
fn test_sve_feature_guard() {
let mut engine = SVEIselEngine::new(false, false);
let result = engine.lookup(Opcode::Add, &[], None);
assert!(result.is_none());
}
#[test]
fn test_sme_feature_guard() {
let mut engine = SVEIselEngine::new(true, false);
let has_fmopa = engine.patterns.iter().any(|p| {
p.result_opcode == ArmOpcode::FMOPA
&& p.required_feature == Some("sme")
});
assert!(has_fmopa);
}
#[test]
fn test_sve_coverage() {
let engine = SVEIselEngine::new(true, true);
let all_ops = &[
Opcode::Add,
Opcode::Sub,
Opcode::Mul,
Opcode::FAdd,
Opcode::FSub,
Opcode::FMul,
Opcode::FDiv,
Opcode::Load,
Opcode::Store,
Opcode::ICmp,
Opcode::FCmp,
];
let report = engine.coverage_report(all_ops);
assert!(report.contains("SVE/SME ISel Coverage"));
}
}