use core::ops::Index;
use crate::access_type::AccessType;
use crate::encoded_field_mask::EncodedFieldMask;
#[allow(deprecated)]
use crate::instr::InstrType;
use crate::instr_suffixes::InstrSuffix;
use crate::isa::{IsaExtension, IsaVersion};
use crate::opcodes::{Opcode, OpcodeCategory};
use crate::operands::{Operand, OperandIterator, OPERAND_COUNT_MAX};
#[derive(Debug, PartialEq, Eq, Copy, Clone, Ord, PartialOrd, Hash)]
#[allow(clippy::struct_excessive_bools)]
pub struct OpcodeDescriptor {
pub(crate) opcode: Opcode,
pub(crate) opcode_category: OpcodeCategory,
pub(crate) bitpattern: u32,
pub(crate) name: &'static str,
pub(crate) isa_version: IsaVersion,
pub(crate) isa_extension: Option<IsaExtension>,
pub(crate) operands: [Operand; OPERAND_COUNT_MAX],
#[allow(deprecated)]
pub(crate) instr_type: InstrType,
pub(crate) instr_suffix: Option<InstrSuffix>,
pub(crate) is_branch: bool,
pub(crate) is_branch_likely: bool,
pub(crate) is_jump: bool,
pub(crate) is_jump_with_address: bool,
pub(crate) jumps_to_register: bool,
pub(crate) is_trap: bool,
pub(crate) causes_exception: bool,
pub(crate) causes_unconditional_exception: bool,
pub(crate) causes_conditional_exception: bool,
pub(crate) causes_returnable_exception: bool,
pub(crate) is_float: bool,
pub(crate) is_double: bool,
pub(crate) modifies_rs: bool,
pub(crate) modifies_rt: bool,
pub(crate) modifies_rd: bool,
pub(crate) reads_rs: bool,
pub(crate) reads_rt: bool,
pub(crate) reads_rd: bool,
pub(crate) reads_hi: bool,
pub(crate) reads_lo: bool,
pub(crate) modifies_hi: bool,
pub(crate) modifies_lo: bool,
pub(crate) modifies_fs: bool,
pub(crate) modifies_ft: bool,
pub(crate) modifies_fd: bool,
pub(crate) reads_fs: bool,
pub(crate) reads_ft: bool,
pub(crate) reads_fd: bool,
pub(crate) not_emitted_by_compilers: bool,
pub(crate) can_be_hi: bool,
pub(crate) can_be_lo: bool,
pub(crate) can_be_unsigned_lo: bool,
pub(crate) does_link: bool,
pub(crate) does_dereference: bool,
pub(crate) does_load: bool,
pub(crate) does_store: bool,
pub(crate) adds_registers: bool,
pub(crate) subs_registers: bool,
pub(crate) ors_registers: bool,
pub(crate) ands_registers: bool,
pub(crate) is_pseudo: bool,
pub(crate) access_type: Option<AccessType>,
pub(crate) does_unsigned_memory_access: bool,
pub(crate) is_invalid: bool,
}
impl OpcodeDescriptor {
pub(crate) const fn default() -> Self {
Self {
opcode: Opcode::ALL_INVALID,
opcode_category: OpcodeCategory::CORE_NORMAL,
bitpattern: 0,
name: "",
isa_version: IsaVersion::default(),
isa_extension: None,
operands: Operand::arr0(),
#[allow(deprecated)]
instr_type: InstrType::default(),
instr_suffix: None,
is_branch: false,
is_branch_likely: false,
is_jump: false,
is_jump_with_address: false,
jumps_to_register: false,
is_trap: false,
causes_exception: false,
causes_unconditional_exception: false,
causes_conditional_exception: false,
causes_returnable_exception: false,
is_float: false,
is_double: false,
modifies_rs: false,
modifies_rt: false,
modifies_rd: false,
reads_rs: false,
reads_rt: false,
reads_rd: false,
reads_hi: false,
reads_lo: false,
modifies_hi: false,
modifies_lo: false,
modifies_fs: false,
modifies_ft: false,
modifies_fd: false,
reads_fs: false,
reads_ft: false,
reads_fd: false,
not_emitted_by_compilers: false,
can_be_hi: false,
can_be_lo: false,
can_be_unsigned_lo: false,
does_link: false,
does_dereference: false,
does_load: false,
does_store: false,
adds_registers: false,
subs_registers: false,
ors_registers: false,
ands_registers: false,
is_pseudo: false,
access_type: None,
does_unsigned_memory_access: false,
is_invalid: false,
}
}
pub(crate) const fn new(
opcode: Opcode,
opcode_category: OpcodeCategory,
bitpattern: u32,
name: &'static str,
isa_version: IsaVersion,
isa_extension: Option<IsaExtension>,
) -> Self {
Self {
opcode,
opcode_category,
bitpattern,
name,
isa_version,
isa_extension,
..Self::default()
}
}
#[cfg(test)]
#[allow(clippy::cognitive_complexity)]
pub(crate) const fn check_valid_entry(&self) {
use crate::utils;
assert!(
!self.name.is_empty(),
"An opcode must not have an empty name"
);
if self.isa_version as u32 == IsaVersion::EXTENSION as u32 {
assert!(
self.isa_extension.is_some(),
"Opcode was marked as isa EXTENSION, but the extension type is None"
);
} else {
assert!(
self.isa_extension.is_none(),
"Opcode was not marked as isa EXTENSION, but it has a non-None extension type"
);
}
assert!(
utils::truth::a_implies_b(self.is_branch_likely, self.is_branch),
"An 'is_branch_likely' opcode must be `is_branch` too"
);
assert!(
utils::truth::a_implies_b(self.is_jump_with_address, self.is_jump),
"An 'is_jump_with_address' opcode must be `is_jump` too"
);
assert!(
utils::truth::a_implies_b(self.jumps_to_register, self.is_jump),
"An 'jumps_to_register' opcode must be `is_jump` too"
);
assert!(
!(self.is_branch && self.is_jump),
"An opcode must be either branch or jump, not both"
);
assert!(
!(self.is_branch && self.is_trap),
"An opcode must be either branch or trap, not both"
);
assert!(
!(self.is_jump && self.is_trap),
"An opcode must be either jump or trap, not both"
);
assert!(
utils::truth::a_implies_b(self.causes_unconditional_exception, self.causes_exception),
"An 'causes_unconditional_exception' opcode must be `causes_exception` too"
);
assert!(
utils::truth::a_implies_b(self.causes_conditional_exception, self.causes_exception),
"An 'causes_conditional_exception' opcode must be `causes_exception` too"
);
assert!(
!(self.causes_unconditional_exception && self.causes_conditional_exception),
"An opcode must either cause an unconditional exception or a conditional one, not both"
);
assert!(
utils::truth::a_implies_b(self.causes_returnable_exception, self.causes_exception),
"An 'causes_returnable_exception' opcode must be `causes_exception` too"
);
assert!(
utils::truth::a_implies_b(self.is_trap, self.causes_exception),
"An trap instructions cause exceptions"
);
assert!(
utils::truth::a_implies_b(self.is_double, self.is_float),
"An 'is_double' opcode must be `is_float` too"
);
assert!(
!(self.modifies_rs && self.reads_rs),
"An opcode must either modify or read the `rs` gpr register, not both"
);
assert!(
!(self.modifies_rt && self.reads_rt),
"An opcode must either modify or read the `rt` gpr register, not both"
);
assert!(
!(self.modifies_rd && self.reads_rd),
"An opcode must either modify or read the `rd` gpr register, not both"
);
assert!(
utils::truth::both_or_neither(
self.modifies_rs || self.reads_rs,
self.has_operand_alias(Operand::core_rs)
),
"An opcode that touches an `rs` gpr register must have an `rs` operand and viceversa"
);
assert!(
utils::truth::both_or_neither(
self.modifies_rt || self.reads_rt,
self.has_operand_alias(Operand::core_rt)
),
"An opcode that touches an `rt` gpr register must have an `rt` operand and viceversa"
);
assert!(
utils::truth::both_or_neither(
self.modifies_rd || self.reads_rd,
self.has_operand_alias(Operand::core_rd)
),
"An opcode that touches an `rd` gpr register must have an `rd` operand and viceversa"
);
assert!(
!(self.modifies_fs && self.reads_fs),
"An opcode must either modify or read the `fs` gpr register, not both"
);
assert!(
!(self.modifies_ft && self.reads_ft),
"An opcode must either modify or read the `ft` gpr register, not both"
);
assert!(
!(self.modifies_fd && self.reads_fd),
"An opcode must either modify or read the `fd` gpr register, not both"
);
assert!(
utils::truth::both_or_neither(
self.modifies_fs || self.reads_fs,
self.has_operand_alias(Operand::core_fs)
),
"An opcode that touches an `fs` gpr register must have an `fs` operand and viceversa"
);
assert!(
utils::truth::both_or_neither(
self.modifies_ft || self.reads_ft,
self.has_operand_alias(Operand::core_ft)
),
"An opcode that touches an `ft` gpr register must have an `ft` operand and viceversa"
);
assert!(
utils::truth::both_or_neither(
self.modifies_fd || self.reads_fd,
self.has_operand_alias(Operand::core_fd)
),
"An opcode that touches an `fd` gpr register must have an `fd` operand and viceversa"
);
assert!(
!(self.can_be_hi && self.can_be_lo),
"An opcode can be either a `hi` or `lo`, not both"
);
assert!(
!(self.can_be_hi && self.can_be_unsigned_lo),
"An opcode can be either a `hi` or `lo`, not both"
);
assert!(
!(self.can_be_unsigned_lo && self.can_be_lo),
"An opcode can be either an unsigned `lo` or a normal one, not both"
);
assert!(
utils::truth::a_implies_b(self.does_link, self.is_branch || self.is_jump),
"A 'does_link' opcode must be either `is_branch` or `is_jump`"
);
assert!(
utils::truth::a_implies_b(self.does_dereference, self.does_load || self.does_store),
"Dereference must imply either reading from RAM or storing to it"
);
assert!(
utils::truth::a_implies_b(self.does_load, self.does_dereference),
"Reading from RAM must imply a dereference"
);
assert!(
utils::truth::a_implies_b(self.does_store, self.does_dereference),
"Storing to RAM must imply a dereference"
);
assert!(
!(self.does_load && self.does_store),
"Either load or store, not both"
);
assert!(
utils::truth::both_or_neither(self.does_dereference, self.access_type.is_some()),
"An opcode that does dereference memory should have a non NONE AccessType"
);
assert!(
utils::truth::a_implies_b(self.does_unsigned_memory_access, self.does_dereference),
"Unsigned memory accesses require dereferences"
);
assert!(
utils::truth::a_implies_b(
self.adds_registers,
self.has_operand_alias(Operand::core_rd)
&& self.has_operand_alias(Operand::core_rs)
&& self.has_operand_alias(Operand::core_rt)
),
"A `adds_registers` must use three gpr register operands"
);
assert!(
utils::truth::a_implies_b(
self.subs_registers,
self.has_operand_alias(Operand::core_rd)
&& self.has_operand_alias(Operand::core_rs)
&& self.has_operand_alias(Operand::core_rt)
),
"A `adds_registers` must use three gpr register operands"
);
assert!(
utils::truth::a_implies_b(
self.ors_registers,
self.has_operand_alias(Operand::core_rd)
&& self.has_operand_alias(Operand::core_rs)
&& self.has_operand_alias(Operand::core_rt)
),
"A `adds_registers` must use three gpr register operands"
);
assert!(
utils::truth::a_implies_b(
self.ands_registers,
self.has_operand_alias(Operand::core_rd)
&& self.has_operand_alias(Operand::core_rs)
&& self.has_operand_alias(Operand::core_rt)
),
"A `adds_registers` must use three gpr register operands"
);
assert!(
utils::truth::a_implies_b(
self.adds_registers,
!self.subs_registers && !self.ors_registers && !self.ands_registers
),
"These properties are mutually exclusive"
);
assert!(
utils::truth::a_implies_b(
self.subs_registers,
!self.adds_registers && !self.ors_registers && !self.ands_registers
),
"These properties are mutually exclusive"
);
assert!(
utils::truth::a_implies_b(
self.ors_registers,
!self.subs_registers && !self.adds_registers && !self.ands_registers
),
"These properties are mutually exclusive"
);
assert!(
utils::truth::a_implies_b(
self.ands_registers,
!self.subs_registers && !self.ors_registers && !self.adds_registers
),
"These properties are mutually exclusive"
);
}
}
impl OpcodeDescriptor {
#[must_use]
pub const fn opcode(&self) -> Opcode {
self.opcode
}
#[must_use]
pub const fn opcode_category(&self) -> OpcodeCategory {
self.opcode_category
}
#[must_use]
pub const fn bitpattern(&self) -> u32 {
self.bitpattern
}
#[must_use]
pub const fn name(&self) -> &'static str {
self.name
}
#[must_use]
pub const fn isa_version(&self) -> IsaVersion {
self.isa_version
}
#[must_use]
pub const fn isa_extension(&self) -> Option<IsaExtension> {
self.isa_extension
}
#[must_use]
pub const fn operands(&self) -> &[Operand; OPERAND_COUNT_MAX] {
&self.operands
}
#[must_use]
pub fn operands_iter(&self) -> OperandIterator<'_> {
OperandIterator::new(&self.operands)
}
#[must_use]
pub const fn instr_type(&self) -> InstrType {
self.instr_type
}
#[must_use]
pub const fn instr_suffix(&self) -> Option<InstrSuffix> {
self.instr_suffix
}
#[must_use]
pub const fn is_branch(&self) -> bool {
self.is_branch
}
#[must_use]
pub const fn is_branch_likely(&self) -> bool {
self.is_branch_likely
}
#[must_use]
pub const fn is_jump(&self) -> bool {
self.is_jump
}
#[must_use]
pub const fn is_jump_with_address(&self) -> bool {
self.is_jump_with_address
}
#[must_use]
pub const fn jumps_to_register(&self) -> bool {
self.jumps_to_register
}
#[must_use]
pub const fn is_trap(&self) -> bool {
self.is_trap
}
#[must_use]
pub const fn causes_exception(&self) -> bool {
self.causes_exception
}
#[must_use]
pub const fn causes_unconditional_exception(&self) -> bool {
self.causes_unconditional_exception
}
#[must_use]
pub const fn causes_conditional_exception(&self) -> bool {
self.causes_conditional_exception
}
#[must_use]
pub const fn causes_returnable_exception(&self) -> bool {
self.causes_returnable_exception
}
#[must_use]
pub const fn is_float(&self) -> bool {
self.is_float
}
#[must_use]
pub const fn is_double(&self) -> bool {
self.is_double
}
#[must_use]
pub const fn modifies_rs(&self) -> bool {
self.modifies_rs
}
#[must_use]
pub const fn modifies_rt(&self) -> bool {
self.modifies_rt
}
#[must_use]
pub const fn modifies_rd(&self) -> bool {
self.modifies_rd
}
#[must_use]
pub const fn reads_rs(&self) -> bool {
self.reads_rs
}
#[must_use]
pub const fn reads_rt(&self) -> bool {
self.reads_rt
}
#[must_use]
pub const fn reads_rd(&self) -> bool {
self.reads_rd
}
#[must_use]
pub const fn reads_hi(&self) -> bool {
self.reads_hi
}
#[must_use]
pub const fn reads_lo(&self) -> bool {
self.reads_lo
}
#[must_use]
pub const fn modifies_hi(&self) -> bool {
self.modifies_hi
}
#[must_use]
pub const fn modifies_lo(&self) -> bool {
self.modifies_lo
}
#[must_use]
pub const fn modifies_fs(&self) -> bool {
self.modifies_fs
}
#[must_use]
pub const fn modifies_ft(&self) -> bool {
self.modifies_ft
}
#[must_use]
pub const fn modifies_fd(&self) -> bool {
self.modifies_fd
}
#[must_use]
pub const fn reads_fs(&self) -> bool {
self.reads_fs
}
#[must_use]
pub const fn reads_ft(&self) -> bool {
self.reads_ft
}
#[must_use]
pub const fn reads_fd(&self) -> bool {
self.reads_fd
}
#[must_use]
pub const fn not_emitted_by_compilers(&self) -> bool {
self.not_emitted_by_compilers
}
#[must_use]
pub const fn can_be_hi(&self) -> bool {
self.can_be_hi
}
#[must_use]
pub const fn can_be_lo(&self) -> bool {
self.can_be_lo
}
#[must_use]
pub const fn can_be_unsigned_lo(&self) -> bool {
self.can_be_unsigned_lo
}
#[must_use]
pub const fn does_link(&self) -> bool {
self.does_link
}
#[must_use]
pub const fn does_dereference(&self) -> bool {
self.does_dereference
}
#[must_use]
pub const fn does_load(&self) -> bool {
self.does_load
}
#[must_use]
pub const fn does_store(&self) -> bool {
self.does_store
}
#[must_use]
pub const fn adds_registers(&self) -> bool {
self.adds_registers
}
#[must_use]
pub const fn subs_registers(&self) -> bool {
self.subs_registers
}
#[must_use]
pub const fn ors_registers(&self) -> bool {
self.ors_registers
}
#[must_use]
pub const fn ands_registers(&self) -> bool {
self.ands_registers
}
#[must_use]
pub const fn is_pseudo(&self) -> bool {
self.is_pseudo
}
#[must_use]
pub const fn access_type(&self) -> Option<AccessType> {
self.access_type
}
#[must_use]
pub const fn does_unsigned_memory_access(&self) -> bool {
self.does_unsigned_memory_access
}
}
impl OpcodeDescriptor {
#[must_use]
pub fn opcode_bits(&self) -> u32 {
let field = self.opcode_category.field_mask().unshift(self.bitpattern);
let trailing = self.opcode_category.trailing_bits();
field | trailing
}
#[must_use]
pub fn valid_bits(&self) -> EncodedFieldMask {
let mut bits = EncodedFieldMask::empty();
for x in self.operands_iter() {
bits.insert(x.get_descriptor().mask());
}
bits
}
#[must_use]
pub const fn has_delay_slot(&self) -> bool {
self.is_branch() || self.is_jump()
}
#[must_use]
pub const fn has_any_operands(&self) -> bool {
self.operands[0] as usize != Operand::ALL_EMPTY as usize
}
#[must_use]
pub const fn has_specific_operand(&self, operand: Operand) -> bool {
let mut i = 0;
while i < self.operands.len() {
let op = self.operands[i] as usize;
if op == Operand::ALL_EMPTY as usize {
break;
}
if op == operand as usize {
return true;
}
i += 1;
}
false
}
#[allow(clippy::cognitive_complexity)]
#[must_use]
pub const fn has_operand_alias(&self, operand: Operand) -> bool {
if self.has_specific_operand(operand) {
return true;
}
match operand {
Operand::core_rs => {
if self.has_specific_operand(Operand::core_imm_rs) {
return true;
}
#[cfg(feature = "RSP")]
if self.has_specific_operand(Operand::rsp_offset7_rs) {
return true;
}
#[cfg(feature = "RSP")]
if self.has_specific_operand(Operand::rsp_offset8_rs) {
return true;
}
#[cfg(feature = "RSP")]
if self.has_specific_operand(Operand::rsp_offset9_rs) {
return true;
}
#[cfg(feature = "RSP")]
if self.has_specific_operand(Operand::rsp_offset10_rs) {
return true;
}
#[cfg(feature = "RSP")]
if self.has_specific_operand(Operand::rsp_offset11_rs) {
return true;
}
if self.has_specific_operand(Operand::core_maybe_rd_rs) {
return true;
}
if self.has_specific_operand(Operand::core_maybe_zero_rs) {
return true;
}
#[cfg(feature = "R4000ALLEGREX")]
if self.has_specific_operand(Operand::r4000allegrex_offset14_rs) {
return true;
}
#[cfg(feature = "R4000ALLEGREX")]
if self.has_specific_operand(Operand::r4000allegrex_offset14_rs_maybe_wb) {
return true;
}
}
Operand::core_imm_i16 => {
if self.has_specific_operand(Operand::core_imm_rs) {
return true;
}
}
Operand::core_imm_u16 => {}
Operand::core_rt => {}
Operand::core_rd => {
if self.has_specific_operand(Operand::core_maybe_rd_rs) {
return true;
}
}
Operand::core_sa => {}
Operand::core_zero => {}
Operand::core_cop0d => {}
Operand::core_cop0cd => {}
Operand::core_fs => {}
Operand::core_ft => {}
Operand::core_fd => {}
Operand::core_cop1cs => {}
Operand::core_cop2t => {}
Operand::core_cop2d => {}
Operand::core_cop2cd => {}
Operand::core_op => {}
Operand::core_hint => {}
Operand::core_code => {
if self.has_specific_operand(Operand::core_code_lower) {
return true;
}
}
Operand::core_code_lower => {}
Operand::core_copraw => {}
Operand::core_label => {}
Operand::core_branch_target_label => {}
Operand::core_imm_rs => {}
Operand::core_maybe_rd_rs => {}
Operand::core_maybe_zero_rs => {}
#[cfg(feature = "RSP")]
Operand::rsp_cop0d => {
if self.has_specific_operand(Operand::core_cop0d) {
return true;
}
}
#[cfg(feature = "RSP")]
Operand::rsp_cop2cd => {}
#[cfg(feature = "RSP")]
Operand::rsp_vs => {
if self.has_specific_operand(Operand::rsp_vs_index) {
return true;
}
}
#[cfg(feature = "RSP")]
Operand::rsp_vd => {
if self.has_specific_operand(Operand::rsp_vd_de) {
return true;
}
}
#[cfg(feature = "RSP")]
Operand::rsp_vt_elementhigh => {}
#[cfg(feature = "RSP")]
Operand::rsp_vt_elementlow => {}
#[cfg(feature = "RSP")]
Operand::rsp_vd_de => {}
#[cfg(feature = "RSP")]
Operand::rsp_vs_index => {}
#[cfg(feature = "RSP")]
Operand::rsp_offset7_rs => {}
#[cfg(feature = "RSP")]
Operand::rsp_offset8_rs => {}
#[cfg(feature = "RSP")]
Operand::rsp_offset9_rs => {}
#[cfg(feature = "RSP")]
Operand::rsp_offset10_rs => {}
#[cfg(feature = "RSP")]
Operand::rsp_offset11_rs => {}
#[cfg(feature = "R3000GTE")]
Operand::r3000gte_gbg => {}
#[cfg(feature = "R3000GTE")]
Operand::r3000gte_sf => {}
#[cfg(feature = "R3000GTE")]
Operand::r3000gte_mx => {}
#[cfg(feature = "R3000GTE")]
Operand::r3000gte_v => {}
#[cfg(feature = "R3000GTE")]
Operand::r3000gte_cv => {}
#[cfg(feature = "R3000GTE")]
Operand::r3000gte_lm => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_s_vs => {
if self.has_specific_operand(Operand::r4000allegrex_vcmp_cond_s_maybe_vs_maybe_vt) {
return true;
}
}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_s_vt => {
if self.has_specific_operand(Operand::r4000allegrex_vcmp_cond_s_maybe_vs_maybe_vt) {
return true;
}
}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_s_vd => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_s_vt_imm => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_s_vd_imm => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_p_vs => {
if self.has_specific_operand(Operand::r4000allegrex_vcmp_cond_p_maybe_vs_maybe_vt) {
return true;
}
}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_p_vt => {
if self.has_specific_operand(Operand::r4000allegrex_vcmp_cond_p_maybe_vs_maybe_vt) {
return true;
}
}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_p_vd => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_t_vs => {
if self.has_specific_operand(Operand::r4000allegrex_vcmp_cond_t_maybe_vs_maybe_vt) {
return true;
}
}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_t_vt => {
if self.has_specific_operand(Operand::r4000allegrex_vcmp_cond_t_maybe_vs_maybe_vt) {
return true;
}
}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_t_vd => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_q_vs => {
if self.has_specific_operand(Operand::r4000allegrex_vcmp_cond_q_maybe_vs_maybe_vt) {
return true;
}
}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_q_vt => {
if self.has_specific_operand(Operand::r4000allegrex_vcmp_cond_q_maybe_vs_maybe_vt) {
return true;
}
}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_q_vd => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_q_vt_imm => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mp_vs => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mp_vt => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mp_vd => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mp_vs_transpose => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mt_vs => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mt_vt => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mt_vd => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mt_vs_transpose => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mq_vs => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mq_vt => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mq_vd => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_mq_vs_transpose => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_cop2cs => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_cop2cd => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_pos => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_size => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_size_plus_pos => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_imm3 => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_offset14_rs => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_offset14_rs_maybe_wb => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_vcmp_cond_s_maybe_vs_maybe_vt => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_vcmp_cond_p_maybe_vs_maybe_vt => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_vcmp_cond_t_maybe_vs_maybe_vt => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_vcmp_cond_q_maybe_vs_maybe_vt => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_vconstant => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_power_of_two => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_vfpu_cc_bit => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_bn => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_int16 => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_float16 => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_p_vrot_code => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_t_vrot_code => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_q_vrot_code => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_wpx => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_wpy => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_wpz => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_wpw => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_rpx => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_rpy => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_rpz => {}
#[cfg(feature = "R4000ALLEGREX")]
Operand::r4000allegrex_rpw => {}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_I => {}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_Q => {}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_R => {}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_ACC => {
if self.has_specific_operand(Operand::r5900ee_ACCxyzw) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_imm5 => {}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_imm15 => {}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vfs => {
if self.has_specific_operand(Operand::r5900ee_vfsxyzw) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vfsl) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vft => {
if self.has_specific_operand(Operand::r5900ee_vftxyzw) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vftn) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vftm) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vfd => {
if self.has_specific_operand(Operand::r5900ee_vfdxyzw) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vis => {
if self.has_specific_operand(Operand::r5900ee_vis_predecr) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vis_postincr) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vis_parenthesis) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vit => {
if self.has_specific_operand(Operand::r5900ee_vit_predecr) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vit_postincr) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vid => {}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_ACCxyzw => {
if self.has_specific_operand(Operand::r5900ee_ACC) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vfsxyzw => {
if self.has_specific_operand(Operand::r5900ee_vfs) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vftxyzw => {
if self.has_specific_operand(Operand::r5900ee_vft) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vftn) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vfdxyzw => {
if self.has_specific_operand(Operand::r5900ee_vfd) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vfsxyzw_inv_vft | Operand::r5900ee_vftxyzw_inv_vfs => {
if self.has_specific_operand(Operand::r5900ee_vfsxyzw) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vftxyzw) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vfs) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vft) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vftn) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vftn => {
if self.has_specific_operand(Operand::r5900ee_vft) {
return true;
}
if self.has_specific_operand(Operand::r5900ee_vftxyzw) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vfsl => {
if self.has_operand_alias(Operand::r5900ee_vfs) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vftm => {
if self.has_operand_alias(Operand::r5900ee_vft) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vis_predecr => {
if self.has_operand_alias(Operand::r5900ee_vis) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vit_predecr => {
if self.has_operand_alias(Operand::r5900ee_vit) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vis_postincr => {
if self.has_operand_alias(Operand::r5900ee_vis) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vit_postincr => {
if self.has_operand_alias(Operand::r5900ee_vit) {
return true;
}
}
#[cfg(feature = "R5900EE")]
Operand::r5900ee_vis_parenthesis => {
if self.has_operand_alias(Operand::r5900ee_vis) {
return true;
}
}
Operand::ALL_EMPTY => {}
}
false
}
}
impl Index<Opcode> for [OpcodeDescriptor] {
type Output = OpcodeDescriptor;
fn index(&self, index: Opcode) -> &Self::Output {
&self[index as usize]
}
}