use alloc::collections::BTreeSet;
use core::fmt::{Debug, Display};
use amplify::confinement::TinyOrdSet;
use crate::core::{Core, Register, Site, SiteId};
use crate::isa::Bytecode;
use crate::{CoreExt, IsaId};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum ExecStep<Site> {
Stop,
Fail,
Next,
Jump(u16),
Call(Site),
Ret(Site),
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum GotoTarget<'a> {
None,
Absolute(&'a mut u16),
Relative(&'a mut i8),
}
pub trait Instruction<Id: SiteId>: Display + Debug + Bytecode<Id> + Clone + Eq {
const ISA_EXT: &'static [&'static str];
type Core: CoreExt;
type Context<'ctx>;
fn isa_ext() -> TinyOrdSet<IsaId> {
let iter = Self::ISA_EXT.iter().copied().map(IsaId::from);
TinyOrdSet::from_iter_checked(iter)
}
fn is_goto_target(&self) -> bool;
fn local_goto_pos(&mut self) -> GotoTarget;
fn remote_goto_pos(&mut self) -> Option<&mut Site<Id>>;
fn regs(&self) -> BTreeSet<<Self::Core as CoreExt>::Reg> {
let mut regs = self.src_regs();
regs.extend(self.dst_regs());
regs
}
fn src_regs(&self) -> BTreeSet<<Self::Core as CoreExt>::Reg>;
fn dst_regs(&self) -> BTreeSet<<Self::Core as CoreExt>::Reg>;
fn src_reg_bytes(&self) -> u16 {
self.src_regs()
.into_iter()
.map(<Self::Core as CoreExt>::Reg::bytes)
.sum()
}
fn dst_reg_bytes(&self) -> u16 {
self.dst_regs()
.into_iter()
.map(<Self::Core as CoreExt>::Reg::bytes)
.sum()
}
fn op_data_bytes(&self) -> u16;
fn ext_data_bytes(&self) -> u16;
fn base_complexity(&self) -> u64 {
(self.op_data_bytes() as u64
+ self.src_reg_bytes() as u64
+ self.dst_reg_bytes() as u64
+ self.ext_data_bytes() as u64 * 2)
* 8 * 1000 }
fn complexity(&self) -> u64 { self.base_complexity() }
fn exec(
&self,
site: Site<Id>,
core: &mut Core<Id, Self::Core>,
context: &Self::Context<'_>,
) -> ExecStep<Site<Id>>;
}