forked from AbleOS/holey-bytes
adding standard instruction logging utility
Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
parent
9c4b84ce33
commit
8ededb8612
|
@ -98,6 +98,27 @@ fn gen_instrs(generated: &mut String) -> Result<(), Box<dyn std::error::Error>>
|
|||
writeln!(generated, " {name} = {id},")?;
|
||||
}
|
||||
writeln!(generated, "}}")?;
|
||||
|
||||
writeln!(generated, "impl {instr} {{")?;
|
||||
writeln!(generated, " pub fn size(self) -> usize {{")?;
|
||||
writeln!(generated, " match self {{")?;
|
||||
let mut instrs = instructions().collect::<Vec<_>>();
|
||||
instrs.sort_unstable_by_key(|&[.., ty, _]| iter_args(ty).map(arg_to_width).sum::<usize>());
|
||||
for group in instrs.chunk_by(|[.., a, _], [.., b, _]| {
|
||||
iter_args(a).map(arg_to_width).sum::<usize>()
|
||||
== iter_args(b).map(arg_to_width).sum::<usize>()
|
||||
}) {
|
||||
let ty = group[0][2];
|
||||
for &[_, name, ..] in group {
|
||||
writeln!(generated, " | {instr}::{name}")?;
|
||||
}
|
||||
generated.pop();
|
||||
let size = iter_args(ty).map(arg_to_width).sum::<usize>() + 1;
|
||||
writeln!(generated, " => {size},")?;
|
||||
}
|
||||
writeln!(generated, " }}")?;
|
||||
writeln!(generated, " }}")?;
|
||||
writeln!(generated, "}}")?;
|
||||
}
|
||||
|
||||
'_arg_kind: {
|
||||
|
|
|
@ -697,42 +697,7 @@ fn binary_prelude(to: &mut Vec<u8>) {
|
|||
#[derive(Default)]
|
||||
pub struct LoggedMem {
|
||||
pub mem: hbvm::mem::HostMemory,
|
||||
op_buf: Vec<hbbytecode::Oper>,
|
||||
disp_buf: String,
|
||||
prev_instr: Option<hbbytecode::Instr>,
|
||||
}
|
||||
|
||||
impl LoggedMem {
|
||||
unsafe fn display_instr<T>(&mut self, instr: hbbytecode::Instr, addr: hbvm::mem::Address) {
|
||||
let novm: *const hbvm::Vm<Self, 0> = core::ptr::null();
|
||||
let offset = core::ptr::addr_of!((*novm).memory) as usize;
|
||||
let regs = unsafe {
|
||||
&*core::ptr::addr_of!(
|
||||
(*(((self as *mut _ as *mut u8).sub(offset)) as *const hbvm::Vm<Self, 0>))
|
||||
.registers
|
||||
)
|
||||
};
|
||||
|
||||
let mut bytes = core::slice::from_raw_parts(
|
||||
(addr.get() - 1) as *const u8,
|
||||
core::mem::size_of::<T>() + 1,
|
||||
);
|
||||
use core::fmt::Write;
|
||||
hbbytecode::parse_args(&mut bytes, instr, &mut self.op_buf).unwrap();
|
||||
debug_assert!(bytes.is_empty());
|
||||
self.disp_buf.clear();
|
||||
write!(self.disp_buf, "{:<10}", format!("{instr:?}")).unwrap();
|
||||
for (i, op) in self.op_buf.drain(..).enumerate() {
|
||||
if i != 0 {
|
||||
write!(self.disp_buf, ", ").unwrap();
|
||||
}
|
||||
write!(self.disp_buf, "{op:?}").unwrap();
|
||||
if let hbbytecode::Oper::R(r) = op {
|
||||
write!(self.disp_buf, "({})", regs[r as usize].0).unwrap()
|
||||
}
|
||||
}
|
||||
log::trace!("read-typed: {:x}: {}", addr.get(), self.disp_buf);
|
||||
}
|
||||
logger: hbvm::mem::InstrLogger,
|
||||
}
|
||||
|
||||
impl hbvm::mem::Memory for LoggedMem {
|
||||
|
@ -765,20 +730,14 @@ impl hbvm::mem::Memory for LoggedMem {
|
|||
}
|
||||
|
||||
unsafe fn prog_read<T: Copy + 'static>(&mut self, addr: hbvm::mem::Address) -> T {
|
||||
if log::log_enabled!(log::Level::Trace) {
|
||||
if core::any::TypeId::of::<u8>() == core::any::TypeId::of::<T>() {
|
||||
if let Some(instr) = self.prev_instr {
|
||||
self.display_instr::<()>(instr, addr);
|
||||
}
|
||||
self.prev_instr = hbbytecode::Instr::try_from(*(addr.get() as *const u8)).ok();
|
||||
} else {
|
||||
let instr = self.prev_instr.take().unwrap();
|
||||
self.display_instr::<T>(instr, addr);
|
||||
}
|
||||
}
|
||||
|
||||
self.mem.prog_read(addr)
|
||||
}
|
||||
|
||||
fn log_instr(&mut self, at: hbvm::mem::Address, regs: &[hbvm::value::Value]) {
|
||||
log::trace!("read-typed: {:x}: {}", at.get(), unsafe {
|
||||
self.logger.display_instr(at, regs)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
struct AsHex<'a>(&'a [u8]);
|
||||
|
|
|
@ -4,7 +4,7 @@ pub mod softpaging;
|
|||
|
||||
pub(crate) mod addr;
|
||||
|
||||
use crate::utils::impl_display;
|
||||
use crate::{utils::impl_display, value::Value};
|
||||
pub use addr::Address;
|
||||
|
||||
/// Load-store memory access
|
||||
|
@ -36,6 +36,48 @@ pub trait Memory {
|
|||
/// # Safety
|
||||
/// - Data read have to be valid
|
||||
unsafe fn prog_read<T: Copy + 'static>(&mut self, addr: Address) -> T;
|
||||
|
||||
/// Log instruction to be executed
|
||||
fn log_instr(&mut self, _at: Address, _regs: &[Value]) {}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct InstrLogger {
|
||||
#[cfg(debug_assertions)]
|
||||
op_buf: alloc::vec::Vec<hbbytecode::Oper>,
|
||||
#[cfg(debug_assertions)]
|
||||
disp_buf: alloc::string::String,
|
||||
}
|
||||
|
||||
impl InstrLogger {
|
||||
/// # Safety
|
||||
/// - `addr` needs to point to a valid instruction
|
||||
#[cfg(debug_assertions)]
|
||||
pub unsafe fn display_instr(&mut self, addr: Address, regs: &[Value]) -> &str {
|
||||
let instr = hbbytecode::Instr::try_from(unsafe { *(addr.get() as *const u8) }).unwrap();
|
||||
let mut bytes =
|
||||
unsafe { core::slice::from_raw_parts(addr.get() as *const u8, instr.size()) };
|
||||
use core::fmt::Write;
|
||||
hbbytecode::parse_args(&mut bytes, instr, &mut self.op_buf).unwrap();
|
||||
debug_assert!(bytes.is_empty());
|
||||
self.disp_buf.clear();
|
||||
write!(self.disp_buf, "{:<10}", alloc::format!("{instr:?}")).unwrap();
|
||||
for (i, op) in self.op_buf.drain(..).enumerate() {
|
||||
if i != 0 {
|
||||
write!(self.disp_buf, ", ").unwrap();
|
||||
}
|
||||
write!(self.disp_buf, "{op:?}").unwrap();
|
||||
if let hbbytecode::Oper::R(r) = op {
|
||||
write!(self.disp_buf, "({})", regs[r as usize].0).unwrap()
|
||||
}
|
||||
}
|
||||
&self.disp_buf
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
pub unsafe fn display_instr(&mut self, addr: Address, regs: &[Value]) -> &str {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
/// Unhandled load access trap
|
||||
|
|
|
@ -55,6 +55,7 @@ where
|
|||
// - Yes, we assume you run 64 bit CPU. Else ?conradluget a better CPU
|
||||
// sorry 8 bit fans, HBVM won't run on your Speccy :(
|
||||
unsafe {
|
||||
self.memory.log_instr(self.pc, &self.registers);
|
||||
match self
|
||||
.memory
|
||||
.prog_read::<u8>(self.pc as _)
|
||||
|
|
Loading…
Reference in a new issue