summaryrefslogtreecommitdiff
path: root/AT91SAM7S256/armdebug
diff options
context:
space:
mode:
authorTC Wan2010-12-21 11:16:52 +0800
committerTC Wan2010-12-21 11:16:52 +0800
commit7eb731a862755755f0d6dc87d7b4c1357008c3d4 (patch)
treeafffc9e68b0a8fbec46fb0d890a5c383101729e6 /AT91SAM7S256/armdebug
parenta097bcca3e556df8d2c473016cf3734bb9defdb8 (diff)
parent29149e9487715209da4c574b4d3b1cfb7ea17b78 (diff)
Merge branch 'master' of ssh://svc.cs.usm.my/~/gitrepo-bare/armdebug
Diffstat (limited to 'AT91SAM7S256/armdebug')
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_stack.ld2
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_stub.S2
-rw-r--r--AT91SAM7S256/armdebug/Debugger/debug_stub.h15
-rw-r--r--AT91SAM7S256/armdebug/Debugger/undef_handler.S82
4 files changed, 70 insertions, 31 deletions
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_stack.ld b/AT91SAM7S256/armdebug/Debugger/debug_stack.ld
index df27512..8fc4cb7 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_stack.ld
+++ b/AT91SAM7S256/armdebug/Debugger/debug_stack.ld
@@ -2,7 +2,7 @@
/* debugger state */
__debugger_stack_bottom__ = . ;
- . += 0x48; /* 16 user mode registers + SPSR + BKPT Instr Addr */
+ . += 0x48; /* 16 previous mode registers + SPSR + UNDEF Next Instruction Address */
__debugger_stack__ = .;
__debugger_stack_top__ = . ;
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_stub.S b/AT91SAM7S256/armdebug/Debugger/debug_stub.S
index 1ca4099..8448a46 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_stub.S
+++ b/AT91SAM7S256/armdebug/Debugger/debug_stub.S
@@ -321,7 +321,7 @@ debug_armComplexCCTable:
* User Mode R01
* User Mode R00
* User Mode CPSR (UNDEF SPSR)
- * Bkpt Instr Addr __debugger_stack_bottom__
+ * UNDEF Next Instr Addr __debugger_stack_bottom__
* [Low Memory Address]
*
* Each Breakpoint State will initially be zeroed.
diff --git a/AT91SAM7S256/armdebug/Debugger/debug_stub.h b/AT91SAM7S256/armdebug/Debugger/debug_stub.h
index b090572..c3a71c4 100644
--- a/AT91SAM7S256/armdebug/Debugger/debug_stub.h
+++ b/AT91SAM7S256/armdebug/Debugger/debug_stub.h
@@ -91,6 +91,7 @@
#define CPSR_THUMB 0x00000020
#define CPSR_FIQ 0x00000040
#define CPSR_IRQ 0x00000080
+#define CPSR_MODE 0x0000001F
/*@}*/
@@ -167,8 +168,8 @@ FUNCDEF void dbg__bkpt_handler(void);
/** dbg_breakpoint_arm.
* Equivalent to GDB breakpoint() routine for ARM code
*/
-FUNCDEF void dbg_breakpoint_arm(void);
-inline void dbg_breakpoint_arm(void)
+/* FUNCDEF void dbg_breakpoint_arm(void); */
+static inline void dbg_breakpoint_arm(void)
{
asm volatile (".word %a0"
: /* Output (empty) */
@@ -179,9 +180,9 @@ inline void dbg_breakpoint_arm(void)
#if 0 /* Old asm definitions, in case gas does not recognize %a0 operand */
#ifdef __ARM6OR7__
-inline void dbg_breakpoint_arm(void) { asm volatile (".word 0xE727FF7F" /* (BKPT32_INSTR | BKPT32_MANUAL_BKPT) */ ); }
+static inline void dbg_breakpoint_arm(void) { asm volatile (".word 0xE727FF7F" /* (BKPT32_INSTR | BKPT32_MANUAL_BKPT) */ ); }
#else
-inline void dbg_breakpoint_arm(void) { asm volatile (".word 0xE127FF7F" /* (BKPT32_INSTR | BKPT32_MANUAL_BKPT) */ ); }
+static inline void dbg_breakpoint_arm(void) { asm volatile (".word 0xE127FF7F" /* (BKPT32_INSTR | BKPT32_MANUAL_BKPT) */ ); }
#endif
#endif
@@ -189,8 +190,8 @@ inline void dbg_breakpoint_arm(void) { asm volatile (".word 0xE127FF7F" /* (BKPT
/** dbg_breakpoint_thumb.
* Equivalent to GDB breakpoint() routine for Thumb code
*/
-FUNCDEF void dbg_breakpoint_thumb(void);
-inline void dbg_breakpoint_thumb(void)
+/* FUNCDEF void dbg_breakpoint_thumb(void); */
+static inline void dbg_breakpoint_thumb(void)
{
asm volatile (".hword %a0"
: /* Output (empty) */
@@ -200,7 +201,7 @@ inline void dbg_breakpoint_thumb(void)
#if 0 /* Old asm definitions, in case gas does not recognize %a0 operand */
-inline void dbg_breakpoint_thumb(void) { asm volatile (".hword 0xBE7F" /* (BKPT16_INSTR | BKPT16_MANUAL_BKPT) */); }
+static inline void dbg_breakpoint_thumb(void) { asm volatile (".hword 0xBE7F" /* (BKPT16_INSTR | BKPT16_MANUAL_BKPT) */); }
#endif
diff --git a/AT91SAM7S256/armdebug/Debugger/undef_handler.S b/AT91SAM7S256/armdebug/Debugger/undef_handler.S
index 34154f7..6923d4d 100644
--- a/AT91SAM7S256/armdebug/Debugger/undef_handler.S
+++ b/AT91SAM7S256/armdebug/Debugger/undef_handler.S
@@ -11,7 +11,13 @@
#define __ASSEMBLY__
#include "debug_stub.h"
-#define MODE_SVC 0x13 /* Supervisor mode. */
+#define MODE_USR 0x10 /* User mode */
+#define MODE_FIQ 0x11 /* FIQ mode */
+#define MODE_IRQ 0x12 /* IRQ mode */
+#define MODE_SVC 0x13 /* Supervisor mode */
+#define MODE_ABT 0x17 /* Abort mode */
+#define MODE_UND 0x1B /* Undefined mode */
+#define MODE_SYS 0x1F /* System mode */
.text
.code 32
@@ -25,25 +31,61 @@
undef_handler:
/* Remote GDB Debugger relies on BKPT instruction being trapped here
- In ARMv4t, it is an Illegal (Undefined) Instruction.
- On triggering, lr (R14) contains the previous mode's pc (R15).
- Based on example in Hohl, "ARM Assembly Language: Fundamentals and Techniques"
- Chapter 11, Example 11.1.
- Note: The handler is not AAPCS compliant (8 byte-alignment and stack, etc.)
+ * In ARMv4t, it is an Illegal (Undefined) Instruction.
+ * On triggering, lr (R14) contains the previous mode's pc (R15).
+ * Based on example in Hohl, "ARM Assembly Language: Fundamentals and Techniques"
+ * Chapter 11, Example 11.1.
+ * Note: The handler is not AAPCS compliant (8 byte-alignment and stack, etc.)
*/
- /* We assume that the UNDEF stack has been setup previously
- On entry, LR_undef points to one instruction past the UNDEF instruction
+ /* We assume that the UNDEF stack holds only one stack frame and we will overwrite it.
+ * On entry, LR_undef points to one instruction past the UNDEF instruction.
+ *
+ * For the purpose of Debugging, the stack frame should present the PC (R15) as the address
+ * of the instruction that triggered the Breakpoint. Hence we need to adjust R15
+ * to point to the address of the UNDEF instruction. This is what the JTAG debugger
+ * does. (In the ARM hardware, the PC would point to UNDEF+2 instruction address
+ * since it has a three stage pipeline).
+ *
+ * We will also store UNDEF LR (next instruction pointer) and UNDEF SPSR to the stack.
+ *
+ * For the handler, once the user registers have been stored in the debug stack, the
+ * registers will be used as follows:
+ *
+ * R0: UNDEF LR, then UNDEF instruction address, finally UNDEF instruction word / BKPT index
+ * R1: SPSR
+ * R2: Mode
+ * R3: Debug Stack Pointer (for Banked R13-R14 update)
*/
- ldr sp, =__debugger_stack__
- stmfd sp, {r0-r15}^ /* Save workspace, user mode's pc via 'S' flag, R15: placeholder */
- str lr, [sp, #-4] /* Keep User's Next Instr Pointer (in UNDEF SP) in user mode R15 */
- sub sp, sp, #(4*16) /* Need to manually update SP(undef) */
- mrs r1, spsr /* Copy SPSR to r0 */
+ ldr sp, =__debugger_stack__
+ stmfd sp, {r0-r15}^ /* Save workspace, previous mode's pc via 'S' flag, R13-R15: placeholders */
+ mov r3, sp /* Use R3 to write Banked R13-R14, and actual PC of UNDEF instruction */
+ sub sp, sp, #(4*16) /* Need to manually update SP(undef) */
+
+ mov r0, lr /* Keep Next Instruction address after UNDEF instruction in R0 */
+ mrs r1, spsr /* Copy SPSR to r1 */
+ stmfd sp!, {r0,r1} /* Save User's Next Instr Pointer (in UNDEF LR) and previous mode's CPSR to stack */
+
+ tst r1, #CPSR_THUMB /* Check for Thumb Mode */
+ subne r0, r0, #2 /* Is Thumb instruction, adjust PC for UNDEF instruction address */
+ subeq r0, r0, #4 /* Is ARM instruction, adjust PC for UNDEF instruction address */
+ str r0, [r3, #-4]! /* Save PC to stack (R15 slot) */
+
+ and r2, r1, #CPSR_MODE /* Get previous mode */
+ teq r2, #MODE_USR
+ beq _skip_banked_registers /* Can't switch back if we're in User mode! */
+
+_store_prev_mode_banked_regs:
+ /* FIXME: We don't handle FIQ properly! */
+
+ orr r2, #(CPSR_FIQ | CPSR_IRQ) /* Disable Interrupts */
+ msr cpsr_c, r2 /* Switch to previous mode */
+ stmfd r3!, {sp, lr} /* Store Previous Mode's LR (R14), SP (R13) via R3 */
+ msr cpsr_c, #(MODE_UND | CPSR_FIQ | CPSR_IRQ) /* Revert to Undef Mode */
+
+_skip_banked_registers:
tst r1, #CPSR_THUMB /* Check for Thumb Mode */
beq _is_arm /* Clear, so it's ARM mode */
_is_thumb:
- sub r0, lr, #2 /* LR points to instruction after UNDEF instruction */
- stmfd sp!, {r0,r1} /* Save UNDEF instruction addr and previous mode's CPSR to stack */
ldrh r0, [r0] /* load UNDEF instruction into r0 */
ldr r1, =BKPT16_ENUM_MASK /* Thumb BKPT enum mask */
bic r2, r0, r1 /* leave only opcode */
@@ -51,13 +93,8 @@ _is_thumb:
teq r2, r1
bne default_undef_handler
ldr r1, =BKPT16_ENUM_MASK /* get Thumb BKPT Enum Mask */
- and r0, r1, r0 /* Keep index value */
- msr cpsr_c, #(MODE_SVC) /* Configure Supervisor Mode */
- ldr lr, =dbg__thumb_bkpt_handler /* handle BKPT, BKPT index in r0 */
- mov pc, lr /* Invoke Debugger State (Supervisor Mode) */
+ b _exit_undef_handler
_is_arm:
- sub r0, lr, #4 /* LR points to instruction after UNDEF instruction */
- stmfd sp!, {r0,r1} /* Save UNDEF instruction addr and previous mode's CPSR to stack */
ldr r0, [r0] /* load UNDEF instruction into r0 */
ldr r1, =BKPT32_ENUM_MASK /* ARM BKPT enum mask */
bic r2, r0, r1 /* leave only opcode */
@@ -65,8 +102,9 @@ _is_arm:
teq r2, r1
bne default_undef_handler
ldr r1, =BKPT32_ENUM_MASK /* get ARM BKPT Enum Mask */
+_exit_undef_handler:
and r0, r1, r0 /* Keep index value */
- msr cpsr_c, #(MODE_SVC) /* Configure Supervisor Mode */
+ msr cpsr_c, #(MODE_ABT) /* Configure Abort Mode */
ldr lr, =dbg__arm_bkpt_handler /* handle BKPT, BKPT index in r0 */
mov pc, lr /* Invoke Debugger State (Supervisor Mode) */