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