mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-11 09:31:34 +11:00
Merge pull request #189 from corwinkuiper/perfectly-poor-profiler
Problematic poor person's profiler
This commit is contained in:
commit
518f73c01e
|
@ -5,6 +5,7 @@ extern crate alloc;
|
|||
|
||||
use agb::display::object::{Graphics, ObjectController, Sprite, TagMap};
|
||||
use alloc::vec::Vec;
|
||||
use bare_metal::CriticalSection;
|
||||
|
||||
const GRAPHICS: &Graphics = agb::include_aseprite!(
|
||||
"../examples/the-purple-night/gfx/objects.aseprite",
|
||||
|
@ -100,6 +101,10 @@ fn all_tags(gfx: &ObjectController) {
|
|||
fn main(mut gba: agb::Gba) -> ! {
|
||||
let gfx = gba.display.object.get();
|
||||
|
||||
let mut timers = gba.timers.timers();
|
||||
|
||||
let _a = agb::interrupt::profiler(&mut timers.timer0, 5000);
|
||||
|
||||
loop {
|
||||
all_tags(&gfx);
|
||||
all_sprites(&gfx);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
@ An interrupt handler that simply acknowledges all interrupts
|
||||
.arm
|
||||
.global InterruptHandler
|
||||
|
@ -14,6 +15,10 @@ InterruptHandler:
|
|||
ldrh r3, [r2, #2] @ load 16 bit interrupt request to r3
|
||||
and r0, r1, r3 @ interrupts both enabled and requested
|
||||
|
||||
ldr r1, [sp, #20]
|
||||
ldr r3, =agb_rs__program_counter
|
||||
str r1, [r3]
|
||||
|
||||
@ change to system mode
|
||||
mrs r1, cpsr
|
||||
orr r1, r1, #0xD
|
||||
|
@ -43,3 +48,10 @@ InterruptHandler:
|
|||
|
||||
bx lr @ return to bios
|
||||
.pool
|
||||
|
||||
|
||||
.section .iwram
|
||||
.global agb_rs__program_counter
|
||||
.balign 4
|
||||
agb_rs__program_counter:
|
||||
.word 0
|
||||
|
|
|
@ -360,3 +360,22 @@ mod tests {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
/// The behaviour of this function is undefined in the sense that it will output
|
||||
/// some information in some way that can be interpreted in a way to give some
|
||||
/// profiling information. What it outputs, how it outputs it, and how to
|
||||
/// interpret it are all subject to change at any time.
|
||||
///
|
||||
/// With that out of the way, the current version will, in mgba, output the
|
||||
/// program counter at regular intervals. This can be used to see hot functions
|
||||
/// using, for example, addr2line.
|
||||
pub fn profiler(timer: &mut crate::timer::Timer, period: u16) -> InterruptHandler {
|
||||
timer.set_interrupt(true);
|
||||
timer.set_overflow_amount(period);
|
||||
timer.set_enabled(true);
|
||||
|
||||
add_interrupt_handler(timer.get_interrupt(), |_key: &CriticalSection| {
|
||||
crate::println!("{:#010x}", crate::get_program_counter_before_interrupt());
|
||||
})
|
||||
}
|
||||
|
|
|
@ -407,3 +407,11 @@ mod test {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn get_program_counter_before_interrupt() -> u32 {
|
||||
extern "C" {
|
||||
static mut agb_rs__program_counter: u32;
|
||||
}
|
||||
unsafe { agb_rs__program_counter }
|
||||
}
|
||||
|
|
|
@ -90,6 +90,11 @@ impl Timer {
|
|||
self.control_register().set_bits(bit, 1, 2);
|
||||
}
|
||||
|
||||
pub fn set_interrupt(&mut self, interrupt: bool) {
|
||||
let bit = interrupt as u16;
|
||||
self.control_register().set_bits(bit, 1, 6);
|
||||
}
|
||||
|
||||
fn data_register(&self) -> MemoryMapped<u16> {
|
||||
timer_data(self.get_timer_number())
|
||||
}
|
||||
|
@ -101,6 +106,17 @@ impl Timer {
|
|||
fn get_timer_number(&self) -> usize {
|
||||
self.timer_number as usize
|
||||
}
|
||||
|
||||
pub fn get_interrupt(&self) -> crate::interrupt::Interrupt {
|
||||
use crate::interrupt::Interrupt;
|
||||
match self.timer_number {
|
||||
0 => Interrupt::Timer0,
|
||||
1 => Interrupt::Timer1,
|
||||
2 => Interrupt::Timer2,
|
||||
3 => Interrupt::Timer3,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
|
|
Loading…
Reference in a new issue