use crate::Isa;
use crate::format::Operands;
use crate::opcodes::c::C_UNIMP;
use crate::opcodes::{Codec, Opcode};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Instruction {
pub(crate) isa: Isa,
pub(crate) pc: u64,
pub(crate) inst: u64,
pub(crate) len: u8,
pub(crate) op: &'static Opcode,
pub(crate) decoded: &'static Opcode,
pub(crate) rd: u8,
pub(crate) rs1: u8,
pub(crate) rs2: u8,
pub(crate) rs3: u8,
pub(crate) rm: u8,
pub(crate) pred: u8,
pub(crate) succ: u8,
pub(crate) aq: bool,
pub(crate) rl: bool,
pub(crate) imm: i32,
pub(crate) imm2: i32,
pub(crate) masked: bool,
pub(crate) fp_in_x: bool,
}
impl Instruction {
pub(crate) fn new(isa: Isa, pc: u64, inst: u64, op: &'static Opcode) -> Self {
let len = crate::inst_length(inst as u16).unwrap_or(2) as u8;
Instruction {
isa,
pc,
inst,
len,
op,
decoded: op,
rd: 0,
rs1: 0,
rs2: 0,
rs3: 0,
rm: 0,
pred: 0,
succ: 0,
aq: false,
rl: false,
imm: 0,
imm2: 0,
masked: false,
fp_in_x: false,
}
}
pub fn isa(&self) -> Isa {
self.isa
}
pub fn pc(&self) -> u64 {
self.pc
}
pub fn raw(&self) -> u64 {
self.inst
}
pub fn length(&self) -> usize {
self.len as usize
}
pub fn mnemonic(&self) -> &'static str {
self.op.name
}
pub fn operands(&self) -> Operands<'_> {
Operands(self)
}
pub fn is_illegal(&self) -> bool {
self.op.codec == Codec::Illegal || *self.decoded == C_UNIMP
}
pub fn without_aliases(&self) -> Instruction {
Instruction {
op: self.decoded,
..*self
}
}
pub(crate) fn target(&self) -> u64 {
let target = self.pc.wrapping_add(self.imm as i64 as u64);
match self.isa {
Isa::Rv32 => target & 0xffff_ffff,
Isa::Rv64 | Isa::Rv128 => target,
}
}
}