@@ -220,14 +220,22 @@ static const uint16_t cortexr_spsr_encodings[5] = {
220
220
* Instruction encodings for indirect loads and stores of data via the CPU
221
221
* LDRB -> Load Register Byte (immediate) (DDI0406C §A8.8.69, pg419)
222
222
* LDRH -> Load Register Halfword (immediate) (DDI0406C §A8.8.81, pg443)
223
+ * STRB -> Store Register Byte (immediate) (DDI0406C §A8.8.208, pg681)
224
+ * STRH -> Store Register Halfword (immediate) (DDI0406C §A8.8.218, pg701)
223
225
*
224
226
* The first is `LDRB r1, [r0], #+1` to load a uint8_t from [r0] into r1 and increment the
225
227
* address in r0 by 1, writing the new address back to r0.
226
228
* The second is `LDRH r1, [r0], #+2` to load a uint16_t from [r0] into r1 and increment
227
229
* the address in r0 by 2, writing the new address back to r0.
230
+ * The third is `STRB r1, [r0], #+1` to store a uint8_t to [r0] from r1 and increment the
231
+ * address in r0 by 1, writing the new address back to r0.
232
+ * The fourth is `STRH r1, [r0], #+2` to store a uint16_t to [r0] from r1 and increment
233
+ * the address in r0 by 2, writing the new address back to r0.
228
234
*/
229
235
#define ARM_LDRB_R0_R1_INSN 0xe4f01001U
230
236
#define ARM_LDRH_R0_R1_INSN 0xe0f010b2U
237
+ #define ARM_STRB_R1_R0_INSN 0xe4e01001U
238
+ #define ARM_STRH_R1_R0_INSN 0xe0e010b2U
231
239
232
240
/* Coprocessor register definitions */
233
241
#define CORTEXR_CPACR 15U, ENCODE_CP_REG(1U, 0U, 0U, 2U)
@@ -822,6 +830,45 @@ static inline bool cortexr_mem_write_fast(target_s *const target, const uint32_t
822
830
return true; /* Signal success */
823
831
}
824
832
833
+ /* Slow path for cortexr_mem_write(). Trashes r0 and r1. */
834
+ static bool cortexr_mem_write_slow (
835
+ target_s * const target , target_addr_t addr , const uint8_t * const data , const size_t length )
836
+ {
837
+ size_t offset = 0 ;
838
+ /* If the address is odd, write a byte to get onto an even address */
839
+ if (addr & 1U ) {
840
+ cortexr_core_reg_write (target , 1U , data [offset ++ ]);
841
+ if (!cortexr_run_insn (target , ARM_STRB_R1_R0_INSN ))
842
+ return false;
843
+ ++ addr ;
844
+ }
845
+ /* If the address is now even but only 16-bit aligned, write a uint16_t to get onto 32-bit alignment */
846
+ if ((addr & 2U ) && length - offset >= 2U ) {
847
+ cortexr_core_reg_write (target , 1U , read_le2 (data , offset ));
848
+ if (!cortexr_run_insn (target , ARM_STRH_R1_R0_INSN ))
849
+ return false;
850
+ offset += 2U ;
851
+ }
852
+ /* Use the fast path to write as much as possible before doing a slow path fixup at the end */
853
+ if (!cortexr_mem_write_fast (target , (uint32_t * )(data + offset ), (length - offset ) >> 2U ))
854
+ return false;
855
+ const uint8_t remainder = (length - offset ) & 3U ;
856
+ /* If the remainder needs at least 2 more bytes write, do this first */
857
+ if (remainder & 2U ) {
858
+ cortexr_core_reg_write (target , 1U , read_le2 (data , offset ));
859
+ if (!cortexr_run_insn (target , ARM_STRH_R1_R0_INSN ))
860
+ return false;
861
+ offset += 2U ;
862
+ }
863
+ /* Finally, fix things up if a final byte is required. */
864
+ if (remainder & 1U ) {
865
+ cortexr_core_reg_write (target , 1U , data [offset ]);
866
+ if (!cortexr_run_insn (target , ARM_STRB_R1_R0_INSN ))
867
+ return false;
868
+ }
869
+ return true; /* Signal success */
870
+ }
871
+
825
872
/*
826
873
* This writes memory by jumping from the debug unit bus to the system bus.
827
874
* NB: This requires the core to be halted! Uses instruction launches on
@@ -844,7 +891,7 @@ static void cortexr_mem_write(target_s *const target, const target_addr_t dest,
844
891
if ((dest & 3U ) == 0U && (len & 3U ) == 0U )
845
892
cortexr_mem_write_fast (target , (const uint32_t * )src , len >> 2U );
846
893
else
847
- adiv5_mem_write ( cortex_ap ( target ) , dest , src , len );
894
+ cortexr_mem_write_slow ( target , dest , ( const uint8_t * ) src , len );
848
895
/* Deal with any data faults that occured */
849
896
cortexr_mem_handle_fault (target , __func__ , fault_status , fault_addr );
850
897
}
0 commit comments