* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
return retval;
}
+/**
+ * Write to program counter and switch the core state (arm/thumb) according to
+ * the address.
+ */
+static int dpm_write_pc_core_state(struct arm_dpm *dpm, struct reg *r)
+{
+ uint32_t value = buf_get_u32(r->value, 0, 32);
+
+ /* read r0 from DCC; then "BX r0" */
+ return dpm->instr_write_data_r0(dpm, ARMV4_5_BX(0), value);
+}
+
/**
* Read basic registers of the the current context: R0 to R15, and CPSR;
* sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
goto done;
arm->cpsr->dirty = false;
+ /* restore the PC, make sure to also switch the core state
+ * to whatever it was set to with "arm core_state" command.
+ * target code will have set PC to an appropriate resume address.
+ */
+ retval = dpm_write_pc_core_state(dpm, arm->pc);
+ if (retval != ERROR_OK)
+ goto done;
+ /* on Cortex-A5 (as found on NXP VF610 SoC), BX instruction
+ * executed in debug state doesn't appear to set the PC,
+ * explicitly set it with a "MOV pc, r0". This doesn't influence
+ * CPSR on Cortex-A9 so it should be OK. Maybe due to different
+ * debug version?
+ */
retval = dpm_write_reg(dpm, arm->pc, 15);
if (retval != ERROR_OK)
goto done;
}
static int arm_dpm_write_core_reg(struct target *target, struct reg *r,
- int regnum, enum arm_mode mode, uint32_t value)
+ int regnum, enum arm_mode mode, uint8_t *value)
{
struct arm_dpm *dpm = target_to_arm(target)->dpm;
int retval;
did_read = true;
mode = r->mode;
- /* For R8..R12 when we've entered debug
- * state in FIQ mode... patch mode.
+ /* For regular (ARM_MODE_ANY) R8..R12
+ * in case we've entered debug state
+ * in FIQ mode we need to patch mode.
*/
- if (mode == ARM_MODE_ANY)
- mode = ARM_MODE_USR;
+ if (mode != ARM_MODE_ANY)
+ retval = dpm_modeswitch(dpm, mode);
+ else
+ retval = dpm_modeswitch(dpm, ARM_MODE_USR);
- /* REVISIT error checks */
- retval = dpm_modeswitch(dpm, mode);
if (retval != ERROR_OK)
goto done;
}