📄 mn10300_stub.c
字号:
/* mn10300_stub.c - helper functions for mn10300 stub. * * Copyright (c) 1998,1999 Cygnus Solutions * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. */#include <stddef.h>#include <pkgconf/hal.h>#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS#include <cyg/hal/hal_stub.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_intr.h>#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT#include <cyg/hal/dbg-threads-api.h> // dbg_currthread_id#endif/* Given a trap value TRAP, return the corresponding signal. */int __computeSignal (unsigned int trap_number){ return SIGTRAP;}/* Return the trap number corresponding to the last-taken trap. */int __get_trap_number (void){ // The vector is not not part of the GDB register set so get it // directly from the save context. return _hal_registers->vector;}/* Set the currently-saved pc register value to PC. This also updates NPC as needed. */void set_pc (target_register_t pc){ put_register (PC, pc);}/*---------------------------------------------------------------------- * Single-step support. Lifted from CygMon. */#define NUM_SS_BPTS 2static target_register_t break_mem [NUM_SS_BPTS] = {0, 0};static unsigned char break_mem_data [NUM_SS_BPTS];/* Set a single-step breakpoint at ADDR. Up to two such breakpoints can be set; WHICH specifies which one to set (0 or 1). */static voidset_single_bp (int which, unsigned char *addr){ if (0 == break_mem[which]) { break_mem[which] = (target_register_t) addr; break_mem_data[which] = *addr; *addr = HAL_BREAKINST; }}/* Clear any single-step breakpoint(s) that may have been set. */void __clear_single_step (void){ int x; for (x = 0; x < NUM_SS_BPTS; x++) { unsigned char* addr = (unsigned char*) break_mem[x]; if (addr) { *addr = break_mem_data[x]; break_mem[x] = 0; } }}/* Read a 16-bit displacement from address 'p'. The value is stored little-endian. */static shortread_disp16(unsigned char *p){ return (short)(p[0] | (p[1] << 8));}/* Read a 32-bit displacement from address 'p'. The value is stored little-endian. */static intread_disp32(unsigned char *p){ return (int)(p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));}/* Get the contents of An register. */static unsigned intget_areg (int n){ switch (n) { case 0: return get_register (A0); case 1: return get_register (A1); case 2: return get_register (A2); case 3: return get_register (A3); } return 0;}/* Table of instruction sizes, indexed by first byte of instruction, used to determine the address of the next instruction for single stepping. If an entry is zero, special code must handle the case (for example, branches or multi-byte opcodes). */static char opcode_size[256] ={ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ /*------------------------------------------------*//* 0 */ 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3,/* 1 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 2 */ 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3,/* 3 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1,/* 4 */ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2,/* 5 */ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,/* 6 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 7 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 8 */ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2,/* 9 */ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2,/* a */ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2,/* b */ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2,/* c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2,/* d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* e */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* f */ 0, 2, 2, 2, 2, 2, 2, 1, 0, 3, 0, 4, 0, 6, 7, 1};/* Set breakpoint(s) to simulate a single step from the current PC. */void __single_step (void){ unsigned char *pc = (unsigned char *) get_register (PC); unsigned int opcode; int displ; opcode = *pc; /* Check the table for the simple cases. */ displ = opcode_size[opcode]; if (displ != 0) { set_single_bp (0, pc + displ); return; } /* Handle the more complicated cases. */ switch (opcode) { case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: /* * bxx (d8,PC) */ displ = *((signed char *)pc + 1); set_single_bp (0, pc + 2); if (displ < 0 || displ > 2) set_single_bp (1, pc + displ); break; case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: case 0xd8: case 0xd9: case 0xda: /* * lxx (d8,PC) */ if (pc != (unsigned char*) get_register (LAR)) set_single_bp (0, (unsigned char *) get_register (LAR)); set_single_bp (1, pc + 1); break; case 0xdb: /* * setlb requires special attention. It loads the next four instruction * bytes into the LIR register, so we can't insert a breakpoint in any * of those locations. */ set_single_bp (0, pc + 5); break; case 0xcc: case 0xcd: /* * jmp (d16,PC) or call (d16,PC) */ displ = read_disp16((char *)(pc + 1)); set_single_bp (0, pc + displ); break; case 0xdc: case 0xdd: /* * jmp (d32,PC) or call (d32,PC) */ displ = read_disp32((char *)(pc + 1)); set_single_bp (0, pc + displ); break; case 0xde: /* * retf */ set_single_bp (0, (unsigned char *) get_register (MDR)); break; case 0xdf: /* * ret */ displ = *((char *)pc + 2); set_single_bp (0, (unsigned char *) read_disp32 ((unsigned char *) get_register (SP) + displ)); break; case 0xf0: /* * Some branching 2-byte instructions. */ opcode = *(pc + 1); if (opcode >= 0xf0 && opcode <= 0xf7) { /* jmp (An) / calls (An) */ set_single_bp (0, (unsigned char *) get_areg (opcode & 3)); } else if (opcode == 0xfc) { /* rets */ set_single_bp (0, (unsigned char *) read_disp32 ((unsigned char *) get_register (SP))); } else if (opcode == 0xfd) { /* rti */ set_single_bp (0, (unsigned char *) read_disp32 ((unsigned char *) get_register (SP) + 4)); } else set_single_bp (0, pc + 2); break; case 0xf8: /* * Some branching 3-byte instructions. */ opcode = *(pc + 1); if (opcode >= 0xe8 && opcode <= 0xeb) { displ = *((signed char *)pc + 2); set_single_bp (0, pc + 3); if (displ < 0 || displ > 3) set_single_bp (1, pc + displ); } else set_single_bp (0, pc + 3); break; case 0xfa: opcode = *(pc + 1); if (opcode == 0xff) { /* calls (d16,PC) */ displ = read_disp16((char *)(pc + 2)); set_single_bp (0, pc + displ); } else set_single_bp (0, pc + 4); break; case 0xfc: opcode = *(pc + 1); if (opcode == 0xff) { /* calls (d32,PC) */ displ = read_disp32((char *)(pc + 2)); set_single_bp (0, pc + displ); } else set_single_bp (0, pc + 6); break; }}void __install_breakpoints (void){ /* NOP since single-step HW exceptions are used instead of breakpoints. */}void __clear_breakpoints (void) {}/* If the breakpoint we hit is in the breakpoint() instruction, return a non-zero value. */int__is_breakpoint_function (){ return get_register (PC) == (target_register_t)&CYG_LABEL_NAME(breakinst);}/* Skip the current instruction. */void __skipinst (void){ unsigned char *pc = (char *) get_register (PC); switch (*pc) { case 0xff: // breakpoint instruction pc++; break; case 0xf0: // Assume syscall trap (0xf0, 0x20) pc += 2; break; default: pc++; // Assume all other instructions break; // are one byte } put_register (PC, (target_register_t) pc);}#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -