📄 mips-stub.c
字号:
/* mips-stub.c - helper functions for stub, generic to all MIPS processors * * 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>#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS#include <cyg/hal/mips-regs.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/mips_opcode.h>/* Given a trap value TRAP, return the corresponding signal. */int __computeSignal (unsigned int trap_number){ switch (trap_number) { case EXC_INT: /* External interrupt */ return SIGINT; case EXC_RI: /* Reserved instruction */ case EXC_CPU: /* Coprocessor unusable */ return SIGILL; case EXC_BP: /* Break point */ return SIGTRAP; case EXC_OVF: /* Arithmetic overflow */ case EXC_TRAP: /* Trap exception */ case EXC_FPE: /* Floating Point Exception */ return SIGFPE; case EXC_IBE: /* Bus error (Ifetch) */ case EXC_DBE: /* Bus error (data load or store) */ return SIGBUS; case EXC_MOD: /* TLB modification exception */ case EXC_TLBL: /* TLB miss (Load or Ifetch) */ case EXC_TLBS: /* TLB miss (Store) */ case EXC_ADEL: /* Address error (Load or Ifetch) */ case EXC_ADES: /* Address error (Store) */ return SIGSEGV; case EXC_SYS: /* System call */ return SIGSYS; default: return SIGTERM; }}/* Return the trap number corresponding to the last-taken trap. */int __get_trap_number (void){ return (get_register (CAUSE) & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT;}/* 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 *//* Saved instruction data for single step support. */typedef unsigned long t_inst;static struct{ t_inst *targetAddr; t_inst savedInstr;} instrBuffer;/* Set things up so that the next user resume will execute one instruction. This may be done by setting breakpoints or setting a single step flag in the saved user registers, for example. */void __single_step (void){ InstFmt inst; t_inst *pc = (t_inst *) get_register (PC); instrBuffer.targetAddr = pc + 1; /* set default */ inst.word = *pc; /* read the next instruction *///diag_printf("pc %08x %08x\n",pc,inst.word); switch (inst.RType.op) { /* override default if branch */ case OP_SPECIAL: switch (inst.RType.func) { case OP_JR: case OP_JALR: instrBuffer.targetAddr = (t_inst *) get_register (inst.RType.rs); break; }; break; case OP_REGIMM: switch (inst.IType.rt) { case OP_BLTZ: case OP_BLTZL: case OP_BLTZAL: case OP_BLTZALL: if (get_register (inst.IType.rs) < 0 ) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); else instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); break; case OP_BGEZ: case OP_BGEZL: case OP_BGEZAL: case OP_BGEZALL: if (get_register (inst.IType.rs) >= 0 ) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); else instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); break; }; break; case OP_J: case OP_JAL: instrBuffer.targetAddr = (t_inst *)((inst.JType.target<<2) + ((get_register (PC) + 4)&0xf0000000)); break; case OP_BEQ: case OP_BEQL: if (get_register (inst.IType.rs) == get_register (inst.IType.rt)) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); else instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); break; case OP_BNE: case OP_BNEL: if (get_register (inst.IType.rs) != get_register (inst.IType.rt)) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); else instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); break; case OP_BLEZ: case OP_BLEZL: if (get_register (inst.IType.rs) <= 0) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); else instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); break; case OP_BGTZ: case OP_BGTZL: if (get_register (inst.IType.rs) > 0) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); else instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); break;#if 0 /* no floating point support at the moment */ case OP_COP1: if (inst.RType.rs == OP_BC) switch (inst.RType.rt) { case COPz_BCF: case COPz_BCFL: if (get_register (FCSR) & CSR_C) instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); else instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); break; case COPz_BCT: case COPz_BCTL: if (get_register (FCSR) & CSR_C) instrBuffer.targetAddr = (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); else instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); break; }; break;#endif }}/* Clear the single-step state. */void __clear_single_step (void){//diag_printf("clear_ss ta %08x\n",instrBuffer.targetAddr); if (instrBuffer.targetAddr != NULL) { *instrBuffer.targetAddr = instrBuffer.savedInstr; instrBuffer.targetAddr = NULL; } instrBuffer.savedInstr = NOP_INSTR;}void __install_breakpoints (){//diag_printf("install_bpt ta %08x\n",instrBuffer.targetAddr); if (instrBuffer.targetAddr != NULL) { instrBuffer.savedInstr = *instrBuffer.targetAddr; *instrBuffer.targetAddr = __break_opcode ();//diag_printf("ta %08x si %08x *ta %08x\n",// instrBuffer.targetAddr,instrBuffer.savedInstr,*instrBuffer.targetAddr); }}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. Since this is only called by the stub when the PC points to a breakpoint or trap instruction, we can safely just skip 4. */void __skipinst (void){ put_register (PC, get_register (PC) + 4);}#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -