1use stackdump_core::register_data::RegisterData;
4use stackdump_core::{memory_region::ArrayMemoryRegion, register_data::ArrayRegisterData};
5
6#[cfg(not(has_fpu))]
8pub fn capture<const SIZE: usize>(
9 stack: &mut ArrayMemoryRegion<SIZE>,
10 core_registers: &mut ArrayRegisterData<16, u32>,
11) {
12 capture_core_registers(core_registers);
13 capture_stack(
14 core_registers
15 .register(stackdump_core::gimli::Arm::SP)
16 .unwrap(),
17 stack,
18 );
19}
20
21#[cfg(has_fpu)]
23pub fn capture<const SIZE: usize>(
24 stack: &mut ArrayMemoryRegion<SIZE>,
25 core_registers: &mut ArrayRegisterData<16, u32>,
26 fpu_registers: &mut ArrayRegisterData<32, u32>,
27) {
28 capture_core_registers(core_registers);
29 capture_fpu_registers(fpu_registers);
30 capture_stack(
31 core_registers
32 .register(stackdump_core::gimli::Arm::SP)
33 .unwrap(),
34 stack,
35 );
36}
37
38fn capture_core_registers(buffer: &mut ArrayRegisterData<16, u32>) {
39 #[cfg(cortex_m)]
40 use core::arch::asm;
41
42 let mut register_array = arrayvec::ArrayVec::new();
44
45 unsafe {
46 register_array.set_len(16);
48
49 #[cfg(cortex_m)]
50 asm!(
51 "str r0, [{0}, #0]",
52 "str r1, [{0}, #4]",
53 "str r2, [{0}, #8]",
54 "str r3, [{0}, #12]",
55 "str r4, [{0}, #16]",
56 "str r5, [{0}, #20]",
57 "str r6, [{0}, #24]",
58 "str r7, [{0}, #28]",
59 "str r8, [{0}, #32]",
60 "str r9, [{0}, #36]",
61 "str r10, [{0}, #40]",
62 "str r11, [{0}, #44]",
63 "str r12, [{0}, #48]",
64 "str sp, [{0}, #52]",
65 "str lr, [{0}, #56]",
66 "mov {tmp}, pc", "str {tmp}, [{0}, #60]",
68 in(reg) register_array.as_mut_ptr(), tmp = out(reg) _, );
71 }
72
73 *buffer = ArrayRegisterData::new(stackdump_core::gimli::Arm::R0, register_array);
74}
75
76#[cfg(has_fpu)]
77fn capture_fpu_registers(buffer: &mut ArrayRegisterData<32, u32>) {
78 #[cfg(cortex_m)]
79 use core::arch::asm;
80
81 let mut register_array = arrayvec::ArrayVec::new();
83
84 unsafe {
85 register_array.set_len(32);
87
88 #[cfg(cortex_m)]
89 asm!(
90 "vstr s0, [{0}, #0]",
91 "vstr s1, [{0}, #4]",
92 "vstr s2, [{0}, #8]",
93 "vstr s3, [{0}, #12]",
94 "vstr s4, [{0}, #16]",
95 "vstr s5, [{0}, #20]",
96 "vstr s6, [{0}, #24]",
97 "vstr s7, [{0}, #28]",
98 "vstr s8, [{0}, #32]",
99 "vstr s9, [{0}, #36]",
100 "vstr s10, [{0}, #40]",
101 "vstr s11, [{0}, #44]",
102 "vstr s12, [{0}, #48]",
103 "vstr s13, [{0}, #52]",
104 "vstr s14, [{0}, #56]",
105 "vstr s15, [{0}, #60]",
106 "vstr s16, [{0}, #64]",
107 "vstr s17, [{0}, #68]",
108 "vstr s18, [{0}, #72]",
109 "vstr s19, [{0}, #76]",
110 "vstr s20, [{0}, #80]",
111 "vstr s21, [{0}, #84]",
112 "vstr s22, [{0}, #88]",
113 "vstr s23, [{0}, #92]",
114 "vstr s24, [{0}, #96]",
115 "vstr s25, [{0}, #100]",
116 "vstr s26, [{0}, #104]",
117 "vstr s27, [{0}, #108]",
118 "vstr s28, [{0}, #112]",
119 "vstr s29, [{0}, #116]",
120 "vstr s30, [{0}, #120]",
121 "vstr s31, [{0}, #124]",
122 in(reg) register_array.as_mut_ptr(), );
124 }
125
126 *buffer = ArrayRegisterData::new(stackdump_core::gimli::Arm::S0, register_array)
127}
128
129fn capture_stack<const SIZE: usize>(stack_pointer: u32, stack: &mut ArrayMemoryRegion<SIZE>) {
135 extern "C" {
136 static mut _stack_start: core::ffi::c_void;
137 }
138
139 fn stack_start() -> u32 {
142 unsafe { &_stack_start as *const _ as u32 }
143 }
144
145 let stack_size = stack_start().saturating_sub(stack_pointer).min(SIZE as u32);
146 unsafe {
147 stack.copy_from_memory(stack_pointer as *const u8, stack_size as usize);
148 }
149}