From 6f8cf930bc015037e2ad4260c7d360d563644329 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Wed, 29 Jun 2016 15:39:11 +0200 Subject: Fix resume when core state has been modified Sometimes it is necessary to resume into a different state (ARM/Thumb) than at debug state entry. According to the documentation this should be possible with "arm core_state arm|thumb" before the resume command, however the original code also restores the original CPSR, which overrides whatever state the core was set to. This seems to work on some cores (e.g. Cortex-A5) but not on others (e.g. Cortex-A9). Using the "BX" instruction to set resume PC and core state works on Cortex-A9 and ARM11, but is not sufficient on Cortex-A5, where an explicit write to the PC (MOV pc, r0) is required additionally. Change-Id: Ic03153b4b250fbb8cf6c75f8e329fb34829aa35f Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3386 Tested-by: jenkins Reviewed-by: Alexander Stein Reviewed-by: Andreas Fritiofson --- src/target/arm11.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'src/target/arm11.c') diff --git a/src/target/arm11.c b/src/target/arm11.c index 5f160739..cbe4d450 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -418,11 +418,33 @@ static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t a { void *value = arm11->arm.pc->value; - if (!current) - buf_set_u32(value, 0, 32, address); - else + /* use the current program counter */ + if (current) address = buf_get_u32(value, 0, 32); + /* Make sure that the gdb thumb fixup does not + * kill the return address + */ + switch (arm11->arm.core_state) { + case ARM_STATE_ARM: + address &= 0xFFFFFFFC; + break; + case ARM_STATE_THUMB: + /* When the return address is loaded into PC + * bit 0 must be 1 to stay in Thumb state + */ + address |= 0x1; + break; + + /* catch-all for JAZELLE and THUMB_EE */ + default: + break; + } + + buf_set_u32(value, 0, 32, address); + arm11->arm.pc->dirty = 1; + arm11->arm.pc->valid = 1; + return address; } -- cgit v1.2.3-18-g5258