1c2fa8171SAlex Crichton //! Primitive support for debugging Pulley 2c2fa8171SAlex Crichton //! 3c2fa8171SAlex Crichton //! This `Debug` visitor defined in this module is what's actually used as part 4c2fa8171SAlex Crichton //! of the interpreter loop in Pulley. Due to the code size impact of always 5c2fa8171SAlex Crichton //! including this and the runtime overhead of always checking a flag this is 6c2fa8171SAlex Crichton //! enabled/disabled via a `const DEBUG` below. This is currently only really 7c2fa8171SAlex Crichton //! suitable for one-off debugging while developing locally. 8c2fa8171SAlex Crichton //! 9c2fa8171SAlex Crichton //! The hope is that this'll eventually evolve into something more useful, but 10c2fa8171SAlex Crichton //! for now it's a quick-and-easy way to dump all the instructions that are 11c2fa8171SAlex Crichton //! executed as well as the values in various registers. 12c2fa8171SAlex Crichton //! 13c2fa8171SAlex Crichton //! If debugging is disabled, or in `#[no_std]` mode, then this module should 14c2fa8171SAlex Crichton //! compile away (e.g. a "zero cost abstraction"). 15c2fa8171SAlex Crichton 16c2fa8171SAlex Crichton use super::Interpreter; 17c2fa8171SAlex Crichton use crate::decode::{ExtendedOpVisitor, OpVisitor}; 18c2fa8171SAlex Crichton use crate::imms::*; 19c2fa8171SAlex Crichton use crate::regs::*; 20c2fa8171SAlex Crichton use alloc::string::ToString; 21c2fa8171SAlex Crichton 22c2fa8171SAlex Crichton // Whether or not debugging is enabled at all. 23c2fa8171SAlex Crichton const DEBUG: bool = false; 24c2fa8171SAlex Crichton 25c2fa8171SAlex Crichton // Whether or not these registers are dumped between each instruction. 26c2fa8171SAlex Crichton const DEBUG_X_REGS: bool = true; 27c2fa8171SAlex Crichton const DEBUG_F_REGS: bool = false; 28c2fa8171SAlex Crichton 29c2fa8171SAlex Crichton #[cfg(not(feature = "std"))] 30c2fa8171SAlex Crichton macro_rules! print { 31c2fa8171SAlex Crichton ($($t:tt)*) => ({ let _ = format_args!($($t)*); }) 32c2fa8171SAlex Crichton } 33c2fa8171SAlex Crichton #[cfg(not(feature = "std"))] 34c2fa8171SAlex Crichton macro_rules! println { 35c2fa8171SAlex Crichton () => (); 36c2fa8171SAlex Crichton ($($t:tt)*) => ({ let _ = format_args!($($t)*); }) 37c2fa8171SAlex Crichton } 38c2fa8171SAlex Crichton 39c2fa8171SAlex Crichton #[repr(transparent)] 40c2fa8171SAlex Crichton pub(super) struct Debug<'a>(pub Interpreter<'a>); 41c2fa8171SAlex Crichton 42c2fa8171SAlex Crichton macro_rules! debug_then_delegate { 43c2fa8171SAlex Crichton ( 44c2fa8171SAlex Crichton $( 45c2fa8171SAlex Crichton $( #[$attr:meta] )* 46c2fa8171SAlex Crichton $snake_name:ident = $name:ident $( { 47c2fa8171SAlex Crichton $( 48c2fa8171SAlex Crichton $( #[$field_attr:meta] )* 49c2fa8171SAlex Crichton $field:ident : $field_ty:ty 50c2fa8171SAlex Crichton ),* 51c2fa8171SAlex Crichton } )? ; 52c2fa8171SAlex Crichton )* 53c2fa8171SAlex Crichton ) => { 54c2fa8171SAlex Crichton $( 55c2fa8171SAlex Crichton $( #[$attr] )* 56c2fa8171SAlex Crichton fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return { 57c2fa8171SAlex Crichton if DEBUG { 58c2fa8171SAlex Crichton println!( 59c2fa8171SAlex Crichton concat!( 60c2fa8171SAlex Crichton stringify!($snake_name), 61c2fa8171SAlex Crichton $( 62c2fa8171SAlex Crichton $( 63c2fa8171SAlex Crichton " ", 64c2fa8171SAlex Crichton stringify!($field), 65c2fa8171SAlex Crichton "={:?}", 66c2fa8171SAlex Crichton )* 67c2fa8171SAlex Crichton )? 68c2fa8171SAlex Crichton ), 69c2fa8171SAlex Crichton $($($field),*)? 70c2fa8171SAlex Crichton ); 71c2fa8171SAlex Crichton } 72c2fa8171SAlex Crichton self.0.$snake_name($( $($field),* )?) 73c2fa8171SAlex Crichton } 74c2fa8171SAlex Crichton )* 75c2fa8171SAlex Crichton } 76c2fa8171SAlex Crichton } 77c2fa8171SAlex Crichton 78c2fa8171SAlex Crichton impl<'a> OpVisitor for Debug<'a> { 79c2fa8171SAlex Crichton type BytecodeStream = <Interpreter<'a> as OpVisitor>::BytecodeStream; 80c2fa8171SAlex Crichton type Return = <Interpreter<'a> as OpVisitor>::Return; 81c2fa8171SAlex Crichton bytecode(&mut self) -> &mut Self::BytecodeStream82c2fa8171SAlex Crichton fn bytecode(&mut self) -> &mut Self::BytecodeStream { 83c2fa8171SAlex Crichton self.0.bytecode() 84c2fa8171SAlex Crichton } 85c2fa8171SAlex Crichton before_visit(&mut self)86c2fa8171SAlex Crichton fn before_visit(&mut self) { 87*1d1c06f3SAlex Crichton self.0.record_executing_pc_for_profiling(); 88c2fa8171SAlex Crichton if !DEBUG { 89c2fa8171SAlex Crichton return; 90c2fa8171SAlex Crichton } 91c2fa8171SAlex Crichton print!("\t{:?}\t", self.bytecode().as_ptr()); 92c2fa8171SAlex Crichton } 93c2fa8171SAlex Crichton after_visit(&mut self)94c2fa8171SAlex Crichton fn after_visit(&mut self) { 95c2fa8171SAlex Crichton if !DEBUG { 96c2fa8171SAlex Crichton return; 97c2fa8171SAlex Crichton } 98c2fa8171SAlex Crichton if DEBUG_X_REGS { 99c2fa8171SAlex Crichton for (i, regs) in self.0.state.x_regs.chunks(4).enumerate() { 100c2fa8171SAlex Crichton print!("\t\t"); 101c2fa8171SAlex Crichton for (j, reg) in regs.iter().enumerate() { 102c2fa8171SAlex Crichton let n = i * 4 + j; 103c2fa8171SAlex Crichton let val = reg.get_u64(); 104c2fa8171SAlex Crichton let reg = XReg::new(n as u8).unwrap().to_string(); 105c2fa8171SAlex Crichton print!(" {reg:>3}={val:#018x}"); 106c2fa8171SAlex Crichton } 107c2fa8171SAlex Crichton println!(); 108c2fa8171SAlex Crichton } 109c2fa8171SAlex Crichton } 110c2fa8171SAlex Crichton if DEBUG_F_REGS { 111c2fa8171SAlex Crichton for (i, regs) in self.0.state.f_regs.chunks(4).enumerate() { 112c2fa8171SAlex Crichton print!("\t\t"); 113c2fa8171SAlex Crichton for (j, reg) in regs.iter().enumerate() { 114c2fa8171SAlex Crichton let n = i * 4 + j; 115c2fa8171SAlex Crichton let val = reg.get_f64().to_bits(); 116c2fa8171SAlex Crichton let reg = FReg::new(n as u8).unwrap().to_string(); 117c2fa8171SAlex Crichton print!(" {reg:>3}={val:#018x}"); 118c2fa8171SAlex Crichton } 119c2fa8171SAlex Crichton println!(); 120c2fa8171SAlex Crichton } 121c2fa8171SAlex Crichton } 122c2fa8171SAlex Crichton } 123c2fa8171SAlex Crichton 124c2fa8171SAlex Crichton for_each_op!(debug_then_delegate); 125c2fa8171SAlex Crichton } 126c2fa8171SAlex Crichton 127c2fa8171SAlex Crichton impl<'a> ExtendedOpVisitor for Debug<'a> { 128c2fa8171SAlex Crichton for_each_extended_op!(debug_then_delegate); 129c2fa8171SAlex Crichton } 130