Files
sixtyfou-rs/utils/instruction.rs
T
2026-08-18 10:01:06 +02:00

185 lines
6.2 KiB
Rust

use proc_bitfield::bitfield;
bitfield! {
#[derive(Clone, Copy, Debug)]
pub struct Instruction(pub u32): FromStorage, IntoStorage, DerefStorage {
pub special: u8 @ 0..6,
pub regimm: u8 @ 16..21,
pub rt: u8 @ 16..21,
pub cop_rt: u8 @ 16..21,
pub rs: u8 @ 21..26,
pub cop_rs: u8 @ 21..26,
pub opcode: u8 @ 26..32,
pub imm: u16 @ 0..16,
pub target: u32 @ 0..26,
pub funct: u8 @ 0..6,
pub sa: u8 @ 6..11,
pub rd: u8 @ 11..16,
}
}
pub enum BranchType {
Pure,
Likely,
Link,
LinkLikely,
}
impl Instruction {
pub fn get_branch(self) -> Option<BranchType> {
match self.opcode() {
Instruction::BEQ | Instruction::BNE | Instruction::BLEZ | Instruction::BGTZ => {
Some(BranchType::Pure)
}
Instruction::BEQL | Instruction::BNEL | Instruction::BLEZL | Instruction::BGTZL => {
Some(BranchType::Likely)
}
Instruction::REGIMM => match self.regimm() {
Instruction::BLTZ | Instruction::BGEZ => Some(BranchType::Pure),
Instruction::BLTZAL | Instruction::BGEZAL => Some(BranchType::Link),
Instruction::BLTZL | Instruction::BGEZL => Some(BranchType::Likely),
Instruction::BLTZALL | Instruction::BGEZALL => Some(BranchType::LinkLikely),
_ => None,
},
Instruction::COP1 => {
if self.cop_rs() == 8 {
match self.cop_rt() {
0 | 1 => Some(BranchType::Pure),
2 | 3 => Some(BranchType::Likely),
_ => None,
}
} else {
None
}
}
_ => None,
}
}
pub const SPECIAL: u8 = 0b000000;
pub const REGIMM: u8 = 0b000001;
pub const J: u8 = 0b000010;
pub const JAL: u8 = 0b000011;
pub const BEQ: u8 = 0b000100;
pub const BNE: u8 = 0b000101;
pub const BLEZ: u8 = 0b000110;
pub const BGTZ: u8 = 0b000111;
pub const ADDI: u8 = 0b001000;
pub const ADDIU: u8 = 0b001001;
pub const SLTI: u8 = 0b001010;
pub const SLTIU: u8 = 0b001011;
pub const ANDI: u8 = 0b001100;
pub const ORI: u8 = 0b001101;
pub const XORI: u8 = 0b001110;
pub const LUI: u8 = 0b001111;
pub const COP0: u8 = 0b010000;
pub const COP1: u8 = 0b010001;
pub const COP2: u8 = 0b010010;
pub const BEQL: u8 = 0b010100;
pub const BNEL: u8 = 0b010101;
pub const BLEZL: u8 = 0b010110;
pub const BGTZL: u8 = 0b010111;
pub const DADDI: u8 = 0b011000;
pub const DADDIU: u8 = 0b011001;
pub const LDL: u8 = 0b011010;
pub const LDR: u8 = 0b011011;
pub const LB: u8 = 0b100000;
pub const LH: u8 = 0b100001;
pub const LWL: u8 = 0b100010;
pub const LW: u8 = 0b100011;
pub const LBU: u8 = 0b100100;
pub const LHU: u8 = 0b100101;
pub const LWR: u8 = 0b100110;
pub const LWU: u8 = 0b100111;
pub const SB: u8 = 0b101000;
pub const SH: u8 = 0b101001;
pub const SWL: u8 = 0b101010;
pub const SW: u8 = 0b101011;
pub const SDL: u8 = 0b101100;
pub const SDR: u8 = 0b101101;
pub const SWR: u8 = 0b101110;
pub const CACHE: u8 = 0b101111;
pub const LL: u8 = 0b110000;
pub const LWC1: u8 = 0b110001;
pub const LWC2: u8 = 0b110010;
pub const LLD: u8 = 0b110100;
pub const LDC1: u8 = 0b110101;
pub const LDC2: u8 = 0b110110;
pub const LD: u8 = 0b110111;
pub const SC: u8 = 0b111000;
pub const SWC1: u8 = 0b111001;
pub const SWC2: u8 = 0b111010;
pub const SCD: u8 = 0b111100;
pub const SDC1: u8 = 0b111101;
pub const SDC2: u8 = 0b111110;
pub const SD: u8 = 0b111111;
// special
pub const SLL: u8 = 0b000000;
pub const SRL: u8 = 0b000010;
pub const SRA: u8 = 0b000011;
pub const SLLV: u8 = 0b000100;
pub const SRLV: u8 = 0b000110;
pub const SRAV: u8 = 0b000111;
pub const JR: u8 = 0b001000;
pub const JALR: u8 = 0b001001;
pub const SYSCALL: u8 = 0b001100;
pub const BREAK: u8 = 0b001101;
pub const SYNC: u8 = 0b001111;
pub const MFHI: u8 = 0b010000;
pub const MTHI: u8 = 0b010001;
pub const MFLO: u8 = 0b010010;
pub const MTLO: u8 = 0b010011;
pub const DSLLV: u8 = 0b010100;
pub const DSRLV: u8 = 0b010110;
pub const DSRAV: u8 = 0b010111;
pub const MULT: u8 = 0b011000;
pub const MULTU: u8 = 0b011001;
pub const DIV: u8 = 0b011010;
pub const DIVU: u8 = 0b011011;
pub const DMULT: u8 = 0b011100;
pub const DMULTU: u8 = 0b011101;
pub const DDIV: u8 = 0b011110;
pub const DDIVU: u8 = 0b011111;
pub const ADD: u8 = 0b100000;
pub const ADDU: u8 = 0b100001;
pub const SUB: u8 = 0b100010;
pub const SUBU: u8 = 0b100011;
pub const AND: u8 = 0b100100;
pub const OR: u8 = 0b100101;
pub const XOR: u8 = 0b100110;
pub const NOR: u8 = 0b100111;
pub const SLT: u8 = 0b101010;
pub const SLTU: u8 = 0b101011;
pub const DADD: u8 = 0b101100;
pub const DADDU: u8 = 0b101101;
pub const DSUB: u8 = 0b101110;
pub const DSUBU: u8 = 0b101111;
pub const TGE: u8 = 0b110000;
pub const TGEU: u8 = 0b110001;
pub const TLT: u8 = 0b110010;
pub const TLTU: u8 = 0b110011;
pub const TEQ: u8 = 0b110100;
pub const TNE: u8 = 0b110110;
pub const DSLL: u8 = 0b111000;
pub const DSRL: u8 = 0b111010;
pub const DSRA: u8 = 0b111011;
pub const DSLL32: u8 = 0b111100;
pub const DSRL32: u8 = 0b111110;
pub const DSRA32: u8 = 0b111111;
// regimm
pub const BLTZ: u8 = 0b00000;
pub const BGEZ: u8 = 0b00001;
pub const BLTZL: u8 = 0b00010;
pub const BGEZL: u8 = 0b00011;
pub const TGEI: u8 = 0b01000;
pub const TGEIU: u8 = 0b01001;
pub const TLTI: u8 = 0b01010;
pub const TLTIU: u8 = 0b01011;
pub const TEQI: u8 = 0b01100;
pub const TNEI: u8 = 0b01110;
pub const BLTZAL: u8 = 0b10000;
pub const BGEZAL: u8 = 0b10001;
pub const BLTZALL: u8 = 0b10010;
pub const BGEZALL: u8 = 0b10011;
}