/** @file debug_macros.h * @brief internal macros used by debug_stub routines * */ /* Copyright (C) 2007-2010 the NxOS developers * * Module Developed by: TC Wan * * See AUTHORS for a full list of the developers. * * See COPYING for redistribution license * */ #ifndef __DEBUG_MACROS_H__ #define __DEBUG_MACROS_H__ /*@{*/ /** _dbg_jumpTableHandler * Call Jump Table Routine based on Index * On entry: * @param jumptableaddr is the address (constant) of the Jump Table * @param jumpreg is the register used to perform the indirect jump * @param indexreg contains jump table index value */ .macro _dbg_jumpTableHandler jumptableaddr, jumpreg, indexreg ldr \jumpreg, =\jumptableaddr ldr \jumpreg, [\jumpreg, \indexreg, lsl #2] mov lr, pc bx \jumpreg /* Call Command Handler Routine */ .endm /** _dbg_thumbDecodeEntry * Load Thumb Instruction Decoder Entry * On entry: * @param instrreg is the register to load the instruction into * @param instrmask is the register to load the instruction mask into * @param codehandler is the register to load the code handling routine into * @param indexreg contains decode table index value * NOTE: instrreg, instrmask, codehandler must be in increasing register number order */ .macro _dbg_thumbDecodeEntry instrreg, instrmask, codehandler, indexreg ldr \instrmask, =debug_thumbDecodeTable /* Temporary register */ add \instrmask, \instrmask, \indexreg, lsl #3 ldm \instrmask, {\instrreg, \codehandler} /* LSHW: IID, MSHW: IBM */ mov \instrmask, \instrreg, lsr #16 mov \instrreg, \instrreg, lsl #16 mov \instrreg, \instrreg, lsr #16 /* Keep HLFWORD0 containing instruction */ .endm /** _dbg_armDecodeEntry * Load ARM Instruction Decoder Entry * On entry: * @param instrreg is the register to load the instruction into * @param instrmask is the register to load the instruction mask into * @param codehandler is the register to load the code handling routine into * @param indexreg contains decode table index value * NOTE: instrreg, instrmask, codehandler must be in increasing register number order */ .macro _dbg_armDecodeEntry instrreg, instrmask, codehandler, indexreg ldr \instrmask, =debug_armDecodeTable /* Temporary register */ add \instrmask, \instrmask, \indexreg, lsl #3 add \instrmask, \instrmask, \indexreg, lsl #2 /* 12 byte entries */ ldm \instrmask, {\instrreg, \instrmask, \codehandler} .endm /** _asciiz * Terminate string given string buffer pointer in \strptr * scratchreg is used as a scratch register (destroyed) * */ .macro _asciiz strptr, scratchreg mov \scratchreg, #0 /* ASCIIZ character */ strb \scratchreg, [\strptr] /* Terminate ASCII string */ .endm /** _dbg_stpcpy * _dbg_stpcpy macro * On entry: * deststrptr: Destination string * sourcestrptr: Source string * scratchreg: scratch register for copying * On exit: * deststrptr: Pointer to ASCIIZ character in destination string * sourcestrptr: Pointer to next character slot in source string (after ASCIIZ) * scratchreg: destroyed */ .macro _dbg_stpcpy deststrptr, sourcestrptr, scratchreg 1: ldrb \scratchreg, [\sourcestrptr], #1 strb \scratchreg, [\deststrptr], #1 teq \scratchreg, #0 bne 1b sub \deststrptr, \deststrptr, #1 /* Adjust Destination string pointer to point at ASCIIZ character */ .endm /** _dbg_memcpy * _dbg_stpcpy macro * On entry: * deststrptr: Destination string * sourcestrptr: Source string * sizereg: Number of bytes to copy * scratchreg: scratch register for copying * On exit: * deststrptr: Pointer to next character slot in destination string * sourcestrptr: Pointer to next character slot in source string * sizereg, scratchreg: destroyed */ .macro _dbg_memcpy deststrptr, sourcestrptr, sizereg, scratchreg 1: ldrb \scratchreg, [\sourcestrptr], #1 strb \scratchreg, [\deststrptr], #1 subs \sizereg, \sizereg, #1 bne 1b .endm /** _dbg_CopyMsg2OutputBuf * Copies source message to output buffer * On entry: * R2: source message buffer (ASCIIZ terminated) * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R2-R3: destroyed */ .macro _dbg_CopyMsg2OutputBuf ldr r0, =debug_OutMsgBuf _dbg_stpcpy r0, r2, r3 .endm /** _dbg_CopyMsg2OutputBuf_withParam * Internal Routine called to output message with parameters * Return Message with byte-sized parameter * On entry: * R1: byte-sized param * R2: source message buffer (ASCIIZ terminated) * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R1-R3: destroyed */ .macro _dbg_CopyMsg2OutputBuf_withParam _dbg_CopyMsg2OutputBuf /* R1 unchanged */ bl byte2ascii /* R0 points to buffer position after byte value */ _asciiz r0, r1 .endm /** _dbg_outputAckOnlyFlag * Return Flag ('+') for Continue or Step * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R2-R3: destroyed */ .macro _dbg_outputAckOnlyFlag ldr r2, =debug_AckOnlyFlag /* ASCIIZ terminated */ _dbg_CopyMsg2OutputBuf .endm /** _dbg_outputRetransmitFlag * Return Flag ('-') for Checksum Error (retransmission needed) * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R2-R3: destroyed */ .macro _dbg_outputRetransmitFlag ldr r2, =debug_RetransmitFlag /* ASCIIZ terminated */ _dbg_CopyMsg2OutputBuf .endm /** _dbg_outputMsgValidResponse * Return Message with valid response ('+$') * On exit: * R0: Pointer to Output Buffer next character slot location * R2-R3: destroyed */ .macro _dbg_outputMsgValidResponse ldr r2, =debug_ValidResponsePrefix _dbg_CopyMsg2OutputBuf .endm /** _dbg_outputMsgStatusOk * Return Message with Ok ('+$OK') status * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R2-R3: destroyed */ .macro _dbg_outputMsgStatusOk ldr r2, =debug_OkResponse /* ASCIIZ terminated */ _dbg_CopyMsg2OutputBuf .endm /** _dbg_outputMsgCurrTID * Return Message with Default Thread ID ('+$QC0') * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R2-R3: destroyed */ .macro _dbg_outputMsgCurrTID ldr r2, =debug_ThreadIDResponse /* ASCIIZ terminated */ _dbg_CopyMsg2OutputBuf .endm /** _dbg_outputMsgFirstThreadInfo * Return Message with Default Current Thread ID ('+$m0') * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R2-R3: destroyed */ .macro _dbg_outputMsgFirstThreadInfo ldr r2, =debug_FirstThreadInfoResponse /* ASCIIZ terminated */ _dbg_CopyMsg2OutputBuf .endm /** _dbg_outputMsgSubsequentThreadInfo * Return Message with Default Current Thread ID ('+$m0') * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R2-R3: destroyed */ .macro _dbg_outputMsgSubsequentThreadInfo ldr r2, =debug_SubsequentThreadInfoResponse /* ASCIIZ terminated */ _dbg_CopyMsg2OutputBuf .endm /** _dbg_outputMsgStatusErr * Return Message with Error ('+$ENN') status * On entry: * R1: error code * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R1-R3: destroyed */ .macro _dbg_outputMsgStatusErr ldr r2, =debug_ErrorResponsePrefix _dbg_CopyMsg2OutputBuf_withParam .endm /** _dbg_outputMsgStatusErrCode * Return Message with Error ('+$ENN') status * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R1-R3: destroyed */ .macro _dbg_outputMsgStatusErrCode errcode mov r1, #\errcode _dbg_outputMsgStatusErr .endm /** _dbg_outputMsgStatusSig * Return Message with Signal ('+$SNN') status * On entry: * R1: signal code * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R1-R3: destroyed */ .macro _dbg_outputMsgStatusSig ldr r2, =debug_SignalResponsePrefix _dbg_CopyMsg2OutputBuf_withParam .endm /** _dbg_outputMsgStatusSigCode * Return Message with Signal ('+$SNN') status * On exit: * R0: Pointer to Output Buffer ASCIIZ location * R1-R3: destroyed */ .macro _dbg_outputMsgStatusSigCode statuscode mov r1, #\statuscode _dbg_outputMsgStatusSig .endm /** _regenum2index * Convert register enum to debugger stack index * * On entry: * @param indexenum: enum representing Register to access * @param indexreg: register to be used to store the debugger stack index value (0-max index) * On exit: * @param indexreg contains debugger stack index value (0-max index) */ .macro _regenum2index indexenum, indexreg add \indexreg, \indexenum, #DBGSTACK_USERREG_INDEX /* Convert register index to Debug Stack index */ .endm /** _getdbgregisterfromindex * Retrieve register contents from debugger stack given index * * On entry: * @param indexreg contains debugger stack index value (0-max index) * On exit: * @param indexreg: Breakpoint index (preserved) * @param contentsreg: Register Contents for given index */ .macro _getdbgregisterfromindex indexreg, contentsreg ldr \contentsreg, =__debugger_stack_bottom__ ldr \contentsreg, [\contentsreg, \indexreg, lsl #2] .endm /** _setdbgregisterfromindex * Store register contents to debugger stack given index * * On entry: * @param indexreg contains debugger stack index value (0-max index) * @param contentsreg: Register Contents for given index * @param addressreg: Scratch register for address pointer * On exit: * @param indexreg: Breakpoint index (preserved) * @param contentsreg: Register Contents for given index */ .macro _setdbgregisterfromindex indexreg, contentsreg, addressreg ldr \addressreg, =__debugger_stack_bottom__ str \contentsreg, [\addressreg, \indexreg, lsl #2] .endm /** _getdbgregister * Retrieve register contents from debugger stack given immediate index value * * On entry: * @param indexval contains debugger stack index value (0-max index) * On exit: * @param contentsreg: Register Contents for given index */ .macro _getdbgregister indexval, contentsreg ldr \contentsreg, =__debugger_stack_bottom__ ldr \contentsreg, [\contentsreg, #(\indexval << 2)] .endm /** _setdbgregister * Store register contents to debugger stack given immediate index value * * On entry: * @param indexval contains debugger stack index value (0-max index) * @param contentsreg: Register Contents for given index * @param addressreg: Scratch register for address pointer * On exit: * @param contentsreg: Register Contents for given index * @param addressreg: Destroyed */ .macro _setdbgregister indexval, contentsreg, addressreg ldr \addressreg, =__debugger_stack_bottom__ str \contentsreg, [\addressreg, #(\indexval << 2)] .endm /** _index2bkptindex_addr * Convert Breakpoint index to breakpoing entry address * * On entry: * @param indexreg contains breakpoint index value * On exit: * @param indexreg: Breakpoint index (preserved) * @param addrreg: Breakpoint Entry Address */ .macro _index2bkptindex_addr indexreg, addrreg ldr \addrreg, =__breakpoints_start__ add \addrreg, \addrreg, \indexreg, lsl #3 /* Calculate Breakpoint Entry Address */ .endm /** _dbg_getstate * Get Debugger State * On exit: * @param reg: Debugger State enum */ .macro _dbg_getstate reg ldr \reg, =debug_state ldrb \reg, [\reg] .endm /** _dbg_setstate * Set Debugger State to given value * On exit: * r0, r1: destroyed */ .macro _dbg_setstate state mov r0, #\state ldr r1, =debug_state strb r0, [r1] .endm /** _dbg_getmode * Get Debugger Mode * On exit: * @param reg: Debugger Mode (Boolean) */ .macro _dbg_getmode reg ldr \reg, =debug_mode ldrb \reg, [\reg] .endm /** _dbg_setmode * Set Debugger Mode to given value * On exit: * r0, r1: destroyed */ .macro _dbg_setmode mode mov r0, #\mode ldr r1, =debug_mode strb r0, [r1] .endm /** _dbg_get_bkpt_type * Get Breakpoint Type * On exit: * @param reg: Breakpoint Type */ .macro _dbg_get_bkpt_type reg ldr \reg, =debug_bkpt_type ldrb \reg, [\reg] .endm /** _dbg_set_bkpt_type * Set Breakpoint Type using value in reg * On exit: * @param reg: destroyed * r1: destroyed */ .macro _dbg_set_bkpt_type reg ldr r1, =debug_bkpt_type strb \reg, [r1] .endm /** _dbg_set_bkpt_type_val * Set Breakpoint Type to given value * On exit: * r0, r1: destroyed */ .macro _dbg_set_bkpt_type_val bkpt_type mov r0, #\bkpt_type ldr r1, =debug_bkpt_type strb r0, [r1] .endm /** _dbg_getcurrbkpt_index * Get current breakpoint index * On exit: * @param reg: Breakpoint index */ .macro _dbg_getcurrbkpt_index reg ldr \reg, =debug_curr_breakpoint ldrb \reg, [\reg] .endm /** _dbg_setcurrbkpt_index * Set current breakpoint index * On exit: * r1: destroyed */ .macro _dbg_setcurrbkpt_index reg ldr r1, =debug_curr_breakpoint strb \reg, [r1] .endm /*@}*/ #endif /* __DEBUG_MACROS_H__ */