use crate::access_type::AccessType;
use crate::encoded_field_mask::EncodedFieldMask;
use crate::instr::InstrType;
use crate::instr_suffixes::InstrSuffix;
#[cfg(any(
feature = "RSP",
feature = "R3000GTE",
feature = "R4000ALLEGREX",
feature = "R5900EE",
))]
use crate::isa::IsaExtension;
use crate::isa::IsaVersion;
use crate::opcodes::{Opcode, OpcodeCategory, OpcodeDescriptor, OPCODES};
use crate::operands::{Operand, OperandIterator, OPERAND_COUNT_MAX};
pub(crate) const OPCODE_COUNT: usize = {
let mut count = 1;
count += 143;
if cfg!(feature = "MIPS_II") {
count += 44;
}
if cfg!(feature = "MIPS_III") {
count += 45;
}
if cfg!(feature = "MIPS_IV") {
count += 3;
}
if cfg!(feature = "RSP") {
count += 73;
}
if cfg!(feature = "R3000GTE") {
count += 22;
}
if cfg!(feature = "R4000ALLEGREX") {
count += 296;
}
if cfg!(feature = "R5900EE") {
count += 266;
}
if cfg!(feature = "RspViceMsp") {
count += 21;
}
count
};
impl Opcode {
#[must_use]
pub fn get_descriptor(&self) -> &'static OpcodeDescriptor {
&OPCODES[*self]
}
}
impl Opcode {
#[must_use]
pub fn opcode_category(&self) -> OpcodeCategory {
self.get_descriptor().opcode_category()
}
#[must_use]
pub fn bitpattern(&self) -> u32 {
self.get_descriptor().bitpattern()
}
#[must_use]
pub fn name(&self) -> &'static str {
self.get_descriptor().name()
}
#[must_use]
pub fn isa_version(&self) -> IsaVersion {
self.get_descriptor().isa_version()
}
#[cfg(any(
feature = "RSP",
feature = "R3000GTE",
feature = "R4000ALLEGREX",
feature = "R5900EE",
))]
#[must_use]
pub fn isa_extension(&self) -> Option<IsaExtension> {
self.get_descriptor().isa_extension()
}
#[must_use]
pub fn operands(&self) -> &[Operand; OPERAND_COUNT_MAX] {
self.get_descriptor().operands()
}
#[must_use]
pub fn operands_iter(&self) -> OperandIterator<'static> {
self.get_descriptor().operands_iter()
}
#[must_use]
pub fn instr_type(&self) -> InstrType {
self.get_descriptor().instr_type()
}
#[must_use]
pub fn instr_suffix(&self) -> Option<InstrSuffix> {
self.get_descriptor().instr_suffix()
}
#[must_use]
pub fn is_branch(&self) -> bool {
self.get_descriptor().is_branch()
}
#[must_use]
pub fn is_branch_likely(&self) -> bool {
self.get_descriptor().is_branch_likely()
}
#[must_use]
pub fn is_jump(&self) -> bool {
self.get_descriptor().is_jump()
}
#[must_use]
pub fn is_jump_with_address(&self) -> bool {
self.get_descriptor().is_jump_with_address()
}
#[must_use]
pub fn jumps_to_register(&self) -> bool {
self.get_descriptor().jumps_to_register()
}
#[must_use]
pub fn is_trap(&self) -> bool {
self.get_descriptor().is_trap()
}
#[must_use]
pub fn causes_exception(&self) -> bool {
self.get_descriptor().causes_exception()
}
#[must_use]
pub fn causes_unconditional_exception(&self) -> bool {
self.get_descriptor().causes_unconditional_exception()
}
#[must_use]
pub fn causes_conditional_exception(&self) -> bool {
self.get_descriptor().causes_conditional_exception()
}
#[must_use]
pub fn causes_returnable_exception(&self) -> bool {
self.get_descriptor().causes_returnable_exception()
}
#[must_use]
pub fn is_float(&self) -> bool {
self.get_descriptor().is_float()
}
#[must_use]
pub fn is_double(&self) -> bool {
self.get_descriptor().is_double()
}
#[must_use]
pub fn modifies_rs(&self) -> bool {
self.get_descriptor().modifies_rs()
}
#[must_use]
pub fn modifies_rt(&self) -> bool {
self.get_descriptor().modifies_rt()
}
#[must_use]
pub fn modifies_rd(&self) -> bool {
self.get_descriptor().modifies_rd()
}
#[must_use]
pub fn reads_rs(&self) -> bool {
self.get_descriptor().reads_rs()
}
#[must_use]
pub fn reads_rt(&self) -> bool {
self.get_descriptor().reads_rt()
}
#[must_use]
pub fn reads_rd(&self) -> bool {
self.get_descriptor().reads_rd()
}
#[must_use]
pub fn reads_hi(&self) -> bool {
self.get_descriptor().reads_hi()
}
#[must_use]
pub fn reads_lo(&self) -> bool {
self.get_descriptor().reads_lo()
}
#[must_use]
pub fn modifies_hi(&self) -> bool {
self.get_descriptor().modifies_hi()
}
#[must_use]
pub fn modifies_lo(&self) -> bool {
self.get_descriptor().modifies_lo()
}
#[must_use]
pub fn modifies_fs(&self) -> bool {
self.get_descriptor().modifies_fs()
}
#[must_use]
pub fn modifies_ft(&self) -> bool {
self.get_descriptor().modifies_ft()
}
#[must_use]
pub fn modifies_fd(&self) -> bool {
self.get_descriptor().modifies_fd()
}
#[must_use]
pub fn reads_fs(&self) -> bool {
self.get_descriptor().reads_fs()
}
#[must_use]
pub fn reads_ft(&self) -> bool {
self.get_descriptor().reads_ft()
}
#[must_use]
pub fn reads_fd(&self) -> bool {
self.get_descriptor().reads_fd()
}
#[must_use]
pub fn not_emitted_by_compilers(&self) -> bool {
self.get_descriptor().not_emitted_by_compilers()
}
#[must_use]
pub fn can_be_hi(&self) -> bool {
self.get_descriptor().can_be_hi()
}
#[must_use]
pub fn can_be_lo(&self) -> bool {
self.get_descriptor().can_be_lo()
}
#[must_use]
pub fn can_be_unsigned_lo(&self) -> bool {
self.get_descriptor().can_be_unsigned_lo()
}
#[must_use]
pub fn does_link(&self) -> bool {
self.get_descriptor().does_link()
}
#[must_use]
pub fn does_dereference(&self) -> bool {
self.get_descriptor().does_dereference()
}
#[must_use]
pub fn does_load(&self) -> bool {
self.get_descriptor().does_load()
}
#[must_use]
pub fn does_store(&self) -> bool {
self.get_descriptor().does_store()
}
#[must_use]
pub fn adds_registers(&self) -> bool {
self.get_descriptor().adds_registers()
}
#[must_use]
pub fn subs_registers(&self) -> bool {
self.get_descriptor().subs_registers()
}
#[must_use]
pub fn ors_registers(&self) -> bool {
self.get_descriptor().ors_registers()
}
#[must_use]
pub fn ands_registers(&self) -> bool {
self.get_descriptor().ands_registers()
}
#[must_use]
pub fn is_pseudo(&self) -> bool {
self.get_descriptor().is_pseudo()
}
#[must_use]
pub fn access_type(&self) -> Option<AccessType> {
self.get_descriptor().access_type()
}
#[must_use]
pub fn does_unsigned_memory_access(&self) -> bool {
self.get_descriptor().does_unsigned_memory_access()
}
}
impl Opcode {
#[must_use]
pub fn opcode_bits(&self) -> u32 {
self.get_descriptor().opcode_bits()
}
#[must_use]
pub fn valid_bits(&self) -> EncodedFieldMask {
self.get_descriptor().valid_bits()
}
#[must_use]
pub fn has_delay_slot(&self) -> bool {
self.get_descriptor().has_delay_slot()
}
#[must_use]
pub fn has_any_operands(&self) -> bool {
self.get_descriptor().has_any_operands()
}
#[must_use]
pub fn has_specific_operand(&self, operand: Operand) -> bool {
self.get_descriptor().has_specific_operand(operand)
}
#[must_use]
pub fn has_operand_alias(&self, operand: Operand) -> bool {
self.get_descriptor().has_operand_alias(operand)
}
}
impl Opcode {
#[must_use]
pub const fn default() -> Self {
Self::ALL_INVALID
}
#[must_use]
pub(crate) const fn is_valid(&self) -> bool {
!matches!(*self, Self::ALL_INVALID)
}
}
impl Default for Opcode {
fn default() -> Self {
Self::default()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_j() {
assert!(OPCODES[Opcode::core_j].is_jump);
assert!(Opcode::core_j.get_descriptor().is_jump);
assert!(OPCODES[Opcode::core_j].is_jump_with_address);
assert!(Opcode::core_j.get_descriptor().is_jump_with_address);
assert!(!OPCODES[Opcode::core_j].is_branch);
assert!(!Opcode::core_j.get_descriptor().is_branch);
}
}