summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AT91SAM7S256/Debugger/debug_stub.S80
-rw-r--r--AT91SAM7S256/Debugger/debug_stub.h15
-rw-r--r--AT91SAM7S256/Debugger/undef_handler.S71
3 files changed, 146 insertions, 20 deletions
diff --git a/AT91SAM7S256/Debugger/debug_stub.S b/AT91SAM7S256/Debugger/debug_stub.S
index 34bda59..98bc968 100644
--- a/AT91SAM7S256/Debugger/debug_stub.S
+++ b/AT91SAM7S256/Debugger/debug_stub.S
@@ -440,20 +440,42 @@ _dbg__flush_icache:
bx lr
- .global dbg__bkpt_handler
-/* dbg__bkpt_handler
- * GDB handle_exception() routine
+ .global dbg__thumb_bkpt_handler
+/* dbg__thumb_bkpt_handler
+ * GDB handle_exception() routine (Thumb Mode)
*/
-dbg__bkpt_handler:
+dbg__thumb_bkpt_handler:
+/* On entry, r0 contains breakpoint index value */
+ mov r4, #BKPT16_AUTO_BKPT
+ and r4, r0, #BKPT16_AUTO_BKPT /* keep AUTO flag value in r4 */
+ bic r0, r0, #BKPT16_AUTO_BKPT /* mask out AUTO flag */
+ _dbg_setcurrbkpt_index r0 /* keep current breakpoint index in memory */
+ ldr r1, =BKPT16_MANUAL_BKPT
+ teq r0, r1
+ beq _process_manual_breakpoint_thumb
+ ldr r1, =__breakpoints_num__
+ cmp r0, r1 /* Sanity check that index is in range */
+ bhs dbg__bkpt_offset_outofrange
+/* Valid index value found */
+ teq r4, #0 /* Check if AUTO flag set */
+ bne _process_auto_breakpoint
+/* else */
+ _dbg_setstate DBG_NORMAL_BKPT_THUMB
+ b _process_normal_breakpoint
+
+ .global dbg__arm_bkpt_handler
+/* dbg__arm_bkpt_handler
+ * GDB handle_exception() routine (ARM Mode)
+ */
+dbg__arm_bkpt_handler:
/* On entry, r0 contains breakpoint index value */
-/* FIXME: Currently we only deal with ARM mode, Thumb mode checks are missing! */
mov r4, #BKPT32_AUTO_BKPT
and r4, r0, #BKPT32_AUTO_BKPT /* keep AUTO flag value in r4 */
bic r0, r0, #BKPT32_AUTO_BKPT /* mask out AUTO flag */
_dbg_setcurrbkpt_index r0 /* keep current breakpoint index in memory */
ldr r1, =BKPT32_MANUAL_BKPT
teq r0, r1
- beq _process_manual_breakpoint
+ beq _process_manual_breakpoint_arm
ldr r1, =__breakpoints_num__
cmp r0, r1 /* Sanity check that index is in range */
bhs dbg__bkpt_offset_outofrange
@@ -461,11 +483,14 @@ dbg__bkpt_handler:
teq r4, #0 /* Check if AUTO flag set */
bne _process_auto_breakpoint
/* else */
+ _dbg_setstate DBG_NORMAL_BKPT_ARM
+/* b _process_normal_breakpoint */
+
+_process_normal_breakpoint:
bl _dbg__restore_breakpoints
bl _dbg__restore_singlestep
bl _dbg__clear_singlestep
bl _dbg__flush_icache
- _dbg_setstate DBG_NORMAL_BKPT_ARM
b dbg__bkpt_waitCMD
_process_auto_breakpoint:
@@ -479,7 +504,11 @@ _process_auto_breakpoint:
bl _dbg__clear_singlestep
b __dbg__resume_execution
-_process_manual_breakpoint:
+_process_manual_breakpoint_thumb:
+ _dbg_setstate DBG_MANUAL_BKPT_THUMB
+ b dbg__bkpt_waitCMD
+
+_process_manual_breakpoint_arm:
_dbg_setstate DBG_MANUAL_BKPT_ARM
/* b dbg__bkpt_waitCMD */
@@ -644,10 +673,13 @@ _dbg__procGetRegs:
* NOP Command Handler (placeholder)
* On entry:
* r0: parameter buffer (contents after '$' and '<cmdchar>')
- * r1: output message buffer
*/
_dbg__nop:
- bx lr /* Dummy, just return */
+ stmfd sp!, {lr}
+ mov r0, #MSG_ERRIMPL /* Stub, not implemented yet */
+ _dbg_outputMsgStatusErr
+ bl dbg__putDebugMsg /* Send error response to the GDB server */
+ ldmfd sp!, {pc}
/* dbg__cmd_install_breakpoint
@@ -1188,18 +1220,28 @@ void __single_step (void)
* the next instruction address (for inserting a Breakpoint).
*/
_dbg_next_instruction_addr:
-/* FIXME: Currently we only deal with ARM mode, Thumb mode checks are missing! */
/* We assume that any BKPT instructions in the code will be Manual Breakpoints,
* i.e., the Debugger does not leave stray Single Step / Auto / Normal breakpoints in memory
*/
- _dbg_getabortedinstr_addr r2 /* Retrieve aborted instruction address */
-1: ldr r0, [r2] /* Read actual instruction from memory */
- ldr r1, =(BKPT32_INSTR | BKPT32_MANUAL_BKPT) /* check for ARM Manual Breakpoint Instruction */
- teq r0, r1
- bne 2f /* Not Manual breakpoint */
- add r2, r2, #4 /* Is Manual Breakpoint, Skip to next ARM instruction */
- _dbg_setabortedinstr_addr r2 /* Update aborted instruction address */
- b 1b /* To protect against a sequence of Manual Breakpoint Instructions */
+
+ mov r2, #DBGSTACK_USERCPSR_INDEX /* Retrieve User CPSR */
+ _index2dbgstackaddr r2, r0 /* Calculate address pointer to relevant register, result in R0 */
+ ldr r0, [r0] /* Retrieve Register contents into R0 */
+ and r4, r0, #CPSR_THUMB /* store Thumb Mode status in R4 */
+
+ _dbg_getabortedinstr_addr r2 /* Retrieve aborted instruction address */
+1: teq r4, #0 /* Check if it is ARM or Thumb instruction */
+ ldrneh r0, [r2]
+ ldrne r1, =(BKPT16_INSTR | BKPT16_MANUAL_BKPT) /* check for Thumb Manual Breakpoint Instruction */
+ ldreq r0, [r2]
+ ldreq r1, =(BKPT32_INSTR | BKPT32_MANUAL_BKPT) /* check for ARM Manual Breakpoint Instruction */
+ teq r0, r1
+ bne 2f /* Not Manual breakpoint */
+ teq r4, #0 /* Check if it is ARM or Thumb instruction */
+ addne r2, r2, #2 /* Is Manual Breakpoint, Skip to next Thumb instruction */
+ addeq r2, r2, #4 /* Is Manual Breakpoint, Skip to next ARM instruction */
+ _dbg_setabortedinstr_addr r2 /* Update aborted instruction address */
+ b 1b /* To protect against a sequence of Manual Breakpoint Instructions */
/* Here, r0 contains the instruction which will be reexecuted when program resumes. We need to dissect it to see if
* it is a branch instruction.
diff --git a/AT91SAM7S256/Debugger/debug_stub.h b/AT91SAM7S256/Debugger/debug_stub.h
index 9a120e5..7849d56 100644
--- a/AT91SAM7S256/Debugger/debug_stub.h
+++ b/AT91SAM7S256/Debugger/debug_stub.h
@@ -39,6 +39,7 @@
#define MSGBUF_ERRCHAR 'E'
#define MSGBUF_SIGCHAR 'S'
#define MSGBUF_CPSRREG '!'
+#define MSGBUF_SETCHAR '='
#define MSGBUF_CMDINDEX_OUTOFRANGE_VAL -1
/*@}*/
@@ -75,6 +76,17 @@
#define HLFWRD1 0xFFFF0000 /* Halfword 0 word(31:16) */
/*@}*/
+/** @name CPSR Bit Definitions.
+ *
+ * Various Bit definitions for accessing the CPSR register.
+ */
+/*@{*/
+#define CPSR_THUMB 0x00000020
+#define CPSR_FIQ 0x00000040
+#define CPSR_IRQ 0x00000080
+
+/*@}*/
+
/** @name BKPT suppport constants
*
* ARM and Thumb Breakpoint Instructions.
@@ -111,7 +123,8 @@ ENUM_END(dbg_state_t)
* The enums must be consecutive, starting from 1
*/
ENUM_BEGIN
-ENUM_VALASSIGN(MSG_ERRCHKSUM, 1) /**< Checksum Error. */
+ENUM_VALASSIGN(MSG_ERRIMPL, 0) /**< Stub (not implemented) Error. */
+ENUM_VAL(MSG_ERRCHKSUM) /**< Checksum Error. */
ENUM_VAL(MSG_ERRFORMAT) /**< Message Format Error. */
ENUM_VAL(MSG_UNKNOWNCMD) /**< Unrecognized Command Error. */
ENUM_VAL(MSG_UNKNOWNPARAM) /**< Unrecognized Parameter Error. */
diff --git a/AT91SAM7S256/Debugger/undef_handler.S b/AT91SAM7S256/Debugger/undef_handler.S
new file mode 100644
index 0000000..c160179
--- /dev/null
+++ b/AT91SAM7S256/Debugger/undef_handler.S
@@ -0,0 +1,71 @@
+
+/* Copyright (C) 2007-2010 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"
+
+#define MODE_SVC 0x13 /* Supervisor mode. */
+
+.text
+.code 32
+.align 0
+
+ .extern dbg__thumb_bkpt_handler
+ .extern dbg__arm_bkpt_handler
+
+ .global undef_handler
+
+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.)
+ */
+ /* We assume that the UNDEF stack has been setup previously
+ On entry, LR_undef points to one instruction past the UNDEF instruction
+ */
+ ldr sp, =__debugger_stack__
+ stmfd sp, {r0-r15}^ /* Save workspace, user mode's pc via 'S' flag */
+ sub sp, sp, #(4*16) /* Need to manually update SP(undef) */
+ mrs r1, spsr /* Copy SPSR to r0 */
+ 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 */
+ tst r1, #CPSR_THUMB /* Check for Thumb Mode */
+ beq _is_arm /* Clear, so it's ARM mode */
+_is_thumb:
+ ldrh r0, [r0] /* load UNDEF instruction into r0 */
+ ldr r1, =BKPT16_ENUM_MASK /* Thumb BKPT enum mask */
+ bic r2, r0, r1 /* leave only opcode */
+ ldr r1, =BKPT16_INSTR /* check for Thumb Breakpoint Instruction */
+ 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) */
+_is_arm:
+ ldr r0, [r0] /* load UNDEF instruction into r0 */
+ ldr r1, =BKPT32_ENUM_MASK /* ARM BKPT enum mask */
+ bic r2, r0, r1 /* leave only opcode */
+ ldr r1, =BKPT32_INSTR /* check for ARM Breakpoint Instruction */
+ teq r2, r1
+ bne default_undef_handler
+ ldr r1, =BKPT32_ENUM_MASK /* get ARM BKPT Enum Mask */
+ and r0, r1, r0 /* Keep index value */
+ msr cpsr_c, #(MODE_SVC) /* Configure Supervisor Mode */
+ ldr lr, =dbg__arm_bkpt_handler /* handle BKPT, BKPT index in r0 */
+ mov pc, lr /* Invoke Debugger State (Supervisor Mode) */
+
+
+default_undef_handler:
+ b default_undef_handler /* Infinite loop */