summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-12-01 00:49:04 -0800
committerDavid Brownell <dbrownell@users.sourceforge.net>2009-12-01 00:49:04 -0800
commit563d937c3c6a7080998baa2313d66ae184b820ac (patch)
tree488384ceb5ba42dea28efbbcc42e1b82fd6c72fd /src
parent177bbd8891ae737ea7f8c0791a6236f72cedee40 (diff)
downloadopenocd+libswd-563d937c3c6a7080998baa2313d66ae184b820ac.tar.gz
openocd+libswd-563d937c3c6a7080998baa2313d66ae184b820ac.tar.bz2
openocd+libswd-563d937c3c6a7080998baa2313d66ae184b820ac.tar.xz
openocd+libswd-563d937c3c6a7080998baa2313d66ae184b820ac.zip
ARM: implement mrc()/mcr() as DPM ops
Instead of having separate ARM11 and Cortex-A8 implementations of this code, have one shared implementation which just builds on the existing "run instruction via R0" support. This enables followup patches to remove that now-unused code from those two drivers. (Patches to move the "mrc" and "mcr" code into "struct arm" are due too ... MIPS and other cores do not support those ARM-specific concepts.) Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'src')
-rw-r--r--src/target/arm_dpm.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c
index b8107d78..127f87b5 100644
--- a/src/target/arm_dpm.c
+++ b/src/target/arm_dpm.c
@@ -34,6 +34,61 @@
* implementation differences between cores like ARM1136 and Cortex-A8.
*/
+/*
+ * Coprocessor support
+ */
+
+/* Read coprocessor */
+static int dpm_mrc(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
+ uint32_t *value)
+{
+ struct arm *arm = target_to_arm(target);
+ struct arm_dpm *dpm = arm->dpm;
+ int retval;
+
+ retval = dpm->prepare(dpm);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum, op1, CRn, CRm, op2);
+
+ /* read coprocessor register into R0; return via DCC */
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2),
+ value);
+
+ /* (void) */ dpm->finish(dpm);
+ return retval;
+}
+
+static int dpm_mcr(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
+ uint32_t value)
+{
+ struct arm *arm = target_to_arm(target);
+ struct arm_dpm *dpm = arm->dpm;
+ int retval;
+
+ retval = dpm->prepare(dpm);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum, op1, CRn, CRm, op2);
+
+ /* read DCC into r0; then write coprocessor register from R0 */
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2),
+ value);
+
+ /* (void) */ dpm->finish(dpm);
+ return retval;
+}
+
+/*
+ * Register access utilities
+ */
+
/* Toggles between recorded core mode (USR, SVC, etc) and a temporary one.
* Routines *must* restore the original mode before returning!!
*/
@@ -510,6 +565,10 @@ int arm_dpm_setup(struct arm_dpm *dpm)
return ERROR_FAIL;
*register_get_last_cache_p(&target->reg_cache) = cache;
+
+ arm->mrc = dpm_mrc;
+ arm->mcr = dpm_mcr;
+
return ERROR_OK;
}