diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2009-12-01 00:49:04 -0800 |
---|---|---|
committer | David Brownell <dbrownell@users.sourceforge.net> | 2009-12-01 00:49:04 -0800 |
commit | 563d937c3c6a7080998baa2313d66ae184b820ac (patch) | |
tree | 488384ceb5ba42dea28efbbcc42e1b82fd6c72fd /src/target | |
parent | 177bbd8891ae737ea7f8c0791a6236f72cedee40 (diff) | |
download | openocd+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/target')
-rw-r--r-- | src/target/arm_dpm.c | 59 |
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; } |