use crate::gpr;
use crate::xmm;
use crate::{Amode, DeferredTarget, GprMem, XmmMem};
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt;
use core::num::NonZeroU8;
pub trait CodeSink {
fn put1(&mut self, _: u8);
fn put2(&mut self, _: u16);
fn put4(&mut self, _: u32);
fn put8(&mut self, _: u64);
fn add_trap(&mut self, code: TrapCode);
fn use_target(&mut self, target: DeferredTarget);
fn known_offset(&self, offset: KnownOffset) -> i32;
}
impl CodeSink for Vec<u8> {
fn put1(&mut self, v: u8) {
self.extend_from_slice(&[v]);
}
fn put2(&mut self, v: u16) {
self.extend_from_slice(&v.to_le_bytes());
}
fn put4(&mut self, v: u32) {
self.extend_from_slice(&v.to_le_bytes());
}
fn put8(&mut self, v: u64) {
self.extend_from_slice(&v.to_le_bytes());
}
fn add_trap(&mut self, _: TrapCode) {}
fn use_target(&mut self, _: DeferredTarget) {}
fn known_offset(&self, offset: KnownOffset) -> i32 {
panic!("unknown offset {offset:?}")
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
pub struct Label(pub u32);
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
pub struct Constant(pub u32);
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
pub struct TrapCode(pub NonZeroU8);
impl fmt::Display for TrapCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "trap={}", self.0)
}
}
pub type KnownOffset = u8;
pub trait Registers {
type ReadGpr: AsReg;
type ReadWriteGpr: AsReg;
type WriteGpr: AsReg;
type ReadXmm: AsReg;
type ReadWriteXmm: AsReg;
type WriteXmm: AsReg;
}
pub trait AsReg: Copy + Clone + core::fmt::Debug + PartialEq {
fn new(enc: u8) -> Self;
fn enc(&self) -> u8;
fn to_string(&self, size: Option<gpr::Size>) -> String {
match size {
Some(size) => gpr::enc::to_string(self.enc(), size).into(),
None => xmm::enc::to_string(self.enc()).into(),
}
}
}
impl AsReg for u8 {
fn new(enc: u8) -> Self {
enc
}
fn enc(&self) -> u8 {
*self
}
}
pub trait RegisterVisitor<R: Registers> {
fn read_gpr(&mut self, reg: &mut R::ReadGpr);
fn read_write_gpr(&mut self, reg: &mut R::ReadWriteGpr);
fn write_gpr(&mut self, reg: &mut R::WriteGpr);
fn fixed_read_gpr(&mut self, reg: &mut R::ReadGpr, enc: u8);
fn fixed_read_write_gpr(&mut self, reg: &mut R::ReadWriteGpr, enc: u8);
fn fixed_write_gpr(&mut self, reg: &mut R::WriteGpr, enc: u8);
fn read_xmm(&mut self, reg: &mut R::ReadXmm);
fn read_write_xmm(&mut self, reg: &mut R::ReadWriteXmm);
fn write_xmm(&mut self, reg: &mut R::WriteXmm);
fn fixed_read_xmm(&mut self, reg: &mut R::ReadXmm, enc: u8);
fn fixed_read_write_xmm(&mut self, reg: &mut R::ReadWriteXmm, enc: u8);
fn fixed_write_xmm(&mut self, reg: &mut R::WriteXmm, enc: u8);
fn read_amode(&mut self, amode: &mut Amode<R::ReadGpr>) {
match amode {
Amode::ImmReg { base, .. } => {
self.read_gpr(base);
}
Amode::ImmRegRegShift { base, index, .. } => {
self.read_gpr(base);
self.read_gpr(index.as_mut());
}
Amode::RipRelative { .. } => {}
}
}
fn read_write_gpr_mem(&mut self, op: &mut GprMem<R::ReadWriteGpr, R::ReadGpr>) {
match op {
GprMem::Gpr(r) => self.read_write_gpr(r),
GprMem::Mem(m) => self.read_amode(m),
}
}
fn write_gpr_mem(&mut self, op: &mut GprMem<R::WriteGpr, R::ReadGpr>) {
match op {
GprMem::Gpr(r) => self.write_gpr(r),
GprMem::Mem(m) => self.read_amode(m),
}
}
fn read_gpr_mem(&mut self, op: &mut GprMem<R::ReadGpr, R::ReadGpr>) {
match op {
GprMem::Gpr(r) => self.read_gpr(r),
GprMem::Mem(m) => self.read_amode(m),
}
}
fn read_xmm_mem(&mut self, op: &mut XmmMem<R::ReadXmm, R::ReadGpr>) {
match op {
XmmMem::Xmm(r) => self.read_xmm(r),
XmmMem::Mem(m) => self.read_amode(m),
}
}
fn write_xmm_mem(&mut self, op: &mut XmmMem<R::WriteXmm, R::ReadGpr>) {
match op {
XmmMem::Xmm(r) => self.write_xmm(r),
XmmMem::Mem(m) => self.read_amode(m),
}
}
}