sp1_core_executor/
instruction.rsuse core::fmt::Debug;
use serde::{Deserialize, Serialize};
use crate::opcode::Opcode;
#[derive(Clone, Copy, Serialize, Deserialize)]
#[repr(C)]
pub struct Instruction {
pub opcode: Opcode,
pub op_a: u8,
pub op_b: u32,
pub op_c: u32,
pub imm_b: bool,
pub imm_c: bool,
}
impl Instruction {
#[must_use]
pub const fn new(
opcode: Opcode,
op_a: u8,
op_b: u32,
op_c: u32,
imm_b: bool,
imm_c: bool,
) -> Self {
Self { opcode, op_a, op_b, op_c, imm_b, imm_c }
}
#[must_use]
#[inline]
pub const fn is_alu_instruction(&self) -> bool {
matches!(
self.opcode,
Opcode::ADD
| Opcode::SUB
| Opcode::XOR
| Opcode::OR
| Opcode::AND
| Opcode::SLL
| Opcode::SRL
| Opcode::SRA
| Opcode::SLT
| Opcode::SLTU
| Opcode::MUL
| Opcode::MULH
| Opcode::MULHU
| Opcode::MULHSU
| Opcode::DIV
| Opcode::DIVU
| Opcode::REM
| Opcode::REMU
)
}
#[must_use]
#[inline]
pub const fn is_ecall_instruction(&self) -> bool {
matches!(self.opcode, Opcode::ECALL)
}
#[must_use]
#[inline]
pub const fn is_memory_load_instruction(&self) -> bool {
matches!(self.opcode, Opcode::LB | Opcode::LH | Opcode::LW | Opcode::LBU | Opcode::LHU)
}
#[must_use]
#[inline]
pub const fn is_memory_store_instruction(&self) -> bool {
matches!(self.opcode, Opcode::SB | Opcode::SH | Opcode::SW)
}
#[must_use]
#[inline]
pub const fn is_branch_instruction(&self) -> bool {
matches!(
self.opcode,
Opcode::BEQ | Opcode::BNE | Opcode::BLT | Opcode::BGE | Opcode::BLTU | Opcode::BGEU
)
}
#[must_use]
#[inline]
pub const fn is_jump_instruction(&self) -> bool {
matches!(self.opcode, Opcode::JAL | Opcode::JALR)
}
#[must_use]
#[inline]
pub const fn is_auipc_instruction(&self) -> bool {
matches!(self.opcode, Opcode::AUIPC)
}
#[must_use]
#[inline]
pub const fn is_divrem_instruction(&self) -> bool {
matches!(self.opcode, Opcode::DIV | Opcode::DIVU | Opcode::REM | Opcode::REMU)
}
#[must_use]
#[inline]
pub const fn is_ebreak_instruction(&self) -> bool {
matches!(self.opcode, Opcode::EBREAK)
}
#[must_use]
#[inline]
pub const fn is_unimp_instruction(&self) -> bool {
matches!(self.opcode, Opcode::UNIMP)
}
}
impl Debug for Instruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mnemonic = self.opcode.mnemonic();
let op_a_formatted = format!("%x{}", self.op_a);
let op_b_formatted = if self.imm_b || self.opcode == Opcode::AUIPC {
format!("{}", self.op_b as i32)
} else {
format!("%x{}", self.op_b)
};
let op_c_formatted =
if self.imm_c { format!("{}", self.op_c as i32) } else { format!("%x{}", self.op_c) };
let width = 10;
write!(
f,
"{mnemonic:<width$} {op_a_formatted:<width$} {op_b_formatted:<width$} {op_c_formatted:<width$}"
)
}
}