1 //========================================================================
5 // Helper functions for H8/300H stub
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####
43 // Author(s): Red Hat, jskov
44 // Contributors: Red Hat, jskov
47 // Description: Helper functions for H8/300H stub
50 //####DESCRIPTIONEND####
52 //========================================================================
56 #include <pkgconf/hal.h>
58 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
60 #include <cyg/hal/hal_stub.h>
61 #include <cyg/hal/hal_arch.h>
62 #include <cyg/hal/hal_intr.h>
64 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
65 #include <cyg/hal/dbg-threads-api.h> // dbg_currthread_id
68 /*----------------------------------------------------------------------
69 * Asynchronous interrupt support
72 typedef unsigned short t_inst;
80 /* Called to asynchronously interrupt a running program.
81 Must be passed address of instruction interrupted.
82 This is typically called in response to a debug port
87 install_async_breakpoint(void *pc)
89 asyncBuffer.targetAddr = pc;
90 asyncBuffer.savedInstr = *(t_inst *)pc;
91 *(t_inst *)pc = (t_inst)HAL_BREAKINST;
92 __instruction_cache(CACHE_FLUSH);
93 __data_cache(CACHE_FLUSH);
96 /*--------------------------------------------------------------------*/
97 /* Given a trap value TRAP, return the corresponding signal. */
99 int __computeSignal (unsigned int trap_number)
101 switch (trap_number) {
109 /*--------------------------------------------------------------------*/
110 /* Return the trap number corresponding to the last-taken trap. */
112 int __get_trap_number (void)
114 extern int CYG_LABEL_NAME(_intvector);
115 // The vector is not not part of the GDB register set so get it
116 // directly from the save context.
117 return CYG_LABEL_NAME(_intvector);
120 /*--------------------------------------------------------------------*/
121 /* Set the currently-saved pc register value to PC. This also updates NPC
124 void set_pc (target_register_t pc)
126 put_register (PC, pc);
130 /*----------------------------------------------------------------------
131 * Single-step support. Lifted from CygMon.
134 #define NUM_SS_BPTS 2
135 static target_register_t break_mem [NUM_SS_BPTS] = {0, 0};
136 static unsigned char break_mem_data [NUM_SS_BPTS];
138 /* Set a single-step breakpoint at ADDR. Up to two such breakpoints
139 can be set; WHICH specifies which one to set (0 or 1). */
142 set_single_bp (int which, unsigned char *addr)
144 if (break_mem[which] == 0) {
145 break_mem[which] = (target_register_t) addr;
146 break_mem_data[which] = *(unsigned short *)addr;
147 *(unsigned short *)addr = HAL_BREAKINST;
151 /* Clear any single-step breakpoint(s) that may have been set. */
153 void __clear_single_step (void)
156 for (x = 0; x < NUM_SS_BPTS; x++)
158 unsigned char* addr = (unsigned char*) break_mem[x];
160 *addr = break_mem_data[x];
166 /* Set breakpoint(s) to simulate a single step from the current PC. */
168 const static unsigned char opcode_length0[]={
169 0x04,0x02,0x04,0x02,0x04,0x02,0x04,0x02, /* 0x58 */
170 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, /* 0x60 */
171 0x02,0x02,0x11,0x11,0x02,0x02,0x04,0x04, /* 0x68 */
172 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, /* 0x70 */
173 0x08,0x04,0x06,0x04,0x04,0x04,0x04,0x04 /* 0x78 */
176 const static unsigned char opcode_length1[]={
177 0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00,
178 0x02,0x00,0x00,0x00,0x04,0x04,0x00,0x04
181 static int insn_length(unsigned char *pc)
183 if (*pc != 0x01 && (*pc < 0x58 || *pc>=0x80))
188 switch (*(pc+1) & 0xf0) {
190 if (*(pc+2)== 0x78) {
192 } else if (*(pc+2)== 0x6b) {
193 return (*(pc+3) & 0x20)?8:6;
195 return (*(pc+2) & 0x02)?6:4;
198 return (*(pc+2) & 0x02)?8:6;
200 return opcode_length1[*(pc+1)>>4];
204 return (*(pc+1) & 0x20)?6:4;
206 return opcode_length0[*pc-0x58];
210 void __single_step (void)
212 unsigned int pc = get_register (PC);
216 opcode = *(unsigned short *)pc;
217 next = pc + insn_length((unsigned char *)pc);
218 if (opcode == 0x5470) {
221 sp = (unsigned long *)get_register(SP);
222 next = *sp & 0x00ffffff;
223 } else if ((opcode & 0xfb00) != 0x5800) {
226 const short reg_tbl[]={ER0,ER1,ER2,ER3,ER4,ER5,ER6,SP};
227 switch(opcode & 0xfb00) {
229 regs = (opcode & 0x0070) >> 8;
230 next = get_register(reg_tbl[regs]);
233 next = *(unsigned long *)(pc+2) & 0x00ffffff;
236 next = *(unsigned long *)(opcode & 0xff);
239 } else if (((opcode & 0xf000) == 0x4000) || ((opcode & 0xff00) == 0x5500)) {
242 dsp = (long)(opcode && 0xff)+pc+2;
243 set_single_bp(1,(unsigned char *)dsp);
244 } else if (((opcode & 0xff00) == 0x5800) || ((opcode & 0xff00) == 0x5c00)) {
247 dsp = *(unsigned short *)(pc+2)+pc+4;
248 set_single_bp(1,(unsigned char *)dsp);
250 set_single_bp(0,(unsigned char *)next);
253 void __install_breakpoints (void)
255 /* NOP since single-step HW exceptions are used instead of
259 void __clear_breakpoints (void)
265 /* If the breakpoint we hit is in the breakpoint() instruction, return a
268 externC void CYG_LABEL_NAME(breakinst)(void);
270 __is_breakpoint_function ()
272 return get_register (PC) == (target_register_t)&CYG_LABEL_NAME(breakinst);
276 /* Skip the current instruction. */
278 void __skipinst (void)
280 unsigned long pc = get_register (PC);
282 pc+=insn_length((unsigned char *)pc);
283 put_register (PC, (target_register_t) pc);
286 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS