📄 dbgarmlib.c
字号:
/* dbgArmLib.c - ARM-specific debug routines for dbg and wdb *//* Copyright 1996-1998 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01h,24may01,h_k fixed reloc to INT32 from UINT32 for BL in Thumb01g,23may01,h_k fixed sign extention for BL in Thumb01f,04sep98,cdp make Thumb support dependent on ARM_THUMB.01e,27oct97,kkk took out "***EOF***" line from end of file.01d,23oct97,cdp make thumbGetNpc() return bit zero clear for all opcodes.01c,08oct97,cdp thumbInstrChangesPc(): clear bit zero of PC before fetching instruction; return false for second half of BL; make thumbGetNpc() return rn when PC is at BL _call_via_rn.01b,15apr97,cdp added Thumb (ARM7TDMI_T) support.01a,08aug96,cdp created by splitting wdbArchLib.c*//*DESCRIPTIONThis module contains some ARM-specific functions used by dbgArchLib.c,trcLib.c and wdbArchLib.c. They are in a separate file so that they can beexcluded from the image if neither dbg nor wdb is enabled. Putting them herealso saves having to maintain separate versions in parallel.*/#include "vxWorks.h"#include "regs.h"/* * check that this compiler does sign extension when an int is shifted right * because a lot of the code below relies on its doing so. */#if (((INT32)-1L) >> 1) > 0# error right shifting an int does not perform sign extension#endif#define BIT(n) ((UINT32)1U << (n))#define BITSET(x,n) (((UINT32)(x) & (1U<<(n))) >> (n))#define BITS(x,m,n) (((UINT32)((x) & (BIT(n) - BIT(m) + BIT(n)))) >> (m))/* externals */#if (ARM_THUMB)extern int _call_via_r0 (void);extern int _call_via_r1 (void);extern int _call_via_r2 (void);extern int _call_via_r3 (void);extern int _call_via_r4 (void);extern int _call_via_r5 (void);extern int _call_via_r6 (void);extern int _call_via_r7 (void);extern int _call_via_r8 (void);extern int _call_via_r9 (void);extern int _call_via_sl (void);extern int _call_via_fp (void);extern int _call_via_ip (void);extern int _call_via_lr (void);#endif/* locals */#if (ARM_THUMB)/* * call_via_tbl is used to determine whether a BL is to one of the call_via_rn * functions (we can't guarantee we have a symbol table in which we can * look up an address. */LOCAL FUNCPTR call_via_tbl[] = { _call_via_r0, _call_via_r1, _call_via_r2, _call_via_r3, _call_via_r4, _call_via_r5, _call_via_r6, _call_via_r7, _call_via_r8, _call_via_r9, _call_via_sl, _call_via_fp, _call_via_ip, _call_via_lr };#endif/* * ccTable is used to determine whether an instruction will be executed, * according to the flags in the PSR and the condition field of the * instruction. The table has an entry for each possible value of the * condition field of the instruction. Each bit indicates whether a particular * combination of flags will cause the instruction to be executed. Since * ther are four flags, this makes 16 possible TRUE/FALSE values. */LOCAL UINT32 ccTable[] = { 0xF0F0, 0x0F0F, 0xCCCC, 0x3333, 0xFF00, 0x00FF, 0xAAAA, 0x5555, 0x0C0C, 0xF3F3, 0xAA55, 0x55AA, 0x0A05, 0xF5FA, 0xFFFF, 0x0000 };#if (!ARM_THUMB)/********************************************************************************* armShiftedRegVal - calculate value of shifted register specified in opcode**/LOCAL UINT32 armShiftedRegVal ( REG_SET * pRegs, /* pointer to task registers */ UINT32 instr, /* machine instruction */ int cFlag /* value of carry flag */ ) { UINT32 res, shift, rm, rs, shiftType; rm = BITS(instr, 0, 3); shiftType = BITS(instr, 5, 6); if (BITSET(instr, 4)) { rs = BITS(instr, 8, 11); shift = (rs == 15 ? (UINT32)pRegs->pc + 8 : pRegs->r[rs]) & 0xFF; } else shift = BITS(instr, 7, 11); res = rm == 15 ? (UINT32)pRegs->pc + (BITSET(instr, 4) ? 12 : 8) : pRegs->r[rm]; switch (shiftType) { case 0: /* LSL */ res = shift >= 32 ? 0 : res << shift; break; case 1: /* LSR */ res = shift >= 32 ? 0 : res >> shift; break; case 2: /* ASR */ if (shift >= 32) shift = 31; res = (res & 0x80000000L) ? ~((~res) >> shift) : res >> shift; break; case 3: /* ROR */ shift &= 31; if (shift == 0) res = (res >> 1) | (cFlag ? 0x80000000L : 0); else res = (res >> shift) | (res << (32 - shift)); break; } return res; } /* armShiftedRegVal() */#endif#if (ARM_THUMB)/********************************************************************************* thumbGetNpc - get the address of the next instruction to be executed** RETURNS: address of the next instruction to be executed.** INTERNAL* This function must be passed the instruction rather than using the one* pointed to by pRegs->pc as the latter may have been replaced by a breakpoint* instruction.*/INSTR * thumbGetNpc ( INSTR instr, /* the current instruction */ REG_SET * pRegs /* pointer to task registers */ ) { UINT32 pc; /* current program counter */ UINT32 nPc; /* next program counter */ pc = (UINT32)pRegs->pc & ~1; /* current PC as a UINT32 */ nPc = pc + 2; /* Thumb default */ /* * Now examine the instruction * Following code is derived from the ARM symbolic debugger. */ switch (BITS(instr, 12, 15)) { case 0x0: case 0x1: case 0x2: case 0x3: case 0x5: case 0x6: case 0x7: case 0x8: case 0x9: case 0xA: case 0xC: /* no effect on PC - next instruction executes */ break; case 4: if (BITS(instr, 7, 11) == 0x0E) { /* BX */ int rn; rn = BITS(instr, 3, 6); nPc = rn == 15 ? pc + 4 : pRegs->r[rn]; break; } if (BITSET(instr, 7) && (BITS(instr, 0, 11) & 0xC07) == 0x407) { /* do something to pc */ int rn; UINT32 operand; rn = BITS(instr, 3, 6); operand = rn == 15 ? pc + 4 : pRegs->r[rn]; switch (BITS(instr, 8, 9)) { case 0: /* ADD */ nPc = pc + 4 + operand; break; case 1: /* CMP */ break; case 2: /* MOV */ nPc = operand; break; case 3: /* BX - already handled */ break; } } break; case 0xB: if (BITS(instr, 8, 11) == 0xD) { /* POP {rlist, pc} */ INT32 offset = 0; UINT32 regList, regBit; for (regList = BITS(instr, 0, 7); regList != 0; regList &= ~regBit) { regBit = regList & (-regList); offset += 4; } nPc = *(UINT32 *)(pRegs->r[13] + offset); /* don't check for new pc == pc like ARM debugger does */ } break; case 0xD: { /* SWI or conditional branch */ UINT32 cond; cond = (instr >> 8) & 0xF; if (cond == 0xF) break; /* SWI */ /* Conditional branch * Use the same mechanism as armGetNpc() to determine whether * the branch will be taken */ if (((ccTable[cond] >> (pRegs->cpsr >> 28)) & 1) == 0) break; /* instruction will not be executed */ /* branch will be taken */ nPc = pc + 4 + (((instr & 0x00FF) << 1) | (BITSET(instr, 7) ? 0xFFFFFE00 : 0)); } break; case 0xE: if (BITSET(instr, 11) == 0) /* Unconditional branch */ nPc = pc + 4 + (((instr & 0x07FF) << 1) | (BITSET(instr, 10) ? 0xFFFFF000 : 0)); break; case 0xF: /* BL */ if (BITSET(instr, 11)) { /* second half of BL - PC should never be here */ nPc = pRegs->r[14] + ((instr & 0x07FF) << 1); } else { /* first half of BL */ UINT32 nextBit; UINT i; INT32 reloc; nextBit = *(UINT16 *)(pc + 2); if ((nextBit & 0xF800) != 0xF800) /* Something strange going on */ break; reloc = (INT32)(((instr & 0x7FF) << 12) | ((nextBit & 0x7FF) << 1)); reloc = (reloc ^ 0x00400000) - 0x00400000; /* sign extend */ nPc = pc + 4 + reloc; /* * if it's a call to a call_via_rn function, make the * next PC the contents of the register being used * (otherwise the kernel will halt) */ for (i = 0; i < (sizeof(call_via_tbl) / sizeof(FUNCPTR)); ++i) if (nPc == ((UINT32)(call_via_tbl[i]) & ~1)) break; if (i < (sizeof(call_via_tbl) / sizeof(FUNCPTR))) /* address matches one of the call_via_rn functions */ nPc = pRegs->r[i]; } break; } /* switch */ return (INSTR *)((UINT32)nPc & ~1); } /* thumbGetNpc() */#else /* (ARM_THUMB) *//********************************************************************************* armGetNpc - get the address of the next instruction to be executed** RETURNS: address of the next instruction to be executed.** INTERNAL* This function must be passed the instruction rather than using the one* pointed to by pRegs->pc as the latter may have been replaced by a breakpoint* instruction.*/INSTR * armGetNpc ( INSTR instr, /* the current instruction */ REG_SET * pRegs /* pointer to task registers */ ) { UINT32 pc; /* current program counter */ UINT32 nPc; /* next program counter */ /* * Early versions of this file looked at the PSR to determine whether the * CPU was in ARM state or Thumb state and decode the next instruction * accordingly. This has been removed since there is to be no support for * ARM/Thumb interworking. */ pc = (UINT32)pRegs->pc; /* current PC as a UINT32 */ nPc = pc + 4; /* default */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -