comparison packages/hal/mips/arch/current/src/mips-stub.c @ 0:3111d98ba7b3 ecos-v1_1-release

Initial commit of eCos version 1.1
author jlarmour
date Tue, 11 May 1999 11:16:07 +0000
parents
children 443894e2e912
comparison
equal deleted inserted replaced
-1:000000000000 0:3111d98ba7b3
1 /* mips-stub.c - helper functions for stub, generic to all MIPS processors
2 *
3 * Copyright (c) 1998 Cygnus Support
4 *
5 * The authors hereby grant permission to use, copy, modify, distribute,
6 * and license this software and its documentation for any purpose, provided
7 * that existing copyright notices are retained in all copies and that this
8 * notice is included verbatim in any distributions. No written agreement,
9 * license, or royalty fee is required for any of the authorized uses.
10 * Modifications to this software may be copyrighted by their authors
11 * and need not follow the licensing terms described here, provided that
12 * the new terms are clearly indicated on the first page of each file where
13 * they apply.
14 */
15
16 #include <stddef.h>
17
18 #include "cyg/hal/hal_stub.h"
19
20 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
21
22 #include "cyg/hal/hal_arch.h"
23 #include <cyg/hal/mips-regs.h>
24 #include <cyg/hal/mips_opcode.h>
25
26 #define SIGHUP 1 /* hangup */
27 #define SIGINT 2 /* interrupt */
28 #define SIGQUIT 3 /* quit */
29 #define SIGILL 4 /* illegal instruction (not reset when caught) */
30 #define SIGTRAP 5 /* trace trap (not reset when caught) */
31 #define SIGIOT 6 /* IOT instruction */
32 #define SIGABRT 6 /* used by abort, replace SIGIOT in the future */
33 #define SIGEMT 7 /* EMT instruction */
34 #define SIGFPE 8 /* floating point exception */
35 #define SIGKILL 9 /* kill (cannot be caught or ignored) */
36 #define SIGBUS 10 /* bus error */
37 #define SIGSEGV 11 /* segmentation violation */
38 #define SIGSYS 12 /* bad argument to system call */
39 #define SIGPIPE 13 /* write on a pipe with no one to read it */
40 #define SIGALRM 14 /* alarm clock */
41 #define SIGTERM 15 /* software termination signal from kill */
42
43
44 /* Saved registers. */
45
46 HAL_SavedRegisters *_hal_registers;
47
48 target_register_t * _registers; /* A pointer to the current set of registers */
49 target_register_t registers[NUMREGS];
50 target_register_t alt_registers[NUMREGS] ; /* Thread or saved process state */
51
52
53 /* Given a trap value TRAP, return the corresponding signal. */
54
55 int __computeSignal (unsigned int trap_number)
56 {
57 switch (trap_number)
58 {
59 case EXC_INT:
60 /* External interrupt */
61 return SIGINT;
62
63 case EXC_RI:
64 /* Reserved instruction */
65 case EXC_CPU:
66 /* Coprocessor unusable */
67 return SIGILL;
68
69 case EXC_BP:
70 /* Break point */
71 return SIGTRAP;
72
73 case EXC_OVF:
74 /* Arithmetic overflow */
75 case EXC_TRAP:
76 /* Trap exception */
77 case EXC_FPE:
78 /* Floating Point Exception */
79 return SIGFPE;
80
81 case EXC_IBE:
82 /* Bus error (Ifetch) */
83 case EXC_DBE:
84 /* Bus error (data load or store) */
85 return SIGBUS;
86
87 case EXC_MOD:
88 /* TLB modification exception */
89 case EXC_TLBL:
90 /* TLB miss (Load or Ifetch) */
91 case EXC_TLBS:
92 /* TLB miss (Store) */
93 case EXC_ADEL:
94 /* Address error (Load or Ifetch) */
95 case EXC_ADES:
96 /* Address error (Store) */
97 return SIGSEGV;
98
99 case EXC_SYS:
100 /* System call */
101 return SIGSYS;
102
103 default:
104 return SIGTERM;
105 }
106 }
107
108
109 /* Return the trap number corresponding to the last-taken trap. */
110
111 int __get_trap_number (void)
112 {
113 return (get_register (CAUSE) & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT;
114 }
115
116 // Return the currently-saved value corresponding to register REG of
117 // the exception context.
118 target_register_t get_register (regnames_t reg)
119 {
120 return registers[reg];
121 }
122
123 // Store VALUE in the register corresponding to WHICH in the exception
124 // context.
125 void put_register (regnames_t which, target_register_t value)
126 {
127 registers[which] = value;
128 }
129
130
131 /* Set the currently-saved pc register value to PC. This also updates NPC
132 as needed. */
133
134 void set_pc (target_register_t pc)
135 {
136 put_register (PC, pc);
137 }
138
139
140 /*----------------------------------------------------------------------
141 * Single-step support
142 */
143
144 /* Saved instruction data for single step support. */
145
146 typedef unsigned long t_inst;
147
148 static struct
149 {
150 t_inst *targetAddr;
151 t_inst savedInstr;
152 } instrBuffer;
153
154
155 /* Set things up so that the next user resume will execute one instruction.
156 This may be done by setting breakpoints or setting a single step flag
157 in the saved user registers, for example. */
158
159 void single_step (void)
160 {
161 InstFmt inst;
162 t_inst *pc = (t_inst *) get_register (PC);
163
164 instrBuffer.targetAddr = pc + 1; /* set default */
165
166 inst.word = *pc; /* read the next instruction */
167
168 //diag_printf("pc %08x %08x\n",pc,inst.word);
169
170 switch (inst.RType.op) { /* override default if branch */
171 case OP_SPECIAL:
172 switch (inst.RType.func) {
173 case OP_JR:
174 case OP_JALR:
175 instrBuffer.targetAddr = (t_inst *) get_register (inst.RType.rs);
176 break;
177 };
178 break;
179
180 case OP_REGIMM:
181 switch (inst.IType.rt) {
182 case OP_BLTZ:
183 case OP_BLTZL:
184 case OP_BLTZAL:
185 case OP_BLTZALL:
186 if (get_register (inst.IType.rs) < 0 )
187 instrBuffer.targetAddr =
188 (t_inst *)(((signed short)inst.IType.imm<<2)
189 + (get_register (PC) + 4));
190 else
191 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
192 break;
193 case OP_BGEZ:
194 case OP_BGEZL:
195 case OP_BGEZAL:
196 case OP_BGEZALL:
197 if (get_register (inst.IType.rs) >= 0 )
198 instrBuffer.targetAddr =
199 (t_inst *)(((signed short)inst.IType.imm<<2)
200 + (get_register (PC) + 4));
201 else
202 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
203 break;
204 };
205 break;
206
207 case OP_J:
208 case OP_JAL:
209 instrBuffer.targetAddr =
210 (t_inst *)((inst.JType.target<<2)
211 + ((get_register (PC) + 4)&0xf0000000));
212 break;
213
214 case OP_BEQ:
215 case OP_BEQL:
216 if (get_register (inst.IType.rs) == get_register (inst.IType.rt))
217 instrBuffer.targetAddr =
218 (t_inst *)(((signed short)inst.IType.imm<<2)
219 + (get_register (PC) + 4));
220 else
221 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
222 break;
223 case OP_BNE:
224 case OP_BNEL:
225 if (get_register (inst.IType.rs) != get_register (inst.IType.rt))
226 instrBuffer.targetAddr =
227 (t_inst *)(((signed short)inst.IType.imm<<2)
228 + (get_register (PC) + 4));
229 else
230 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
231 break;
232 case OP_BLEZ:
233 case OP_BLEZL:
234 if (get_register (inst.IType.rs) <= 0)
235 instrBuffer.targetAddr =
236 (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4));
237 else
238 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
239 break;
240 case OP_BGTZ:
241 case OP_BGTZL:
242 if (get_register (inst.IType.rs) > 0)
243 instrBuffer.targetAddr =
244 (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4));
245 else
246 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
247 break;
248
249 #if 0 /* no floating point support at the moment */
250 case OP_COP1:
251 if (inst.RType.rs == OP_BC)
252 switch (inst.RType.rt) {
253 case COPz_BCF:
254 case COPz_BCFL:
255 if (get_register (FCSR) & CSR_C)
256 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
257 else
258 instrBuffer.targetAddr =
259 (t_inst *)(((signed short)inst.IType.imm<<2)
260 + (get_register (PC) + 4));
261 break;
262 case COPz_BCT:
263 case COPz_BCTL:
264 if (get_register (FCSR) & CSR_C)
265 instrBuffer.targetAddr =
266 (t_inst *)(((signed short)inst.IType.imm<<2)
267 + (get_register (PC) + 4));
268 else
269 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
270 break;
271 };
272 break;
273 #endif
274
275 }
276 }
277
278
279 /* Clear the single-step state. */
280
281 void clear_single_step (void)
282 {
283 //diag_printf("clear_ss ta %08x\n",instrBuffer.targetAddr);
284 if (instrBuffer.targetAddr != NULL)
285 {
286 *instrBuffer.targetAddr = instrBuffer.savedInstr;
287 instrBuffer.targetAddr = NULL;
288 }
289 instrBuffer.savedInstr = NOP_INSTR;
290 }
291
292
293 void install_breakpoints ()
294 {
295 //diag_printf("install_bpt ta %08x\n",instrBuffer.targetAddr);
296 if (instrBuffer.targetAddr != NULL)
297 {
298 instrBuffer.savedInstr = *instrBuffer.targetAddr;
299 *instrBuffer.targetAddr = __break_opcode ();
300 //diag_printf("ta %08x si %08x *ta %08x\n",
301 // instrBuffer.targetAddr,instrBuffer.savedInstr,*instrBuffer.targetAddr);
302 }
303 }
304
305
306 /* If the breakpoint we hit is in the breakpoint() instruction, return a
307 non-zero value. */
308
309 int
310 __is_breakpoint_function ()
311 {
312 return get_register (PC) == (target_register_t)&_breakinst;
313 }
314
315
316 /* Skip the current instruction. Since this is only called by the
317 stub when the PC points to a breakpoint or trap instruction,
318 we can safely just skip 4. */
319
320 void __skipinst (void)
321 {
322 put_register (PC, get_register (PC) + 4);
323 }
324
325
326 /* Write the 'T' packet in BUFFER. SIGVAL is the signal the program
327 received. */
328
329 void __build_t_packet (int sigval, char *buf)
330 {
331 target_register_t addr;
332 char *ptr = buf;
333 target_register_t *sp;
334
335 sp = (target_register_t *) get_register (SP);
336
337 *ptr++ = 'T';
338 *ptr++ = __tohex (sigval >> 4);
339 *ptr++ = __tohex (sigval);
340
341
342 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
343 // Include thread ID if thread manipulation is required.
344 {
345 int id;
346 extern int dbg_currthread_id(void); // FIXME: get from header instead
347
348 *ptr++ = 't';
349 *ptr++ = 'h';
350 *ptr++ = 'r';
351 *ptr++ = 'e';
352 *ptr++ = 'a';
353 *ptr++ = 'd';
354 *ptr++ = ':';
355
356 id = dbg_currthread_id ();
357 ptr = __mem2hex((char *)&id, ptr, sizeof(id), 0);
358 *ptr++ = ';';
359 }
360 #endif
361
362 *ptr++ = __tohex (PC >> 4);
363 *ptr++ = __tohex (PC);
364 *ptr++ = ':';
365 addr = get_register (PC);
366 ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0);
367 *ptr++ = ';';
368
369 *ptr++ = __tohex (SP >> 4);
370 *ptr++ = __tohex (SP);
371 *ptr++ = ':';
372 ptr = __mem2hex((char *)&sp, ptr, sizeof(sp), 0);
373 *ptr++ = ';';
374
375 *ptr++ = 0;
376 }
377
378 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS