@@ -200,15 +200,21 @@ static const uint16_t cortexr_spsr_encodings[5] = {
200
200
/*
201
201
* Instruction encodings for coprocessor load/store
202
202
* LDC -> Load Coprocessor (DDI0406C §A8.8.56, pg393)
203
+ * STC -> Store Corprocessor (DDI0406C §A8.8.119, pg663)
203
204
*/
204
205
#define ARM_LDC_INSN 0xec100000U
206
+ #define ARM_STC_INSN 0xec000000U
205
207
/*
206
208
* Pre-encoded LDC/STC operands for getting data in and out of the core
207
209
* The first is a LDC encoded to move [r0] to the debug DTR and then increment r0 by 4
208
210
* (`LDC p14, c5, [r0], #+4`, Preincrement = 0, Unindexed = 1, Doublelength = 0, Writeback = 1)
209
211
* The immediate is encoded shifted right by 2, and the reads are done 32 bits at a time.
212
+ * The second is a STC encoded to move from the debug DTR to [r0] and then increment r0 by 4
213
+ * (`STC p14, c5, [r0], #+4`, Preincrement = 0, Unindexed = 1, Doublelength = 0, Writeback = 1)
214
+ * As with read, the immediate is encoded shifted right by 2 and writes are done 32 bits at a time.
210
215
*/
211
216
#define ARM_LDC_R0_POSTINC4_DTRTX_INSN (ARM_LDC_INSN | 0x00a05e01U)
217
+ #define ARM_STC_DTRRX_R0_POSTINC4_INSN (ARM_STC_INSN | 0x00a05e01U)
212
218
213
219
/*
214
220
* Instruction encodings for indirect loads and stores of data via the CPU
@@ -805,9 +811,42 @@ static void cortexr_mem_read(target_s *const target, void *const dest, const tar
805
811
cortexr_mem_handle_fault (target , __func__ , fault_status , fault_addr );
806
812
}
807
813
814
+ /* Fast path for cortexr_mem_write(). Assumes the address to read data from is already loaded in r0. */
815
+ static inline bool cortexr_mem_write_fast (target_s * const target , const uint32_t * const src , const size_t count )
816
+ {
817
+ /* Read each of the uint32_t's checking for failure */
818
+ for (size_t offset = 0 ; offset < count ; ++ offset ) {
819
+ if (!cortexr_run_write_insn (target , ARM_STC_DTRRX_R0_POSTINC4_INSN , src [offset ]))
820
+ return false; /* Propagate failure if it happens */
821
+ }
822
+ return true; /* Signal success */
823
+ }
824
+
825
+ /*
826
+ * This writes memory by jumping from the debug unit bus to the system bus.
827
+ * NB: This requires the core to be halted! Uses instruction launches on
828
+ * the core and requires we're in debug mode to work. Trashes r0.
829
+ */
808
830
static void cortexr_mem_write (target_s * const target , const target_addr_t dest , const void * const src , const size_t len )
809
831
{
810
- adiv5_mem_write (cortex_ap (target ), dest , src , len );
832
+ cortexr_priv_s * const priv = (cortexr_priv_s * )target -> priv ;
833
+ DEBUG_TARGET ("%s: Writing %zu bytes @0x%" PRIx32 "\n" , __func__ , len , dest );
834
+ /* Cache DFSR and DFAR in case we wind up triggering a data fault */
835
+ const uint32_t fault_status = cortexr_coproc_read (target , CORTEXR_DFSR );
836
+ const uint32_t fault_addr = cortexr_coproc_read (target , CORTEXR_DFAR );
837
+ /* Clear any existing fault state */
838
+ priv -> core_status &= ~(CORTEXR_STATUS_DATA_FAULT | CORTEXR_STATUS_MMU_FAULT );
839
+
840
+ /* Move the start address into the core's r0 */
841
+ cortexr_core_reg_write (target , 0U , dest );
842
+
843
+ /* If the address is 32-bit aligned and we're writing 32 bits at a time, use the fast path */
844
+ if ((dest & 3U ) == 0U && (len & 3U ) == 0U )
845
+ cortexr_mem_write_fast (target , (const uint32_t * )src , len >> 2U );
846
+ else
847
+ adiv5_mem_write (cortex_ap (target ), dest , src , len );
848
+ /* Deal with any data faults that occured */
849
+ cortexr_mem_handle_fault (target , __func__ , fault_status , fault_addr );
811
850
}
812
851
813
852
static void cortexr_regs_read (target_s * const target , void * const data )
0 commit comments