aboutsummaryrefslogtreecommitdiff
path: root/AT91SAM7S256/armdebug/Debugger/abort_handler.S
diff options
context:
space:
mode:
authorTat-Chee Wan2012-02-03 23:57:04 +0100
committerNicolas Schodet2012-02-11 17:30:42 +0100
commitd50dd5ab9567cc308e412c5e9e775dc8e15fb509 (patch)
treeb7d30c1025fb34e65a04d15701c53ee2ca071dec /AT91SAM7S256/armdebug/Debugger/abort_handler.S
parentceb0cbf65a11aed7662eb41ae66157e60ff61d60 (diff)
merge armdebug rc1
This enables the use of GDB or GDB based debuggers to debug the code running on the NXT brick using the USB connection.
Diffstat (limited to 'AT91SAM7S256/armdebug/Debugger/abort_handler.S')
-rw-r--r--AT91SAM7S256/armdebug/Debugger/abort_handler.S108
1 files changed, 108 insertions, 0 deletions
diff --git a/AT91SAM7S256/armdebug/Debugger/abort_handler.S b/AT91SAM7S256/armdebug/Debugger/abort_handler.S
new file mode 100644
index 0000000..f4d1bd0
--- /dev/null
+++ b/AT91SAM7S256/armdebug/Debugger/abort_handler.S
@@ -0,0 +1,108 @@
+
+/* Copyright (C) 2007-2011 the NxOS developers
+ *
+ * Module Developed by: TC Wan <tcwan@cs.usm.my>
+ *
+ * See AUTHORS for a full list of the developers.
+ *
+ * Redistribution of this file is permitted under
+ * the terms of the GNU Public License (GPL) version 2.
+ */
+#define __ASSEMBLY__
+#include "debug_stub.h"
+#include "debug_internals.h"
+
+#define PREFETCH_OFFSET 4
+#define DATA_OFFSET 8
+
+/* Trap Abort Exceptions.
+ * 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: This routine closely mirrors the undef_handler routine, since we will store
+ * the ABORT stack frame in the UNDEF stack.
+ * In addition, since ARMDEBUG uses Abort mode, if the ABORT occurs while the
+ * debugger is running, the value of SP_abort is not valid. This should not happen
+ * in any case (it is a BUG if ARMDEBUG triggers an ABORT).
+ *
+ * We assume that the DEBUG stack holds only one stack frame and we will overwrite it.
+ * On entry, LR_undef contains the PC+4 for Prefetch Abort, and PC+8 for Data Abort.
+ *
+ * For the purpose of Debugging, the stack frame should present the PC (R15) as the address
+ * of the instruction that triggered the Abort. Hence we need to adjust R15
+ * to point to the address of the ABORTed instruction.
+ *
+ * We will also store ABORT LR (next instruction pointer) and ABORT 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: ABORT LR, then ABORT instruction address
+ * R1: SPSR
+ * R2: PC Offset, then Mode
+ * R3: DEBUG Stack Pointer (for Banked R13-R14 update)
+ * R4: Abort Type Enum
+ */
+
+.text
+.code 32
+.align 0
+
+ .extern dbg__display_abort_info
+ .extern dbg__abort_exception_handler
+ .extern default_prefetch_abort_handler
+ .extern default_data_abort_handler
+
+ .global prefetch_abort_handler
+ .global data_abort_handler
+
+prefetch_abort_handler:
+ ldr sp, =__debugger_stack__
+ stmfd sp, {r0-r15}^ /* Save workspace, previous mode's pc via 'S' flag, R13-R15: placeholders */
+ mov r2, #PREFETCH_OFFSET
+ mov r4, #DISP_ABORT_PREFETCH /* Display Abort Info Type */
+ mov r5, #DBG_ABORT_PREFETCH /* Debugger Abort Type */
+ b _common_abort_handler
+
+data_abort_handler:
+ ldr sp, =__debugger_stack__
+ stmfd sp, {r0-r15}^ /* Save workspace, previous mode's pc via 'S' flag, R13-R15: placeholders */
+ mov r2, #DATA_OFFSET
+ mov r4, #DISP_ABORT_DATA /* Display Abort Info Type */
+ mov r5, #DBG_ABORT_DATA /* Debugger Abort Type */
+
+_common_abort_handler:
+ sub r0, lr, r2 /* R0: Adjust PC to ABORTed instruction address */
+ str r0, [sp, #-4] /* Save ABORTed Instruction PC to stack (R15 slot) */
+ sub r3, sp, #4 /* Use R3 to write Banked R13-R14 of ABORT instruction, update R3 to point to R14 slot */
+
+ mrs r1, spsr /* Copy SPSR to r1 */
+ tst r1, #CPSR_THUMB /* Check for Thumb Mode */
+ addne r0, r0, #2 /* Is Thumb instruction, adjust PC for ABORT next instruction address */
+ addeq r0, r0, #4 /* Is ARM instruction, adjust PC for ABORT next instruction address */
+ sub sp, sp, #(4*16) /* Need to manually update SP(abort) */
+ stmfd sp!, {r0,r1} /* Save ABORTed Next Instr Pointer (in R0) and previous mode's CPSR to stack */
+
+ and r2, r1, #CPSR_MODE /* Get previous mode */
+ teq r2, #MODE_USR
+ beq _exit_abort_handler /* 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_ABT | CPSR_FIQ | CPSR_IRQ) /* Revert to ABORT Mode */
+
+_exit_abort_handler:
+ ldr sp, =__abort_stack__ /* Reinitialize stack pointer each time an Abort happens */
+ bic sp, sp, #7
+ mov r0, r4 /* Copy Display Abort Type Enum to R0 */
+ bl dbg__display_abort_info /* Display Abort Type to LCD */
+ mov r0, r5 /* Copy Debugger Abort Type Enum to R0 */
+ b dbg__abort_exception_handler /* Invoke Debugger */
+
+