probe_rs/architecture/arm/core/
armv7a.rs

1//! Register types and the core interface for armv7-a
2
3use super::{
4    CortexAState,
5    instructions::aarch32::{
6        build_ldc, build_mcr, build_mov, build_mrc, build_mrs, build_msr, build_stc, build_vmov,
7        build_vmrs,
8    },
9    registers::{
10        aarch32::{
11            AARCH32_CORE_REGISTERS, AARCH32_WITH_FP_16_CORE_REGISTERS,
12            AARCH32_WITH_FP_32_CORE_REGISTERS,
13        },
14        cortex_m::{FP, PC, RA, SP},
15    },
16};
17use crate::{
18    Architecture, CoreInformation, CoreInterface, CoreRegister, CoreStatus, CoreType,
19    InstructionSet, MemoryInterface,
20    architecture::arm::{
21        ArmError, core::armv7a_debug_regs::*, memory::ArmMemoryInterface,
22        sequences::ArmDebugSequence,
23    },
24    core::{CoreRegisters, MemoryMappedRegister, RegisterId, RegisterValue},
25    error::Error,
26    memory::valid_32bit_address,
27};
28use std::{
29    mem::size_of,
30    sync::Arc,
31    time::{Duration, Instant},
32};
33
34/// Errors for the ARMv7-A state machine
35#[derive(thiserror::Error, Debug)]
36pub enum Armv7aError {
37    /// Invalid register number
38    #[error("Register number {0} is not valid for ARMv7-A")]
39    InvalidRegisterNumber(u16),
40
41    /// Not halted
42    #[error("Core is running but operation requires it to be halted")]
43    NotHalted,
44
45    /// Data Abort occurred
46    #[error("A data abort occurred")]
47    DataAbort,
48}
49
50/// Interface for interacting with an ARMv7-A core
51pub struct Armv7a<'probe> {
52    memory: Box<dyn ArmMemoryInterface + 'probe>,
53
54    state: &'probe mut CortexAState,
55
56    base_address: u64,
57
58    sequence: Arc<dyn ArmDebugSequence>,
59
60    num_breakpoints: Option<u32>,
61
62    itr_enabled: bool,
63}
64
65impl<'probe> Armv7a<'probe> {
66    pub(crate) fn new(
67        mut memory: Box<dyn ArmMemoryInterface + 'probe>,
68        state: &'probe mut CortexAState,
69        base_address: u64,
70        sequence: Arc<dyn ArmDebugSequence>,
71    ) -> Result<Self, Error> {
72        if !state.initialized() {
73            // determine current state
74            let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
75            let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
76
77            tracing::debug!("State when connecting: {:x?}", dbgdscr);
78
79            let core_state = if dbgdscr.halted() {
80                let reason = dbgdscr.halt_reason();
81
82                tracing::debug!("Core was halted when connecting, reason: {:?}", reason);
83
84                CoreStatus::Halted(reason)
85            } else {
86                CoreStatus::Running
87            };
88
89            state.current_state = core_state;
90        }
91
92        let mut core = Self {
93            memory,
94            state,
95            base_address,
96            sequence,
97            num_breakpoints: None,
98            itr_enabled: false,
99        };
100
101        if !core.state.initialized() {
102            core.reset_register_cache();
103            core.read_fp_reg_count()?;
104            core.state.initialize();
105        }
106
107        Ok(core)
108    }
109
110    fn read_fp_reg_count(&mut self) -> Result<(), Error> {
111        if self.state.fp_reg_count == 0 && matches!(self.state.current_state, CoreStatus::Halted(_))
112        {
113            self.prepare_r0_for_clobber()?;
114
115            // VMRS r0, MVFR0
116            let instruction = build_vmrs(0, 0b0111);
117            self.execute_instruction(instruction)?;
118
119            // Read from r0
120            let instruction = build_mcr(14, 0, 0, 0, 5, 0);
121            let vmrs = self.execute_instruction_with_result(instruction)?;
122
123            self.state.fp_reg_count = match vmrs & 0b111 {
124                0b001 => 16,
125                0b010 => 32,
126                _ => 0,
127            };
128        }
129
130        Ok(())
131    }
132
133    /// Execute an instruction
134    fn execute_instruction(&mut self, instruction: u32) -> Result<Dbgdscr, ArmError> {
135        if !self.state.current_state.is_halted() {
136            return Err(ArmError::CoreNotHalted);
137        }
138
139        // Enable ITR if needed
140        if !self.itr_enabled {
141            let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
142            let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
143            dbgdscr.set_itren(true);
144
145            self.memory.write_word_32(address, dbgdscr.into())?;
146
147            self.itr_enabled = true;
148        }
149
150        execute_instruction(&mut *self.memory, self.base_address, instruction)
151    }
152
153    /// Execute an instruction on the CPU and return the result
154    fn execute_instruction_with_result(&mut self, instruction: u32) -> Result<u32, Error> {
155        // Run instruction
156        let mut dbgdscr = self.execute_instruction(instruction)?;
157
158        // Wait for TXfull
159        while !dbgdscr.txfull_l() {
160            let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
161            dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
162        }
163
164        // Read result
165        let address = Dbgdtrtx::get_mmio_address_from_base(self.base_address)?;
166        let result = self.memory.read_word_32(address)?;
167
168        Ok(result)
169    }
170
171    fn execute_instruction_with_input(
172        &mut self,
173        instruction: u32,
174        value: u32,
175    ) -> Result<(), Error> {
176        // Move value
177        let address = Dbgdtrrx::get_mmio_address_from_base(self.base_address)?;
178        self.memory.write_word_32(address, value)?;
179
180        // Wait for RXfull
181        let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
182        let mut dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
183
184        while !dbgdscr.rxfull_l() {
185            dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
186        }
187
188        // Run instruction
189        self.execute_instruction(instruction)?;
190
191        Ok(())
192    }
193
194    fn reset_register_cache(&mut self) {
195        self.state.register_cache = vec![None; 51];
196    }
197
198    /// Sync any updated registers back to the core
199    fn writeback_registers(&mut self) -> Result<(), Error> {
200        let writeback_iter = (17u16..=48).chain(15u16..=16).chain(0u16..=14);
201
202        for i in writeback_iter {
203            if let Some((val, writeback)) = self.state.register_cache[i as usize] {
204                if writeback {
205                    match i {
206                        0..=14 => {
207                            let instruction = build_mrc(14, 0, i, 0, 5, 0);
208
209                            self.execute_instruction_with_input(instruction, val.try_into()?)?;
210                        }
211                        15 => {
212                            // Move val to r0
213                            let instruction = build_mrc(14, 0, 0, 0, 5, 0);
214
215                            self.execute_instruction_with_input(instruction, val.try_into()?)?;
216
217                            // Use `mov pc, r0` rather than `bx r0` because the `bx` instruction is
218                            // `UNPREDICTABLE` in the debug state (ARM Architecture Reference Manual,
219                            // ARMv7-A and ARMv7-R edition, C5.3: "Executing instructions in Debug state").
220                            let instruction = build_mov(15, 0);
221                            self.execute_instruction(instruction)?;
222                        }
223                        16 => {
224                            // msr cpsr_fsxc, r0
225                            let instruction = build_msr(0);
226                            self.execute_instruction_with_input(instruction, val.try_into()?)?;
227                        }
228                        17..=48 => {
229                            // Move value to r0, r1
230                            let value: u64 = val.try_into()?;
231                            let low_word = value as u32;
232                            let high_word = (value >> 32) as u32;
233
234                            let instruction = build_mrc(14, 0, 0, 0, 5, 0);
235                            self.execute_instruction_with_input(instruction, low_word)?;
236
237                            let instruction = build_mrc(14, 0, 1, 0, 5, 0);
238                            self.execute_instruction_with_input(instruction, high_word)?;
239
240                            // VMOV
241                            let instruction = build_vmov(0, 0, 1, i - 17);
242                            self.execute_instruction(instruction)?;
243                        }
244                        _ => {
245                            panic!("Logic missing for writeback of register {i}");
246                        }
247                    }
248                }
249            }
250        }
251
252        self.reset_register_cache();
253
254        Ok(())
255    }
256
257    /// Save r0 if needed before it gets clobbered by instruction execution
258    fn prepare_r0_for_clobber(&mut self) -> Result<(), Error> {
259        self.prepare_for_clobber(0)
260    }
261
262    /// Save `r<n>` if needed before it gets clobbered by instruction execution
263    fn prepare_for_clobber(&mut self, reg: usize) -> Result<(), Error> {
264        if self.state.register_cache[reg].is_none() {
265            // cache reg since we're going to clobber it
266            let val: u32 = self.read_core_reg(RegisterId(reg as u16))?.try_into()?;
267
268            // Mark reg as needing writeback
269            self.state.register_cache[reg] = Some((val.into(), true));
270        }
271
272        Ok(())
273    }
274
275    fn set_r0(&mut self, value: u32) -> Result<(), Error> {
276        let instruction = build_mrc(14, 0, 0, 0, 5, 0);
277
278        self.execute_instruction_with_input(instruction, value)
279    }
280
281    fn set_core_status(&mut self, new_status: CoreStatus) {
282        super::update_core_status(&mut self.memory, &mut self.state.current_state, new_status);
283    }
284
285    pub(crate) fn halted_access<R>(
286        &mut self,
287        op: impl FnOnce(&mut Self) -> Result<R, Error>,
288    ) -> Result<R, Error> {
289        let was_running = !(self.state.current_state.is_halted() || self.status()?.is_halted());
290
291        if was_running {
292            self.halt(Duration::from_millis(100))?;
293        }
294
295        let result = op(self);
296
297        if was_running {
298            self.run()?
299        }
300
301        result
302    }
303}
304
305// These helper functions allow access to the ARMv7A core from Sequences.
306// They are also used by the `CoreInterface` to avoid code duplication.
307
308/// Request the core to halt. Does not wait for the core to halt.
309pub(crate) fn request_halt(
310    memory: &mut dyn ArmMemoryInterface,
311    base_address: u64,
312) -> Result<(), ArmError> {
313    let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
314    let mut value = Dbgdrcr(0);
315    value.set_hrq(true);
316
317    memory.write_word_32(address, value.into())?;
318    Ok(())
319}
320
321/// Start the core running. This does not flush any state.
322pub(crate) fn run(memory: &mut dyn ArmMemoryInterface, base_address: u64) -> Result<(), ArmError> {
323    let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
324    let mut value = Dbgdrcr(0);
325    value.set_rrq(true);
326
327    memory.write_word_32(address, value.into())?;
328
329    // Wait for ack
330    let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
331
332    loop {
333        let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
334        if dbgdscr.restarted() {
335            return Ok(());
336        }
337    }
338}
339
340/// Wait for the core to be halted. If the core does not halt, then
341/// this will return `ArmError::Timeout`.
342pub(crate) fn wait_for_core_halted(
343    memory: &mut dyn ArmMemoryInterface,
344    base_address: u64,
345    timeout: Duration,
346) -> Result<(), ArmError> {
347    // Wait until halted state is active again.
348    let start = Instant::now();
349
350    while !core_halted(memory, base_address)? {
351        if start.elapsed() >= timeout {
352            return Err(ArmError::Timeout);
353        }
354        // Wait a bit before polling again.
355        std::thread::sleep(Duration::from_millis(1));
356    }
357
358    Ok(())
359}
360
361/// Return whether or not the core is halted.
362fn core_halted(memory: &mut dyn ArmMemoryInterface, base_address: u64) -> Result<bool, ArmError> {
363    let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
364    let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
365
366    Ok(dbgdscr.halted())
367}
368
369/// Set and enable a specific breakpoint. If the breakpoint is in use, it
370/// will be cleared.
371pub(crate) fn set_hw_breakpoint(
372    memory: &mut dyn ArmMemoryInterface,
373    base_address: u64,
374    bp_unit_index: usize,
375    addr: u32,
376) -> Result<(), ArmError> {
377    let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
378        + (bp_unit_index * size_of::<u32>()) as u64;
379    let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
380        + (bp_unit_index * size_of::<u32>()) as u64;
381    let mut bp_control = Dbgbcr(0);
382
383    // Breakpoint type - address match
384    bp_control.set_bt(0b0000);
385    // Match on all modes
386    bp_control.set_hmc(true);
387    bp_control.set_pmc(0b11);
388    // Match on all bytes
389    bp_control.set_bas(0b1111);
390    // Enable
391    bp_control.set_e(true);
392
393    memory.write_word_32(bp_value_addr, addr)?;
394    memory.write_word_32(bp_control_addr, bp_control.into())?;
395
396    Ok(())
397}
398
399/// If a specified breakpoint is set, disable it and clear it.
400pub(crate) fn clear_hw_breakpoint(
401    memory: &mut dyn ArmMemoryInterface,
402    base_address: u64,
403    bp_unit_index: usize,
404) -> Result<(), ArmError> {
405    let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
406        + (bp_unit_index * size_of::<u32>()) as u64;
407    let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
408        + (bp_unit_index * size_of::<u32>()) as u64;
409
410    memory.write_word_32(bp_value_addr, 0)?;
411    memory.write_word_32(bp_control_addr, 0)?;
412    Ok(())
413}
414
415/// Get a specific hardware breakpoint. If the breakpoint is not set, return `None`.
416pub(crate) fn get_hw_breakpoint(
417    memory: &mut dyn ArmMemoryInterface,
418    base_address: u64,
419    bp_unit_index: usize,
420) -> Result<Option<u32>, ArmError> {
421    let bp_value_addr = Dbgbvr::get_mmio_address_from_base(base_address)?
422        + (bp_unit_index * size_of::<u32>()) as u64;
423    let bp_value = memory.read_word_32(bp_value_addr)?;
424
425    let bp_control_addr = Dbgbcr::get_mmio_address_from_base(base_address)?
426        + (bp_unit_index * size_of::<u32>()) as u64;
427    let bp_control = Dbgbcr(memory.read_word_32(bp_control_addr)?);
428
429    Ok(if bp_control.e() { Some(bp_value) } else { None })
430}
431
432/// Execute a single instruction.
433fn execute_instruction(
434    memory: &mut dyn ArmMemoryInterface,
435    base_address: u64,
436    instruction: u32,
437) -> Result<Dbgdscr, ArmError> {
438    // Run instruction
439    let address = Dbgitr::get_mmio_address_from_base(base_address)?;
440    memory.write_word_32(address, instruction)?;
441
442    // Wait for completion
443    let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
444    let mut dbgdscr = Dbgdscr(memory.read_word_32(address)?);
445
446    while !dbgdscr.instrcoml_l() {
447        dbgdscr = Dbgdscr(memory.read_word_32(address)?);
448    }
449
450    // Check if we had any aborts, if so clear them and fail
451    if dbgdscr.adabort_l() || dbgdscr.sdabort_l() {
452        let address = Dbgdrcr::get_mmio_address_from_base(base_address)?;
453        let mut dbgdrcr = Dbgdrcr(0);
454        dbgdrcr.set_cse(true);
455
456        memory.write_word_32(address, dbgdrcr.into())?;
457        return Err(ArmError::Armv7a(
458            crate::architecture::arm::armv7a::Armv7aError::DataAbort,
459        ));
460    }
461
462    Ok(dbgdscr)
463}
464
465/// Set the DBGDBGDTRRX register, which can be accessed with an
466/// `STC p14, c5, ..., #4` instruction.
467fn set_instruction_input(
468    memory: &mut dyn ArmMemoryInterface,
469    base_address: u64,
470    value: u32,
471) -> Result<(), ArmError> {
472    // Move value
473    let address = Dbgdtrrx::get_mmio_address_from_base(base_address)?;
474    memory.write_word_32(address, value)?;
475
476    // Wait for RXfull
477    let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
478    let mut dbgdscr = Dbgdscr(memory.read_word_32(address)?);
479
480    while !dbgdscr.rxfull_l() {
481        dbgdscr = Dbgdscr(memory.read_word_32(address)?);
482    }
483    Ok(())
484}
485
486/// Return the contents of DBGDTRTX, which is set as a result of an
487/// `LDC, p14, c5, ..., #4` instruction.
488fn get_instruction_result(
489    memory: &mut dyn ArmMemoryInterface,
490    base_address: u64,
491) -> Result<u32, ArmError> {
492    // Wait for TXfull
493    let address = Dbgdscr::get_mmio_address_from_base(base_address)?;
494    loop {
495        let dbgdscr = Dbgdscr(memory.read_word_32(address)?);
496        if dbgdscr.txfull_l() {
497            break;
498        }
499    }
500
501    // Read result
502    let address = Dbgdtrtx::get_mmio_address_from_base(base_address)?;
503    memory.read_word_32(address)
504}
505
506/// Write a 32-bit value to main memory. Assumes that the core is halted. Note that
507/// this clobbers $r0.
508pub(crate) fn write_word_32(
509    memory: &mut dyn ArmMemoryInterface,
510    base_address: u64,
511    address: u32,
512    data: u32,
513) -> Result<(), ArmError> {
514    // Load address into r0
515    set_instruction_input(memory, base_address, address)?;
516    execute_instruction(memory, base_address, build_mrc(14, 0, 0, 0, 5, 0))?;
517
518    // Store the value in the DBGDBGDTRRX register and store that value into RAM.
519    // STC p14, c5, [r0], #4
520    set_instruction_input(memory, base_address, data)?;
521    execute_instruction(memory, base_address, build_stc(14, 5, 0, 4))?;
522    Ok(())
523}
524
525/// Read a 32-bit value from main memory. Assumes that the core is halted. Note that
526/// this clobbers $r0.
527pub(crate) fn read_word_32(
528    memory: &mut dyn ArmMemoryInterface,
529    base_address: u64,
530    address: u32,
531) -> Result<u32, ArmError> {
532    // Load address into r0
533    set_instruction_input(memory, base_address, address)?;
534    execute_instruction(memory, base_address, build_mrc(14, 0, 0, 0, 5, 0))?;
535
536    // Execute the instruction and store the result in the DBGDTRTX register.
537    // LDC p14, c5, [r0], #4
538    execute_instruction(memory, base_address, build_ldc(14, 5, 0, 4))?;
539    get_instruction_result(memory, base_address)
540}
541
542impl CoreInterface for Armv7a<'_> {
543    fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
544        wait_for_core_halted(&mut *self.memory, self.base_address, timeout).map_err(|e| e.into())
545    }
546
547    fn core_halted(&mut self) -> Result<bool, Error> {
548        core_halted(&mut *self.memory, self.base_address).map_err(|e| e.into())
549    }
550
551    fn status(&mut self) -> Result<crate::core::CoreStatus, Error> {
552        // determine current state
553        let address = Dbgdscr::get_mmio_address_from_base(self.base_address)?;
554        let dbgdscr = Dbgdscr(self.memory.read_word_32(address)?);
555
556        if dbgdscr.halted() {
557            let reason = dbgdscr.halt_reason();
558
559            self.set_core_status(CoreStatus::Halted(reason));
560
561            self.read_fp_reg_count()?;
562
563            return Ok(CoreStatus::Halted(reason));
564        }
565        // Core is neither halted nor sleeping, so we assume it is running.
566        if self.state.current_state.is_halted() {
567            tracing::warn!("Core is running, but we expected it to be halted");
568        }
569
570        self.set_core_status(CoreStatus::Running);
571
572        Ok(CoreStatus::Running)
573    }
574
575    fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
576        if !matches!(self.state.current_state, CoreStatus::Halted(_)) {
577            request_halt(&mut *self.memory, self.base_address)?;
578            self.wait_for_core_halted(timeout)?;
579
580            // Reset our cached values
581            self.reset_register_cache();
582        }
583        // Update core status
584        let _ = self.status()?;
585
586        // try to read the program counter
587        let pc_value = self.read_core_reg(self.program_counter().into())?;
588
589        // get pc
590        Ok(CoreInformation {
591            pc: pc_value.try_into()?,
592        })
593    }
594
595    fn run(&mut self) -> Result<(), Error> {
596        if matches!(self.state.current_state, CoreStatus::Running) {
597            return Ok(());
598        }
599
600        // set writeback values
601        self.writeback_registers()?;
602
603        run(&mut *self.memory, self.base_address)?;
604
605        // Recompute / verify current state
606        self.set_core_status(CoreStatus::Running);
607        let _ = self.status()?;
608
609        Ok(())
610    }
611
612    fn reset(&mut self) -> Result<(), Error> {
613        self.sequence.reset_system(
614            &mut *self.memory,
615            crate::CoreType::Armv7a,
616            Some(self.base_address),
617        )?;
618
619        // Reset our cached values
620        self.reset_register_cache();
621
622        Ok(())
623    }
624
625    fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
626        self.sequence.reset_catch_set(
627            &mut *self.memory,
628            crate::CoreType::Armv7a,
629            Some(self.base_address),
630        )?;
631        self.sequence.reset_system(
632            &mut *self.memory,
633            crate::CoreType::Armv7a,
634            Some(self.base_address),
635        )?;
636
637        // Request halt
638        let address = Dbgdrcr::get_mmio_address_from_base(self.base_address)?;
639        let mut value = Dbgdrcr(0);
640        value.set_hrq(true);
641
642        self.memory.write_word_32(address, value.into())?;
643
644        // Release from reset
645        self.sequence.reset_catch_clear(
646            &mut *self.memory,
647            crate::CoreType::Armv7a,
648            Some(self.base_address),
649        )?;
650
651        self.wait_for_core_halted(timeout)?;
652
653        // Update core status
654        let _ = self.status()?;
655
656        // Reset our cached values
657        self.reset_register_cache();
658
659        // try to read the program counter
660        let pc_value = self.read_core_reg(self.program_counter().into())?;
661
662        // get pc
663        Ok(CoreInformation {
664            pc: pc_value.try_into()?,
665        })
666    }
667
668    fn step(&mut self) -> Result<CoreInformation, Error> {
669        // Save current breakpoint
670        let bp_unit_index = (self.available_breakpoint_units()? - 1) as usize;
671        let bp_value_addr = Dbgbvr::get_mmio_address_from_base(self.base_address)?
672            + (bp_unit_index * size_of::<u32>()) as u64;
673        let saved_bp_value = self.memory.read_word_32(bp_value_addr)?;
674
675        let bp_control_addr = Dbgbcr::get_mmio_address_from_base(self.base_address)?
676            + (bp_unit_index * size_of::<u32>()) as u64;
677        let saved_bp_control = self.memory.read_word_32(bp_control_addr)?;
678
679        // Set breakpoint for any change
680        let current_pc: u32 = self
681            .read_core_reg(self.program_counter().into())?
682            .try_into()?;
683        let mut bp_control = Dbgbcr(0);
684
685        // Breakpoint type - address mismatch
686        bp_control.set_bt(0b0100);
687        // Match on all modes
688        bp_control.set_hmc(true);
689        bp_control.set_pmc(0b11);
690        // Match on all bytes
691        bp_control.set_bas(0b1111);
692        // Enable
693        bp_control.set_e(true);
694
695        self.memory.write_word_32(bp_value_addr, current_pc)?;
696        self.memory
697            .write_word_32(bp_control_addr, bp_control.into())?;
698
699        // Resume
700        self.run()?;
701
702        // Wait for halt
703        self.wait_for_core_halted(Duration::from_millis(100))?;
704
705        // Reset breakpoint
706        self.memory.write_word_32(bp_value_addr, saved_bp_value)?;
707        self.memory
708            .write_word_32(bp_control_addr, saved_bp_control)?;
709
710        // try to read the program counter
711        let pc_value = self.read_core_reg(self.program_counter().into())?;
712
713        // get pc
714        Ok(CoreInformation {
715            pc: pc_value.try_into()?,
716        })
717    }
718
719    fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, Error> {
720        let reg_num = address.0;
721
722        // check cache
723        if (reg_num as usize) < self.state.register_cache.len() {
724            if let Some(cached_result) = self.state.register_cache[reg_num as usize] {
725                return Ok(cached_result.0);
726            }
727        }
728
729        // Generate instruction to extract register
730        let result: Result<RegisterValue, Error> = match reg_num {
731            0..=14 => {
732                // r0-r14, valid
733                // MCR p14, 0, <Rd>, c0, c5, 0 ; Write DBGDTRTXint Register
734                let instruction = build_mcr(14, 0, reg_num, 0, 5, 0);
735
736                let val = self.execute_instruction_with_result(instruction)?;
737
738                Ok(val.into())
739            }
740            15 => {
741                // PC, must access via r0
742                self.prepare_r0_for_clobber()?;
743
744                // MOV r0, PC
745                let instruction = build_mov(0, 15);
746                self.execute_instruction(instruction)?;
747
748                // Read from r0
749                let instruction = build_mcr(14, 0, 0, 0, 5, 0);
750                let pra_plus_offset = self.execute_instruction_with_result(instruction)?;
751
752                // PC returned is PC + 8
753                Ok((pra_plus_offset - 8).into())
754            }
755            16 => {
756                // CPSR, must access via r0
757                self.prepare_r0_for_clobber()?;
758
759                // MRS r0, CPSR
760                let instruction = build_mrs(0);
761                self.execute_instruction(instruction)?;
762
763                // Read from r0
764                let instruction = build_mcr(14, 0, 0, 0, 5, 0);
765                let cpsr = self.execute_instruction_with_result(instruction)?;
766
767                Ok(cpsr.into())
768            }
769            17..=48 => {
770                // Access via r0, r1
771                self.prepare_for_clobber(0)?;
772                self.prepare_for_clobber(1)?;
773
774                // If FPEXC.EN = 0, then these registers aren't safe to access.  Read as zero
775                let fpexc: u32 = self.read_core_reg(50.into())?.try_into()?;
776                if (fpexc & (1 << 30)) == 0 {
777                    // Disabled
778                    return Ok(0u32.into());
779                }
780
781                // VMOV r0, r1, <reg>
782                let instruction = build_vmov(1, 0, 1, reg_num - 17);
783                self.execute_instruction(instruction)?;
784
785                // Read from r0
786                let instruction = build_mcr(14, 0, 0, 0, 5, 0);
787                let mut value = self.execute_instruction_with_result(instruction)? as u64;
788
789                // Read from r1
790                let instruction = build_mcr(14, 0, 1, 0, 5, 0);
791                value |= (self.execute_instruction_with_result(instruction)? as u64) << 32;
792
793                Ok(value.into())
794            }
795            49 => {
796                // Access via r0
797                self.prepare_for_clobber(0)?;
798
799                // If FPEXC.EN = 0, then these registers aren't safe to access.  Read as zero
800                let fpexc: u32 = self.read_core_reg(50.into())?.try_into()?;
801                if (fpexc & (1 << 30)) == 0 {
802                    // Disabled
803                    return Ok(0u32.into());
804                }
805
806                // VMRS r0, FPSCR
807                let instruction = build_vmrs(0, 1);
808                self.execute_instruction(instruction)?;
809
810                // Read from r0
811                let instruction = build_mcr(14, 0, 0, 0, 5, 0);
812                let value = self.execute_instruction_with_result(instruction)?;
813
814                Ok(value.into())
815            }
816            50 => {
817                // Access via r0
818                self.prepare_for_clobber(0)?;
819
820                // VMRS r0, FPEXC
821                let instruction = build_vmrs(0, 0b1000);
822                self.execute_instruction(instruction)?;
823
824                let instruction = build_mcr(14, 0, 0, 0, 5, 0);
825                let value = self.execute_instruction_with_result(instruction)?;
826
827                Ok(value.into())
828            }
829            _ => Err(Error::Arm(
830                Armv7aError::InvalidRegisterNumber(reg_num).into(),
831            )),
832        };
833
834        if let Ok(value) = result {
835            self.state.register_cache[reg_num as usize] = Some((value, false));
836
837            Ok(value)
838        } else {
839            Err(result.err().unwrap())
840        }
841    }
842
843    fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error> {
844        let reg_num = address.0;
845
846        if (reg_num as usize) >= self.state.register_cache.len() {
847            return Err(Error::Arm(
848                Armv7aError::InvalidRegisterNumber(reg_num).into(),
849            ));
850        }
851        self.state.register_cache[reg_num as usize] = Some((value, true));
852
853        Ok(())
854    }
855
856    fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
857        if self.num_breakpoints.is_none() {
858            let address = Dbgdidr::get_mmio_address_from_base(self.base_address)?;
859            let dbgdidr = Dbgdidr(self.memory.read_word_32(address)?);
860
861            self.num_breakpoints = Some(dbgdidr.brps() + 1);
862        }
863        Ok(self.num_breakpoints.unwrap())
864    }
865
866    /// See docs on the [`CoreInterface::hw_breakpoints`] trait
867    fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
868        let mut breakpoints = vec![];
869        let num_hw_breakpoints = self.available_breakpoint_units()? as usize;
870
871        for bp_unit_index in 0..num_hw_breakpoints {
872            let bp_value_addr = Dbgbvr::get_mmio_address_from_base(self.base_address)?
873                + (bp_unit_index * size_of::<u32>()) as u64;
874            let bp_value = self.memory.read_word_32(bp_value_addr)?;
875
876            let bp_control_addr = Dbgbcr::get_mmio_address_from_base(self.base_address)?
877                + (bp_unit_index * size_of::<u32>()) as u64;
878            let bp_control = Dbgbcr(self.memory.read_word_32(bp_control_addr)?);
879
880            if bp_control.e() {
881                breakpoints.push(Some(bp_value as u64));
882            } else {
883                breakpoints.push(None);
884            }
885        }
886        Ok(breakpoints)
887    }
888
889    fn enable_breakpoints(&mut self, _state: bool) -> Result<(), Error> {
890        // Breakpoints are always on with v7-A
891        Ok(())
892    }
893
894    fn set_hw_breakpoint(&mut self, bp_unit_index: usize, addr: u64) -> Result<(), Error> {
895        let addr = valid_32bit_address(addr)?;
896        set_hw_breakpoint(&mut *self.memory, self.base_address, bp_unit_index, addr)?;
897        Ok(())
898    }
899
900    fn clear_hw_breakpoint(&mut self, bp_unit_index: usize) -> Result<(), Error> {
901        clear_hw_breakpoint(&mut *self.memory, self.base_address, bp_unit_index)?;
902        Ok(())
903    }
904
905    fn registers(&self) -> &'static CoreRegisters {
906        match self.state.fp_reg_count {
907            16 => &AARCH32_WITH_FP_16_CORE_REGISTERS,
908            32 => &AARCH32_WITH_FP_32_CORE_REGISTERS,
909            _ => &AARCH32_CORE_REGISTERS,
910        }
911    }
912
913    fn program_counter(&self) -> &'static CoreRegister {
914        &PC
915    }
916
917    fn frame_pointer(&self) -> &'static CoreRegister {
918        &FP
919    }
920
921    fn stack_pointer(&self) -> &'static CoreRegister {
922        &SP
923    }
924
925    fn return_address(&self) -> &'static CoreRegister {
926        &RA
927    }
928
929    fn hw_breakpoints_enabled(&self) -> bool {
930        true
931    }
932
933    fn architecture(&self) -> Architecture {
934        Architecture::Arm
935    }
936
937    fn core_type(&self) -> CoreType {
938        CoreType::Armv7a
939    }
940
941    fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
942        let cpsr: u32 = self.read_core_reg(RegisterId(16))?.try_into()?;
943
944        // CPSR bit 5 - T - Thumb mode
945        match (cpsr >> 5) & 1 {
946            1 => Ok(InstructionSet::Thumb2),
947            _ => Ok(InstructionSet::A32),
948        }
949    }
950
951    fn fpu_support(&mut self) -> Result<bool, Error> {
952        Ok(self.state.fp_reg_count != 0)
953    }
954
955    fn floating_point_register_count(&mut self) -> Result<usize, Error> {
956        Ok(self.state.fp_reg_count)
957    }
958
959    #[tracing::instrument(skip(self))]
960    fn reset_catch_set(&mut self) -> Result<(), Error> {
961        self.halted_access(|core| {
962            core.sequence.reset_catch_set(
963                &mut *core.memory,
964                CoreType::Armv7a,
965                Some(core.base_address),
966            )?;
967            Ok(())
968        })?;
969        Ok(())
970    }
971
972    #[tracing::instrument(skip(self))]
973    fn reset_catch_clear(&mut self) -> Result<(), Error> {
974        // Clear the reset_catch bit which was set earlier.
975        self.halted_access(|core| {
976            core.sequence.reset_catch_clear(
977                &mut *core.memory,
978                CoreType::Armv7a,
979                Some(core.base_address),
980            )?;
981            Ok(())
982        })?;
983        Ok(())
984    }
985
986    #[tracing::instrument(skip(self))]
987    fn debug_core_stop(&mut self) -> Result<(), Error> {
988        if matches!(self.state.current_state, CoreStatus::Halted(_)) {
989            // We may have clobbered registers we wrote during debugging
990            // Best effort attempt to put them back before we exit debug mode
991            self.writeback_registers()?;
992        }
993
994        self.sequence
995            .debug_core_stop(&mut *self.memory, CoreType::Armv7a)?;
996
997        Ok(())
998    }
999}
1000
1001impl MemoryInterface for Armv7a<'_> {
1002    fn supports_native_64bit_access(&mut self) -> bool {
1003        false
1004    }
1005
1006    fn read_word_64(&mut self, address: u64) -> Result<u64, Error> {
1007        self.halted_access(|core| {
1008            let mut ret: u64 = core.read_word_32(address)? as u64;
1009            ret |= (core.read_word_32(address + 4)? as u64) << 32;
1010
1011            Ok(ret)
1012        })
1013    }
1014
1015    fn read_word_32(&mut self, address: u64) -> Result<u32, Error> {
1016        self.halted_access(|core| {
1017            let address = valid_32bit_address(address)?;
1018
1019            // LDC p14, c5, [r0], #4
1020            let instr = build_ldc(14, 5, 0, 4);
1021
1022            // Save r0
1023            core.prepare_r0_for_clobber()?;
1024
1025            // Load r0 with the address to read from
1026            core.set_r0(address)?;
1027
1028            // Read memory from [r0]
1029            core.execute_instruction_with_result(instr)
1030        })
1031    }
1032
1033    fn read_word_16(&mut self, address: u64) -> Result<u16, Error> {
1034        self.halted_access(|core| {
1035            // Find the word this is in and its byte offset
1036            let byte_offset = address % 4;
1037            let word_start = address - byte_offset;
1038
1039            // Read the word
1040            let data = core.read_word_32(word_start)?;
1041
1042            // Return the byte
1043            Ok((data >> (byte_offset * 8)) as u16)
1044        })
1045    }
1046
1047    fn read_word_8(&mut self, address: u64) -> Result<u8, Error> {
1048        self.halted_access(|core| {
1049            // Find the word this is in and its byte offset
1050            let byte_offset = address % 4;
1051            let word_start = address - byte_offset;
1052
1053            // Read the word
1054            let data = core.read_word_32(word_start)?;
1055
1056            // Return the byte
1057            Ok(data.to_le_bytes()[byte_offset as usize])
1058        })
1059    }
1060
1061    fn read_64(&mut self, address: u64, data: &mut [u64]) -> Result<(), Error> {
1062        self.halted_access(|core| {
1063            for (i, word) in data.iter_mut().enumerate() {
1064                *word = core.read_word_64(address + ((i as u64) * 8))?;
1065            }
1066
1067            Ok(())
1068        })
1069    }
1070
1071    fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), Error> {
1072        self.halted_access(|core| {
1073            for (i, word) in data.iter_mut().enumerate() {
1074                *word = core.read_word_32(address + ((i as u64) * 4))?;
1075            }
1076
1077            Ok(())
1078        })
1079    }
1080
1081    fn read_16(&mut self, address: u64, data: &mut [u16]) -> Result<(), Error> {
1082        self.halted_access(|core| {
1083            for (i, word) in data.iter_mut().enumerate() {
1084                *word = core.read_word_16(address + ((i as u64) * 2))?;
1085            }
1086
1087            Ok(())
1088        })
1089    }
1090
1091    fn read_8(&mut self, address: u64, data: &mut [u8]) -> Result<(), Error> {
1092        self.halted_access(|core| {
1093            for (i, byte) in data.iter_mut().enumerate() {
1094                *byte = core.read_word_8(address + (i as u64))?;
1095            }
1096
1097            Ok(())
1098        })
1099    }
1100
1101    fn write_word_64(&mut self, address: u64, data: u64) -> Result<(), Error> {
1102        self.halted_access(|core| {
1103            let data_low = data as u32;
1104            let data_high = (data >> 32) as u32;
1105
1106            core.write_word_32(address, data_low)?;
1107            core.write_word_32(address + 4, data_high)
1108        })
1109    }
1110
1111    fn write_word_32(&mut self, address: u64, data: u32) -> Result<(), Error> {
1112        self.halted_access(|core| {
1113            let address = valid_32bit_address(address)?;
1114
1115            // STC p14, c5, [r0], #4
1116            let instr = build_stc(14, 5, 0, 4);
1117
1118            // Save r0
1119            core.prepare_r0_for_clobber()?;
1120
1121            // Load r0 with the address to write to
1122            core.set_r0(address)?;
1123
1124            // Write to [r0]
1125            core.execute_instruction_with_input(instr, data)
1126        })
1127    }
1128
1129    fn write_word_8(&mut self, address: u64, data: u8) -> Result<(), Error> {
1130        self.halted_access(|core| {
1131            // Find the word this is in and its byte offset
1132            let byte_offset = address % 4;
1133            let word_start = address - byte_offset;
1134
1135            // Get the current word value
1136            let current_word = core.read_word_32(word_start)?;
1137            let mut word_bytes = current_word.to_le_bytes();
1138            word_bytes[byte_offset as usize] = data;
1139
1140            core.write_word_32(word_start, u32::from_le_bytes(word_bytes))
1141        })
1142    }
1143
1144    fn write_word_16(&mut self, address: u64, data: u16) -> Result<(), Error> {
1145        self.halted_access(|core| {
1146            // Find the word this is in and its byte offset
1147            let byte_offset = address % 4;
1148            let word_start = address - byte_offset;
1149
1150            // Get the current word value
1151            let mut word = core.read_word_32(word_start)?;
1152
1153            // patch the word into it
1154            word &= !(0xFFFFu32 << (byte_offset * 8));
1155            word |= (data as u32) << (byte_offset * 8);
1156
1157            core.write_word_32(word_start, word)
1158        })
1159    }
1160
1161    fn write_64(&mut self, address: u64, data: &[u64]) -> Result<(), Error> {
1162        self.halted_access(|core| {
1163            for (i, word) in data.iter().enumerate() {
1164                core.write_word_64(address + ((i as u64) * 8), *word)?;
1165            }
1166
1167            Ok(())
1168        })
1169    }
1170
1171    fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), Error> {
1172        self.halted_access(|core| {
1173            for (i, word) in data.iter().enumerate() {
1174                core.write_word_32(address + ((i as u64) * 4), *word)?;
1175            }
1176
1177            Ok(())
1178        })
1179    }
1180
1181    fn write_16(&mut self, address: u64, data: &[u16]) -> Result<(), Error> {
1182        self.halted_access(|core| {
1183            for (i, word) in data.iter().enumerate() {
1184                core.write_word_16(address + ((i as u64) * 2), *word)?;
1185            }
1186
1187            Ok(())
1188        })
1189    }
1190
1191    fn write_8(&mut self, address: u64, data: &[u8]) -> Result<(), Error> {
1192        self.halted_access(|core| {
1193            for (i, byte) in data.iter().enumerate() {
1194                core.write_word_8(address + (i as u64), *byte)?;
1195            }
1196
1197            Ok(())
1198        })
1199    }
1200
1201    fn supports_8bit_transfers(&self) -> Result<bool, Error> {
1202        Ok(false)
1203    }
1204
1205    fn flush(&mut self) -> Result<(), Error> {
1206        // Nothing to do - this runs through the CPU which automatically handles any caching
1207        Ok(())
1208    }
1209}
1210
1211#[cfg(test)]
1212mod test {
1213    use crate::{
1214        architecture::arm::{
1215            FullyQualifiedApAddress, communication_interface::SwdSequence,
1216            sequences::DefaultArmSequence,
1217        },
1218        probe::DebugProbeError,
1219    };
1220
1221    use super::*;
1222
1223    const TEST_BASE_ADDRESS: u64 = 0x8000_1000;
1224
1225    fn address_to_reg_num(address: u64) -> u32 {
1226        ((address - TEST_BASE_ADDRESS) / 4) as u32
1227    }
1228
1229    pub struct ExpectedMemoryOp {
1230        read: bool,
1231        address: u64,
1232        value: u32,
1233    }
1234
1235    pub struct MockProbe {
1236        expected_ops: Vec<ExpectedMemoryOp>,
1237    }
1238
1239    impl MockProbe {
1240        pub fn new() -> Self {
1241            MockProbe {
1242                expected_ops: vec![],
1243            }
1244        }
1245
1246        pub fn expected_read(&mut self, addr: u64, value: u32) {
1247            self.expected_ops.push(ExpectedMemoryOp {
1248                read: true,
1249                address: addr,
1250                value,
1251            });
1252        }
1253
1254        pub fn expected_write(&mut self, addr: u64, value: u32) {
1255            self.expected_ops.push(ExpectedMemoryOp {
1256                read: false,
1257                address: addr,
1258                value,
1259            });
1260        }
1261    }
1262
1263    impl MemoryInterface<ArmError> for MockProbe {
1264        fn read_8(&mut self, _address: u64, _data: &mut [u8]) -> Result<(), ArmError> {
1265            todo!()
1266        }
1267
1268        fn read_16(&mut self, _address: u64, _data: &mut [u16]) -> Result<(), ArmError> {
1269            todo!()
1270        }
1271
1272        fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), ArmError> {
1273            if self.expected_ops.is_empty() {
1274                panic!(
1275                    "Received unexpected read_32 op: register {:#}",
1276                    address_to_reg_num(address)
1277                );
1278            }
1279
1280            assert_eq!(data.len(), 1);
1281
1282            let expected_op = self.expected_ops.remove(0);
1283
1284            assert!(
1285                expected_op.read,
1286                "R/W mismatch for register: Expected {:#} Actual: {:#}",
1287                address_to_reg_num(expected_op.address),
1288                address_to_reg_num(address)
1289            );
1290            assert_eq!(
1291                expected_op.address,
1292                address,
1293                "Read from unexpected register: Expected {:#} Actual: {:#}",
1294                address_to_reg_num(expected_op.address),
1295                address_to_reg_num(address)
1296            );
1297
1298            data[0] = expected_op.value;
1299
1300            Ok(())
1301        }
1302
1303        fn read(&mut self, address: u64, data: &mut [u8]) -> Result<(), ArmError> {
1304            self.read_8(address, data)
1305        }
1306
1307        fn write_8(&mut self, _address: u64, _data: &[u8]) -> Result<(), ArmError> {
1308            todo!()
1309        }
1310
1311        fn write_16(&mut self, _address: u64, _data: &[u16]) -> Result<(), ArmError> {
1312            todo!()
1313        }
1314
1315        fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), ArmError> {
1316            if self.expected_ops.is_empty() {
1317                panic!(
1318                    "Received unexpected write_32 op: register {:#}",
1319                    address_to_reg_num(address)
1320                );
1321            }
1322
1323            assert_eq!(data.len(), 1);
1324
1325            let expected_op = self.expected_ops.remove(0);
1326
1327            assert!(
1328                !expected_op.read,
1329                "Read/write mismatch on register: {:#}",
1330                address_to_reg_num(address)
1331            );
1332            assert_eq!(
1333                expected_op.address,
1334                address,
1335                "Write to unexpected register: Expected {:#} Actual: {:#}",
1336                address_to_reg_num(expected_op.address),
1337                address_to_reg_num(address)
1338            );
1339
1340            assert_eq!(
1341                expected_op.value, data[0],
1342                "Write value mismatch Expected {:#X} Actual: {:#X}",
1343                expected_op.value, data[0]
1344            );
1345
1346            Ok(())
1347        }
1348
1349        fn write(&mut self, address: u64, data: &[u8]) -> Result<(), ArmError> {
1350            self.write_8(address, data)
1351        }
1352
1353        fn flush(&mut self) -> Result<(), ArmError> {
1354            todo!()
1355        }
1356
1357        fn read_64(&mut self, _address: u64, _data: &mut [u64]) -> Result<(), ArmError> {
1358            todo!()
1359        }
1360
1361        fn write_64(&mut self, _address: u64, _data: &[u64]) -> Result<(), ArmError> {
1362            todo!()
1363        }
1364
1365        fn supports_8bit_transfers(&self) -> Result<bool, ArmError> {
1366            Ok(false)
1367        }
1368
1369        fn supports_native_64bit_access(&mut self) -> bool {
1370            false
1371        }
1372    }
1373
1374    impl ArmMemoryInterface for MockProbe {
1375        fn fully_qualified_address(&self) -> FullyQualifiedApAddress {
1376            todo!()
1377        }
1378
1379        fn get_swd_sequence(&mut self) -> Result<&mut dyn SwdSequence, DebugProbeError> {
1380            Err(DebugProbeError::NotImplemented {
1381                function_name: "get_swd_sequence",
1382            })
1383        }
1384
1385        fn get_arm_probe_interface(
1386            &mut self,
1387        ) -> Result<&mut dyn crate::architecture::arm::ArmProbeInterface, DebugProbeError> {
1388            Err(DebugProbeError::NotImplemented {
1389                function_name: "get_arm_probe_interface",
1390            })
1391        }
1392
1393        fn get_dap_access(
1394            &mut self,
1395        ) -> Result<&mut dyn crate::architecture::arm::DapAccess, DebugProbeError> {
1396            Err(DebugProbeError::NotImplemented {
1397                function_name: "get_dap_access",
1398            })
1399        }
1400
1401        fn generic_status(&mut self) -> Result<crate::architecture::arm::ap::CSW, ArmError> {
1402            Err(ArmError::Probe(DebugProbeError::NotImplemented {
1403                function_name: "generic_status",
1404            }))
1405        }
1406
1407        fn base_address(&mut self) -> Result<u64, ArmError> {
1408            todo!()
1409        }
1410    }
1411
1412    impl SwdSequence for MockProbe {
1413        fn swj_sequence(&mut self, _bit_len: u8, _bits: u64) -> Result<(), DebugProbeError> {
1414            todo!()
1415        }
1416
1417        fn swj_pins(
1418            &mut self,
1419            _pin_out: u32,
1420            _pin_select: u32,
1421            _pin_wait: u32,
1422        ) -> Result<u32, DebugProbeError> {
1423            todo!()
1424        }
1425    }
1426
1427    fn add_status_expectations(probe: &mut MockProbe, halted: bool) {
1428        let mut dbgdscr = Dbgdscr(0);
1429        dbgdscr.set_halted(halted);
1430        dbgdscr.set_restarted(true);
1431        probe.expected_read(
1432            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1433            dbgdscr.into(),
1434        );
1435    }
1436
1437    fn add_enable_itr_expectations(probe: &mut MockProbe) {
1438        let mut dbgdscr = Dbgdscr(0);
1439        dbgdscr.set_halted(true);
1440        probe.expected_read(
1441            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1442            dbgdscr.into(),
1443        );
1444        dbgdscr.set_itren(true);
1445        probe.expected_write(
1446            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1447            dbgdscr.into(),
1448        );
1449    }
1450
1451    fn add_read_reg_expectations(probe: &mut MockProbe, reg: u16, value: u32) {
1452        probe.expected_write(
1453            Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1454            build_mcr(14, 0, reg, 0, 5, 0),
1455        );
1456        let mut dbgdscr = Dbgdscr(0);
1457        dbgdscr.set_instrcoml_l(true);
1458        dbgdscr.set_txfull_l(true);
1459
1460        probe.expected_read(
1461            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1462            dbgdscr.into(),
1463        );
1464        probe.expected_read(
1465            Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1466            value,
1467        );
1468    }
1469
1470    fn add_read_pc_expectations(probe: &mut MockProbe, value: u32) {
1471        let mut dbgdscr = Dbgdscr(0);
1472        dbgdscr.set_instrcoml_l(true);
1473        dbgdscr.set_txfull_l(true);
1474
1475        probe.expected_write(
1476            Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1477            build_mov(0, 15),
1478        );
1479        probe.expected_read(
1480            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1481            dbgdscr.into(),
1482        );
1483        // + 8 to add expected offset on halt
1484        add_read_reg_expectations(probe, 0, value + 8);
1485    }
1486
1487    fn add_read_fp_count_expectations(probe: &mut MockProbe) {
1488        let mut dbgdscr = Dbgdscr(0);
1489        dbgdscr.set_instrcoml_l(true);
1490        dbgdscr.set_txfull_l(true);
1491
1492        probe.expected_write(
1493            Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1494            build_vmrs(0, 0b0111),
1495        );
1496        probe.expected_read(
1497            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1498            dbgdscr.into(),
1499        );
1500        add_read_reg_expectations(probe, 0, 0b010);
1501    }
1502
1503    fn add_read_cpsr_expectations(probe: &mut MockProbe, value: u32) {
1504        let mut dbgdscr = Dbgdscr(0);
1505        dbgdscr.set_instrcoml_l(true);
1506        dbgdscr.set_txfull_l(true);
1507
1508        probe.expected_write(
1509            Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1510            build_mrs(0),
1511        );
1512        probe.expected_read(
1513            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1514            dbgdscr.into(),
1515        );
1516        add_read_reg_expectations(probe, 0, value);
1517    }
1518
1519    fn add_idr_expectations(probe: &mut MockProbe, bp_count: u32) {
1520        let mut dbgdidr = Dbgdidr(0);
1521        dbgdidr.set_brps(bp_count - 1);
1522        probe.expected_read(
1523            Dbgdidr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1524            dbgdidr.into(),
1525        );
1526    }
1527
1528    fn add_set_r0_expectation(probe: &mut MockProbe, value: u32) {
1529        let mut dbgdscr = Dbgdscr(0);
1530        dbgdscr.set_instrcoml_l(true);
1531        dbgdscr.set_rxfull_l(true);
1532
1533        probe.expected_write(
1534            Dbgdtrrx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1535            value,
1536        );
1537        probe.expected_read(
1538            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1539            dbgdscr.into(),
1540        );
1541
1542        probe.expected_write(
1543            Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1544            build_mrc(14, 0, 0, 0, 5, 0),
1545        );
1546        probe.expected_read(
1547            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1548            dbgdscr.into(),
1549        );
1550    }
1551
1552    fn add_read_memory_expectations(probe: &mut MockProbe, address: u64, value: u32) {
1553        add_set_r0_expectation(probe, address as u32);
1554
1555        let mut dbgdscr = Dbgdscr(0);
1556        dbgdscr.set_instrcoml_l(true);
1557        dbgdscr.set_txfull_l(true);
1558
1559        probe.expected_write(
1560            Dbgitr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1561            build_ldc(14, 5, 0, 4),
1562        );
1563        probe.expected_read(
1564            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1565            dbgdscr.into(),
1566        );
1567        probe.expected_read(
1568            Dbgdtrtx::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1569            value,
1570        );
1571    }
1572
1573    #[test]
1574    fn armv7a_new() {
1575        let mut probe = MockProbe::new();
1576
1577        // Add expectations
1578        add_status_expectations(&mut probe, true);
1579        add_enable_itr_expectations(&mut probe);
1580        add_read_reg_expectations(&mut probe, 0, 0);
1581        add_read_fp_count_expectations(&mut probe);
1582
1583        let mock_mem = Box::new(probe) as _;
1584
1585        let _ = Armv7a::new(
1586            mock_mem,
1587            &mut CortexAState::new(),
1588            TEST_BASE_ADDRESS,
1589            DefaultArmSequence::create(),
1590        )
1591        .unwrap();
1592    }
1593
1594    #[test]
1595    fn armv7a_core_halted() {
1596        let mut probe = MockProbe::new();
1597        let mut state = CortexAState::new();
1598
1599        // Add expectations
1600        add_status_expectations(&mut probe, true);
1601        add_enable_itr_expectations(&mut probe);
1602        add_read_reg_expectations(&mut probe, 0, 0);
1603        add_read_fp_count_expectations(&mut probe);
1604
1605        let mut dbgdscr = Dbgdscr(0);
1606        dbgdscr.set_halted(false);
1607        probe.expected_read(
1608            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1609            dbgdscr.into(),
1610        );
1611
1612        dbgdscr.set_halted(true);
1613        probe.expected_read(
1614            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1615            dbgdscr.into(),
1616        );
1617
1618        let mock_mem = Box::new(probe) as _;
1619
1620        let mut armv7a = Armv7a::new(
1621            mock_mem,
1622            &mut state,
1623            TEST_BASE_ADDRESS,
1624            DefaultArmSequence::create(),
1625        )
1626        .unwrap();
1627
1628        // First read false, second read true
1629        assert!(!armv7a.core_halted().unwrap());
1630        assert!(armv7a.core_halted().unwrap());
1631    }
1632
1633    #[test]
1634    fn armv7a_wait_for_core_halted() {
1635        let mut probe = MockProbe::new();
1636        let mut state = CortexAState::new();
1637
1638        // Add expectations
1639        add_status_expectations(&mut probe, true);
1640        add_enable_itr_expectations(&mut probe);
1641        add_read_reg_expectations(&mut probe, 0, 0);
1642        add_read_fp_count_expectations(&mut probe);
1643
1644        let mut dbgdscr = Dbgdscr(0);
1645        dbgdscr.set_halted(false);
1646        probe.expected_read(
1647            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1648            dbgdscr.into(),
1649        );
1650
1651        dbgdscr.set_halted(true);
1652        probe.expected_read(
1653            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1654            dbgdscr.into(),
1655        );
1656
1657        let mock_mem = Box::new(probe) as _;
1658
1659        let mut armv7a = Armv7a::new(
1660            mock_mem,
1661            &mut state,
1662            TEST_BASE_ADDRESS,
1663            DefaultArmSequence::create(),
1664        )
1665        .unwrap();
1666
1667        // Should halt on second read
1668        armv7a
1669            .wait_for_core_halted(Duration::from_millis(100))
1670            .unwrap();
1671    }
1672
1673    #[test]
1674    fn armv7a_status_running() {
1675        let mut probe = MockProbe::new();
1676        let mut state = CortexAState::new();
1677
1678        // Add expectations
1679        add_status_expectations(&mut probe, true);
1680        add_enable_itr_expectations(&mut probe);
1681        add_read_reg_expectations(&mut probe, 0, 0);
1682        add_read_fp_count_expectations(&mut probe);
1683
1684        let mut dbgdscr = Dbgdscr(0);
1685        dbgdscr.set_halted(false);
1686        probe.expected_read(
1687            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1688            dbgdscr.into(),
1689        );
1690
1691        let mock_mem = Box::new(probe) as _;
1692
1693        let mut armv7a = Armv7a::new(
1694            mock_mem,
1695            &mut state,
1696            TEST_BASE_ADDRESS,
1697            DefaultArmSequence::create(),
1698        )
1699        .unwrap();
1700
1701        // Should halt on second read
1702        assert_eq!(CoreStatus::Running, armv7a.status().unwrap());
1703    }
1704
1705    #[test]
1706    fn armv7a_status_halted() {
1707        let mut probe = MockProbe::new();
1708        let mut state = CortexAState::new();
1709
1710        // Add expectations
1711        add_status_expectations(&mut probe, true);
1712        add_enable_itr_expectations(&mut probe);
1713        add_read_reg_expectations(&mut probe, 0, 0);
1714        add_read_fp_count_expectations(&mut probe);
1715
1716        let mut dbgdscr = Dbgdscr(0);
1717        dbgdscr.set_halted(true);
1718        probe.expected_read(
1719            Dbgdscr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1720            dbgdscr.into(),
1721        );
1722        add_read_fp_count_expectations(&mut probe);
1723
1724        let mock_mem = Box::new(probe) as _;
1725
1726        let mut armv7a = Armv7a::new(
1727            mock_mem,
1728            &mut state,
1729            TEST_BASE_ADDRESS,
1730            DefaultArmSequence::create(),
1731        )
1732        .unwrap();
1733
1734        // Should halt on second read
1735        assert_eq!(
1736            CoreStatus::Halted(crate::HaltReason::Request),
1737            armv7a.status().unwrap()
1738        );
1739    }
1740
1741    #[test]
1742    fn armv7a_read_core_reg_common() {
1743        const REG_VALUE: u32 = 0xABCD;
1744
1745        let mut probe = MockProbe::new();
1746        let mut state = CortexAState::new();
1747
1748        // Add expectations
1749        add_status_expectations(&mut probe, true);
1750        add_enable_itr_expectations(&mut probe);
1751        add_read_reg_expectations(&mut probe, 0, 0);
1752        add_read_fp_count_expectations(&mut probe);
1753
1754        // Read register
1755        add_read_reg_expectations(&mut probe, 2, REG_VALUE);
1756
1757        let mock_mem = Box::new(probe) as _;
1758
1759        let mut armv7a = Armv7a::new(
1760            mock_mem,
1761            &mut state,
1762            TEST_BASE_ADDRESS,
1763            DefaultArmSequence::create(),
1764        )
1765        .unwrap();
1766
1767        // First read will hit expectations
1768        assert_eq!(
1769            RegisterValue::from(REG_VALUE),
1770            armv7a.read_core_reg(RegisterId(2)).unwrap()
1771        );
1772
1773        // Second read will cache, no new expectations
1774        assert_eq!(
1775            RegisterValue::from(REG_VALUE),
1776            armv7a.read_core_reg(RegisterId(2)).unwrap()
1777        );
1778    }
1779
1780    #[test]
1781    fn armv7a_read_core_reg_pc() {
1782        const REG_VALUE: u32 = 0xABCD;
1783
1784        let mut probe = MockProbe::new();
1785        let mut state = CortexAState::new();
1786
1787        // Add expectations
1788        add_status_expectations(&mut probe, true);
1789        add_enable_itr_expectations(&mut probe);
1790        add_read_reg_expectations(&mut probe, 0, 0);
1791        add_read_fp_count_expectations(&mut probe);
1792
1793        // Read PC
1794        add_read_pc_expectations(&mut probe, REG_VALUE);
1795
1796        let mock_mem = Box::new(probe) as _;
1797
1798        let mut armv7a = Armv7a::new(
1799            mock_mem,
1800            &mut state,
1801            TEST_BASE_ADDRESS,
1802            DefaultArmSequence::create(),
1803        )
1804        .unwrap();
1805
1806        // First read will hit expectations
1807        assert_eq!(
1808            RegisterValue::from(REG_VALUE),
1809            armv7a.read_core_reg(RegisterId(15)).unwrap()
1810        );
1811
1812        // Second read will cache, no new expectations
1813        assert_eq!(
1814            RegisterValue::from(REG_VALUE),
1815            armv7a.read_core_reg(RegisterId(15)).unwrap()
1816        );
1817    }
1818
1819    #[test]
1820    fn armv7a_read_core_reg_cpsr() {
1821        const REG_VALUE: u32 = 0xABCD;
1822
1823        let mut probe = MockProbe::new();
1824        let mut state = CortexAState::new();
1825
1826        // Add expectations
1827        add_status_expectations(&mut probe, true);
1828        add_enable_itr_expectations(&mut probe);
1829        add_read_reg_expectations(&mut probe, 0, 0);
1830        add_read_fp_count_expectations(&mut probe);
1831
1832        // Read CPSR
1833        add_read_cpsr_expectations(&mut probe, REG_VALUE);
1834
1835        let mock_mem = Box::new(probe) as _;
1836
1837        let mut armv7a = Armv7a::new(
1838            mock_mem,
1839            &mut state,
1840            TEST_BASE_ADDRESS,
1841            DefaultArmSequence::create(),
1842        )
1843        .unwrap();
1844
1845        // First read will hit expectations
1846        assert_eq!(
1847            RegisterValue::from(REG_VALUE),
1848            armv7a.read_core_reg(RegisterId(16)).unwrap()
1849        );
1850
1851        // Second read will cache, no new expectations
1852        assert_eq!(
1853            RegisterValue::from(REG_VALUE),
1854            armv7a.read_core_reg(RegisterId(16)).unwrap()
1855        );
1856    }
1857
1858    #[test]
1859    fn armv7a_halt() {
1860        const REG_VALUE: u32 = 0xABCD;
1861
1862        let mut probe = MockProbe::new();
1863        let mut state = CortexAState::new();
1864
1865        // Add expectations
1866        add_status_expectations(&mut probe, false);
1867
1868        // Write halt request
1869        let mut dbgdrcr = Dbgdrcr(0);
1870        dbgdrcr.set_hrq(true);
1871        probe.expected_write(
1872            Dbgdrcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1873            dbgdrcr.into(),
1874        );
1875
1876        // Wait for halted
1877        add_status_expectations(&mut probe, true);
1878
1879        // Read status
1880        add_status_expectations(&mut probe, true);
1881        add_enable_itr_expectations(&mut probe);
1882        add_read_reg_expectations(&mut probe, 0, 0);
1883        add_read_fp_count_expectations(&mut probe);
1884
1885        // Read PC
1886        add_read_pc_expectations(&mut probe, REG_VALUE);
1887
1888        let mock_mem = Box::new(probe) as _;
1889
1890        let mut armv7a = Armv7a::new(
1891            mock_mem,
1892            &mut state,
1893            TEST_BASE_ADDRESS,
1894            DefaultArmSequence::create(),
1895        )
1896        .unwrap();
1897
1898        // Verify PC
1899        assert_eq!(
1900            REG_VALUE as u64,
1901            armv7a.halt(Duration::from_millis(100)).unwrap().pc
1902        );
1903    }
1904
1905    #[test]
1906    fn armv7a_run() {
1907        let mut probe = MockProbe::new();
1908        let mut state = CortexAState::new();
1909
1910        // Add expectations
1911        add_status_expectations(&mut probe, true);
1912        add_enable_itr_expectations(&mut probe);
1913        add_read_reg_expectations(&mut probe, 0, 0);
1914        add_read_fp_count_expectations(&mut probe);
1915
1916        // Writeback r0
1917        add_set_r0_expectation(&mut probe, 0);
1918
1919        // Write resume request
1920        let mut dbgdrcr = Dbgdrcr(0);
1921        dbgdrcr.set_rrq(true);
1922        probe.expected_write(
1923            Dbgdrcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1924            dbgdrcr.into(),
1925        );
1926
1927        // Wait for running
1928        add_status_expectations(&mut probe, false);
1929
1930        // Read status
1931        add_status_expectations(&mut probe, false);
1932
1933        let mock_mem = Box::new(probe) as _;
1934
1935        let mut armv7a = Armv7a::new(
1936            mock_mem,
1937            &mut state,
1938            TEST_BASE_ADDRESS,
1939            DefaultArmSequence::create(),
1940        )
1941        .unwrap();
1942
1943        armv7a.run().unwrap();
1944    }
1945
1946    #[test]
1947    fn armv7a_available_breakpoint_units() {
1948        const BP_COUNT: u32 = 4;
1949        let mut probe = MockProbe::new();
1950        let mut state = CortexAState::new();
1951
1952        // Add expectations
1953        add_status_expectations(&mut probe, true);
1954        add_enable_itr_expectations(&mut probe);
1955        add_read_reg_expectations(&mut probe, 0, 0);
1956        add_read_fp_count_expectations(&mut probe);
1957
1958        // Read breakpoint count
1959        add_idr_expectations(&mut probe, BP_COUNT);
1960
1961        let mock_mem = Box::new(probe) as _;
1962
1963        let mut armv7a = Armv7a::new(
1964            mock_mem,
1965            &mut state,
1966            TEST_BASE_ADDRESS,
1967            DefaultArmSequence::create(),
1968        )
1969        .unwrap();
1970
1971        assert_eq!(BP_COUNT, armv7a.available_breakpoint_units().unwrap());
1972    }
1973
1974    #[test]
1975    fn armv7a_hw_breakpoints() {
1976        const BP_COUNT: u32 = 4;
1977        const BP1: u64 = 0x2345;
1978        const BP2: u64 = 0x8000_0000;
1979        let mut probe = MockProbe::new();
1980        let mut state = CortexAState::new();
1981
1982        // Add expectations
1983        add_status_expectations(&mut probe, true);
1984        add_enable_itr_expectations(&mut probe);
1985        add_read_reg_expectations(&mut probe, 0, 0);
1986        add_read_fp_count_expectations(&mut probe);
1987
1988        // Read breakpoint count
1989        add_idr_expectations(&mut probe, BP_COUNT);
1990
1991        // Read BP values and controls
1992        probe.expected_read(
1993            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1994            BP1 as u32,
1995        );
1996        probe.expected_read(
1997            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
1998            1,
1999        );
2000
2001        probe.expected_read(
2002            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2003            BP2 as u32,
2004        );
2005        probe.expected_read(
2006            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + 4,
2007            1,
2008        );
2009
2010        probe.expected_read(
2011            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 4),
2012            0,
2013        );
2014        probe.expected_read(
2015            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (2 * 4),
2016            0,
2017        );
2018
2019        probe.expected_read(
2020            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 4),
2021            0,
2022        );
2023        probe.expected_read(
2024            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap() + (3 * 4),
2025            0,
2026        );
2027
2028        let mock_mem = Box::new(probe) as _;
2029
2030        let mut armv7a = Armv7a::new(
2031            mock_mem,
2032            &mut state,
2033            TEST_BASE_ADDRESS,
2034            DefaultArmSequence::create(),
2035        )
2036        .unwrap();
2037
2038        let results = armv7a.hw_breakpoints().unwrap();
2039        assert_eq!(Some(BP1), results[0]);
2040        assert_eq!(Some(BP2), results[1]);
2041        assert_eq!(None, results[2]);
2042        assert_eq!(None, results[3]);
2043    }
2044
2045    #[test]
2046    fn armv7a_set_hw_breakpoint() {
2047        const BP_VALUE: u64 = 0x2345;
2048        let mut probe = MockProbe::new();
2049        let mut state = CortexAState::new();
2050
2051        // Add expectations
2052        add_status_expectations(&mut probe, true);
2053        add_enable_itr_expectations(&mut probe);
2054        add_read_reg_expectations(&mut probe, 0, 0);
2055        add_read_fp_count_expectations(&mut probe);
2056
2057        // Update BP value and control
2058        let mut dbgbcr = Dbgbcr(0);
2059        // Match on all modes
2060        dbgbcr.set_hmc(true);
2061        dbgbcr.set_pmc(0b11);
2062        // Match on all bytes
2063        dbgbcr.set_bas(0b1111);
2064        // Enable
2065        dbgbcr.set_e(true);
2066
2067        probe.expected_write(
2068            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2069            BP_VALUE as u32,
2070        );
2071        probe.expected_write(
2072            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2073            dbgbcr.into(),
2074        );
2075
2076        let mock_mem = Box::new(probe) as _;
2077
2078        let mut armv7a = Armv7a::new(
2079            mock_mem,
2080            &mut state,
2081            TEST_BASE_ADDRESS,
2082            DefaultArmSequence::create(),
2083        )
2084        .unwrap();
2085
2086        armv7a.set_hw_breakpoint(0, BP_VALUE).unwrap();
2087    }
2088
2089    #[test]
2090    fn armv7a_clear_hw_breakpoint() {
2091        let mut probe = MockProbe::new();
2092        let mut state = CortexAState::new();
2093
2094        // Add expectations
2095        add_status_expectations(&mut probe, true);
2096        add_enable_itr_expectations(&mut probe);
2097        add_read_reg_expectations(&mut probe, 0, 0);
2098        add_read_fp_count_expectations(&mut probe);
2099
2100        // Update BP value and control
2101        probe.expected_write(
2102            Dbgbvr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2103            0,
2104        );
2105        probe.expected_write(
2106            Dbgbcr::get_mmio_address_from_base(TEST_BASE_ADDRESS).unwrap(),
2107            0,
2108        );
2109
2110        let mock_mem = Box::new(probe) as _;
2111
2112        let mut armv7a = Armv7a::new(
2113            mock_mem,
2114            &mut state,
2115            TEST_BASE_ADDRESS,
2116            DefaultArmSequence::create(),
2117        )
2118        .unwrap();
2119
2120        armv7a.clear_hw_breakpoint(0).unwrap();
2121    }
2122
2123    #[test]
2124    fn armv7a_read_word_32() {
2125        const MEMORY_VALUE: u32 = 0xBA5EBA11;
2126        const MEMORY_ADDRESS: u64 = 0x12345678;
2127
2128        let mut probe = MockProbe::new();
2129        let mut state = CortexAState::new();
2130
2131        // Add expectations
2132        add_status_expectations(&mut probe, true);
2133        add_enable_itr_expectations(&mut probe);
2134        add_read_reg_expectations(&mut probe, 0, 0);
2135        add_read_fp_count_expectations(&mut probe);
2136
2137        // Read memory
2138        add_read_memory_expectations(&mut probe, MEMORY_ADDRESS, MEMORY_VALUE);
2139
2140        let mock_mem = Box::new(probe) as _;
2141
2142        let mut armv7a = Armv7a::new(
2143            mock_mem,
2144            &mut state,
2145            TEST_BASE_ADDRESS,
2146            DefaultArmSequence::create(),
2147        )
2148        .unwrap();
2149
2150        assert_eq!(MEMORY_VALUE, armv7a.read_word_32(MEMORY_ADDRESS).unwrap());
2151    }
2152
2153    #[test]
2154    fn armv7a_read_word_8() {
2155        const MEMORY_VALUE: u32 = 0xBA5EBA11;
2156        const MEMORY_ADDRESS: u64 = 0x12345679;
2157        const MEMORY_WORD_ADDRESS: u64 = 0x12345678;
2158
2159        let mut probe = MockProbe::new();
2160        let mut state = CortexAState::new();
2161
2162        // Add expectations
2163        add_status_expectations(&mut probe, true);
2164        add_enable_itr_expectations(&mut probe);
2165        add_read_reg_expectations(&mut probe, 0, 0);
2166        add_read_fp_count_expectations(&mut probe);
2167
2168        // Read memory
2169        add_read_memory_expectations(&mut probe, MEMORY_WORD_ADDRESS, MEMORY_VALUE);
2170
2171        let mock_mem = Box::new(probe) as _;
2172
2173        let mut armv7a = Armv7a::new(
2174            mock_mem,
2175            &mut state,
2176            TEST_BASE_ADDRESS,
2177            DefaultArmSequence::create(),
2178        )
2179        .unwrap();
2180
2181        assert_eq!(0xBA, armv7a.read_word_8(MEMORY_ADDRESS).unwrap());
2182    }
2183}