1 //========================================================================
5 // OpenRISC-specific code for remote debugging via gdb
7 //========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: Red Hat, jskov, gthomas
47 // Description: Helper functions for gdb stub for OpenRISC processors
50 //####DESCRIPTIONEND####
52 //========================================================================
56 #include <pkgconf/hal.h>
58 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
60 #define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS
62 #include <cyg/hal/hal_stub.h>
63 #include <cyg/hal/hal_arch.h>
64 #include <cyg/hal/hal_intr.h>
65 #include <cyg/hal/openrisc_opcode.h>
66 #include <cyg/infra/cyg_ass.h> // assertion macros
68 #ifdef CYGNUM_HAL_NO_VECTOR_TRACE
69 #define USE_BREAKPOINTS_FOR_SINGLE_STEP
72 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
73 #include <cyg/hal/dbg-threads-api.h> // dbg_currthread_id
76 /* Given a trap value TRAP, return the corresponding signal. */
78 int __computeSignal (unsigned int trap_number)
82 // Either no matching page-table entry or protection fault
83 // while executing load/store operation
84 case CYGNUM_HAL_VECTOR_DATA_PAGE_FAULT:
85 // Either no matching page-table entry or protection fault
86 // while executing load/store operation
87 case CYGNUM_HAL_VECTOR_INSTR_PAGE_FAULT:
90 // No matching entry in D-TLB
91 case CYGNUM_HAL_VECTOR_DTLB_MISS:
92 // No matching entry in I-TLB
93 case CYGNUM_HAL_VECTOR_ITLB_MISS:
94 // Unaligned load/store memory access
95 case CYGNUM_HAL_VECTOR_UNALIGNED_ACCESS:
96 // Access to non-existent physical memory/device
97 case CYGNUM_HAL_VECTOR_BUS_ERROR:
100 // TRAP instruction executed
101 case CYGNUM_HAL_VECTOR_TRAP:
104 /* System call instruction executed */
105 case CYGNUM_HAL_VECTOR_SYSTEM_CALL:
108 /* Tick timer interrupt fired */
109 case CYGNUM_HAL_VECTOR_TICK_TIMER:
112 /* External interrupt */
113 case CYGNUM_HAL_VECTOR_INTERRUPT:
116 // Illegal or reserved instruction
117 case CYGNUM_HAL_VECTOR_RESERVED_INSTRUCTION:
120 // Numeric overflow, etc.
121 case CYGNUM_HAL_VECTOR_RANGE:
130 /* Return the trap number corresponding to the last-taken trap. */
132 int __get_trap_number (void)
134 // The vector is not not part of the GDB register set so get it
135 // directly from the save context.
136 return _hal_registers->vector;
139 /* Set the currently-saved pc register value to PC. This also updates NPC
142 void set_pc (target_register_t pc)
144 put_register (PC, pc);
149 /*----------------------------------------------------------------------
150 * Single-step support
153 // Type of a single OpenRISC instruction
154 typedef cyg_uint32 t_inst;
156 /* Saved instruction data for single step support. */
164 /* Set things up so that the next user resume will execute one instruction.
165 This may be done by setting breakpoints or setting a single step flag
166 in the saved user registers, for example. */
168 void __single_step (void)
170 t_inst *pc = (t_inst *) get_register (PC);
175 targetAddr = pc + 1; /* set default */
178 switch (insn.JType.op) {
181 targetAddr = pc + insn.JType.target;
185 flag = get_register(SR) & SPR_SR_F;
187 targetAddr = pc + insn.JType.target;
191 flag = get_register(SR) & SPR_SR_F;
193 targetAddr = pc + insn.JType.target;
198 targetAddr = (t_inst*)get_register(insn.JRType.rB);
201 /* We don't step into interrupts, syscalls or traps */
206 instrBuffer.targetAddr = targetAddr;
207 instrBuffer.savedInstr = *targetAddr;
208 *targetAddr = __break_opcode ();
210 // No need to flush caches; Generic stub code will handle this.
213 /* Clear the single-step state. */
214 void __clear_single_step (void)
216 if (instrBuffer.targetAddr != NULL)
218 *instrBuffer.targetAddr = instrBuffer.savedInstr;
219 instrBuffer.targetAddr = NULL;
220 instrBuffer.savedInstr = 0;
225 void __install_breakpoints ()
227 /* if (instrBuffer.targetAddr != NULL)
229 instrBuffer.savedInstr = *instrBuffer.targetAddr;
230 *instrBuffer.targetAddr = __break_opcode ();
233 /* Install the breakpoints in the breakpoint list */
234 __install_breakpoint_list();
236 // No need to flush caches here; Generic stub code will handle this.
239 void __clear_breakpoints (void)
241 __clear_breakpoint_list();
244 /* If the breakpoint we hit is in the breakpoint() instruction, return a
248 __is_breakpoint_function ()
250 return get_register (PC) == (target_register_t)&_breakinst;
254 /* Skip the current instruction. Since this is only called by the
255 stub when the PC points to a breakpoint or trap instruction,
256 we can safely just skip 4. */
258 void __skipinst (void)
260 put_register (PC, get_register (PC) + 4);
264 get_register (regnames_t reg)
266 GDB_Registers* gdb_regs;
268 gdb_regs = (GDB_Registers*)_registers;
270 if (reg >= R0 && reg <= R31)
271 return gdb_regs->r[reg];
280 put_register (regnames_t reg, target_register_t value)
282 GDB_Registers* gdb_regs;
284 gdb_regs = (GDB_Registers*)_registers;
286 if (reg >= R0 && reg <= R31) {
287 gdb_regs->r[reg] = value;
288 } else if (reg == PC) {
289 gdb_regs->pc = value;
290 } else if (reg == SR) {
291 gdb_regs->sr = value;
293 CYG_FAIL("Attempt to write to non-existent register ");
297 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
299 // EOF openrisc_stub.c