Skip to content

Commit 6a8bf71

Browse files
committed
cortexr: Implemented a slow path memory writer for cortexr_mem_write()
1 parent 1075874 commit 6a8bf71

File tree

1 file changed

+48
-1
lines changed

1 file changed

+48
-1
lines changed

src/target/cortexr.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,22 @@ static const uint16_t cortexr_spsr_encodings[5] = {
220220
* Instruction encodings for indirect loads and stores of data via the CPU
221221
* LDRB -> Load Register Byte (immediate) (DDI0406C §A8.8.69, pg419)
222222
* 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)
223225
*
224226
* The first is `LDRB r1, [r0], #+1` to load a uint8_t from [r0] into r1 and increment the
225227
* address in r0 by 1, writing the new address back to r0.
226228
* The second is `LDRH r1, [r0], #+2` to load a uint16_t from [r0] into r1 and increment
227229
* 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.
228234
*/
229235
#define ARM_LDRB_R0_R1_INSN 0xe4f01001U
230236
#define ARM_LDRH_R0_R1_INSN 0xe0f010b2U
237+
#define ARM_STRB_R1_R0_INSN 0xe4e01001U
238+
#define ARM_STRH_R1_R0_INSN 0xe0e010b2U
231239

232240
/* Coprocessor register definitions */
233241
#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
822830
return true; /* Signal success */
823831
}
824832

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+
825872
/*
826873
* This writes memory by jumping from the debug unit bus to the system bus.
827874
* 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,
844891
if ((dest & 3U) == 0U && (len & 3U) == 0U)
845892
cortexr_mem_write_fast(target, (const uint32_t *)src, len >> 2U);
846893
else
847-
adiv5_mem_write(cortex_ap(target), dest, src, len);
894+
cortexr_mem_write_slow(target, dest, (const uint8_t *)src, len);
848895
/* Deal with any data faults that occured */
849896
cortexr_mem_handle_fault(target, __func__, fault_status, fault_addr);
850897
}

0 commit comments

Comments
 (0)