source: trunk/libs/newlib/src/libgloss/sparc/erc32-stub.c @ 621

Last change on this file since 621 was 444, checked in by satin@…, 7 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 8.4 KB
Line 
1/*
2 * Copyright (c) 1996 Cygnus Support
3 *
4 * The authors hereby grant permission to use, copy, modify, distribute,
5 * and license this software and its documentation for any purpose, provided
6 * that existing copyright notices are retained in all copies and that this
7 * notice is included verbatim in any distributions. No written agreement,
8 * license, or royalty fee is required for any of the authorized uses.
9 * Modifications to this software may be copyrighted by their authors
10 * and need not follow the licensing terms described here, provided that
11 * the new terms are clearly indicated on the first page of each file where
12 * they apply.
13 */
14
15#include <string.h>
16#include <signal.h>
17#include "debug.h"
18#include "asm.h"
19#include "slite.h"
20
21extern unsigned long rdtbr();
22extern struct trap_entry fltr_proto;
23extern void trap_low();
24exception_t default_trap_hook = trap_low;
25void target_reset();
26void flush_i_cache();
27char *target_read_registers(unsigned long *);
28char *target_write_registers(unsigned long *);
29char *target_dump_state(unsigned long *);
30
31#define NUMREGS 72
32
33/* Number of bytes of registers.  */
34#define NUMREGBYTES (NUMREGS * 4)
35
36enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
37                 O0, O1, O2, O3, O4, O5, SP, O7,
38                 L0, L1, L2, L3, L4, L5, L6, L7,
39                 I0, I1, I2, I3, I4, I5, FP, I7,
40
41                 F0, F1, F2, F3, F4, F5, F6, F7,
42                 F8, F9, F10, F11, F12, F13, F14, F15,
43                 F16, F17, F18, F19, F20, F21, F22, F23,
44                 F24, F25, F26, F27, F28, F29, F30, F31,
45                 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
46
47/*
48 * Each entry in the trap vector occupies four words, typically a jump
49 * to the processing routine.
50 */
51struct trap_entry {
52  unsigned sethi_filler:10;
53  unsigned sethi_imm22:22;
54  unsigned jmpl_filler:19;
55  unsigned jmpl_simm13:13;
56  unsigned long filler[2];
57};
58
59/*
60 * This table contains the mapping between SPARC hardware trap types, and
61 * signals, which are primarily what GDB understands.  It also indicates
62 * which hardware traps we need to commandeer when initializing the stub.
63 */
64struct trap_info hard_trap_info[] = {
65  {1, SIGSEGV},                 /* instruction access error */
66  {2, SIGILL},                  /* privileged instruction */
67  {3, SIGILL},                  /* illegal instruction */
68  {4, SIGEMT},                  /* fp disabled */
69  {36, SIGEMT},                 /* cp disabled */
70  {7, SIGBUS},                  /* mem address not aligned */
71  {9, SIGSEGV},                 /* data access exception */
72  {10, SIGEMT},                 /* tag overflow */
73  {128+1, SIGTRAP},             /* ta 1 - normal breakpoint instruction */
74  {0, 0}                        /* Must be last */
75};
76
77extern struct trap_entry fltr_proto;
78void
79exception_handler (int tt, unsigned long routine)
80{
81  struct trap_entry *tb;        /* Trap vector base address */
82
83  DEBUG (1, "Entering exception_handler()");
84  if (tt != 256) {
85    tb = (struct trap_entry *) (rdtbr() & ~0xfff);
86  } else {
87    tt = 255;
88    tb = (struct trap_entry *) 0;
89  }
90
91  tb[tt] = fltr_proto;
92
93  tb[tt].sethi_imm22 = routine >> 10;
94  tb[tt].jmpl_simm13 = routine & 0x3ff;
95
96  DEBUG (1, "Leaving exception_handler()");
97}
98
99/*
100 * This is so we can trap a memory fault when reading or writing
101 * directly to memory.
102 */
103void
104set_mem_fault_trap(enable)
105     int enable;
106{
107  extern void fltr_set_mem_err();
108
109  DEBUG (1, "Entering set_mem_fault_trap()");
110
111  mem_err = 0;
112
113  if (enable)
114    exception_handler(9, (unsigned long)fltr_set_mem_err);
115  else
116    exception_handler(9, (unsigned long)trap_low);
117
118  DEBUG (1, "Leaving set_mem_fault_trap()");
119}
120
121/*
122 * This function does all command procesing for interfacing to gdb.  It
123 * returns 1 if you should skip the instruction at the trap address, 0
124 * otherwise.
125 */
126extern void breakinst();
127
128void
129handle_exception (registers)
130     unsigned long *registers;
131{
132  int sigval;
133
134  /* First, we must force all of the windows to be spilled out */
135
136  DEBUG (1, "Entering handle_exception()");
137
138/*  asm("mov %g0, %wim ; nop; nop; nop"); */
139  asm(" save %sp, -64, %sp      \n\
140        save %sp, -64, %sp      \n\
141        save %sp, -64, %sp      \n\
142        save %sp, -64, %sp      \n\
143        save %sp, -64, %sp      \n\
144        save %sp, -64, %sp      \n\
145        save %sp, -64, %sp      \n\
146        save %sp, -64, %sp      \n\
147        restore                 \n\
148        restore                 \n\
149        restore                 \n\
150        restore                 \n\
151        restore                 \n\
152        restore                 \n\
153        restore                 \n\
154        restore                 \n\
155");
156
157  if (registers[PC] == (unsigned long)breakinst) {
158    registers[PC] = registers[NPC];
159    registers[NPC] += 4;
160  }
161
162  /* get the last know signal number from the trap register */
163  sigval = computeSignal((registers[TBR] >> 4) & 0xff);
164
165  /* call the main command processing loop for gdb */
166  gdb_event_loop (sigval, registers);
167}
168
169/*
170 * This function will generate a breakpoint exception.  It is used at the
171 * beginning of a program to sync up with a debugger and can be used
172 * otherwise as a quick means to stop program execution and "break" into
173 * the debugger.
174 */
175void
176breakpoint()
177{
178  DEBUG (1, "Entering breakpoint()");
179
180  if (!initialized)
181    return;
182
183  asm(" .globl " STRINGSYM(breakinst) "         \n\
184        " STRINGSYM(breakinst) ": ta 128+1      \n\
185        nop                                     \n\
186        nop                                     \n\
187      ");
188}
189
190/*
191 * This is just a test vector for debugging excpetions.
192 */
193void
194bad_trap(tt)
195int tt;
196{
197  print ("Got a bad trap #");
198  outbyte (tt);
199  outbyte ('\n');
200  asm("ta 0             \n\
201        nop             \n\
202        nop             \n\
203      ");
204}
205
206/*
207 * This is just a test vector for debugging excpetions.
208 */
209void
210soft_trap(tt)
211int tt;
212{
213  print ("Got a soft trap #");
214  outbyte (tt);
215  outbyte ('\n');
216  asm("ta 0             \n\
217        nop             \n\
218        nop             \n\
219      ");
220}
221
222/*
223 * Flush the instruction cache.  We need to do this for the debugger stub so
224 * that breakpoints, et. al. become visible to the instruction stream after
225 * storing them in memory.
226 *
227 * For the sparclite, we need to do something here, but for a standard
228 * sparc (which SIS simulates), we don't.
229 */
230
231void
232flush_i_cache ()
233{
234}
235
236/*
237 * This will reset the processor, so we never return from here.
238 */
239void
240target_reset()
241{
242  asm ("call 0          \n\
243        nop ");
244}
245
246/*
247 * g - read registers.
248 *      no params.
249 *      returns a vector of words, size is NUM_REGS.
250 */
251char *
252target_read_registers(unsigned long *registers)
253{
254  char *ptr;
255  unsigned long *sp;
256 
257  DEBUG (1, "In target_read_registers()");
258
259  ptr = packet_out_buf;
260  ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
261  ptr = mem2hex((unsigned char *)(sp + 0), ptr, 16 * 4, 0); /* L & I regs */
262  memset(ptr, '0', 32 * 8); /* Floating point */
263  mem2hex((char *)&registers[Y],
264          ptr + 32 * 4 * 2,
265          8 * 4,
266          0);           /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
267  return (ptr);
268}
269
270/*
271 * G - write registers.
272 *      param is a vector of words, size is NUM_REGS.
273 *      returns an OK or an error number.
274 */
275char *
276target_write_registers(unsigned long *registers)
277{       
278  unsigned char *ptr;
279  unsigned long *sp;
280  unsigned long *newsp, psr;
281
282  DEBUG (1, "In target_write_registers()");
283
284  psr = registers[PSR];
285 
286  ptr = &packet_in_buf[1];
287
288  hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
289  hex2mem(ptr + 16 * 4 * 2, (unsigned char *)(sp + 0), 16 * 4, 0); /* L & I regs */
290  hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
291          8 * 4, 0);    /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
292 
293  /*
294   * see if the stack pointer has moved.  If so, then copy the saved
295   * locals and ins to the new location.  This keeps the window
296   * overflow and underflow routines happy.
297   */
298 
299  newsp = (unsigned long *)registers[SP];
300  if (sp != newsp)
301    sp = memcpy(newsp, sp, 16 * 4);
302 
303  /* Don't allow CWP to be modified. */
304 
305  if (psr != registers[PSR])
306    registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
307 
308  return (ptr);
309}
310
311char *
312target_dump_state(unsigned long *registers)
313{
314  int tt;                       /* Trap type */
315  int sigval;
316  char *ptr;
317  unsigned long *sp;
318
319  DEBUG (1, "In target_dump_state()");
320
321  sp = (unsigned long *)registers[SP];
322
323  tt = (registers[TBR] >> 4) & 0xff;
324
325  /* reply to host that an exception has occurred */
326  sigval = computeSignal(tt);
327  ptr = packet_out_buf;
328
329  *ptr++ = 'T';
330  *ptr++ = hexchars[sigval >> 4];
331  *ptr++ = hexchars[sigval & 0xf];
332
333  *ptr++ = hexchars[PC >> 4];
334  *ptr++ = hexchars[PC & 0xf];
335  *ptr++ = ':';
336  ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0);
337  *ptr++ = ';';
338
339  *ptr++ = hexchars[FP >> 4];
340  *ptr++ = hexchars[FP & 0xf];
341  *ptr++ = ':';
342  ptr = mem2hex((unsigned char *)(sp + 8 + 6), ptr, 4, 0); /* FP */
343  *ptr++ = ';';
344
345  *ptr++ = hexchars[SP >> 4];
346  *ptr++ = hexchars[SP & 0xf];
347  *ptr++ = ':';
348  ptr = mem2hex((unsigned char *)&sp, ptr, 4, 0);
349  *ptr++ = ';';
350
351  *ptr++ = hexchars[NPC >> 4];
352
353  return (packet_out_buf);
354}
355
356void
357write_pc(unsigned long *registers, unsigned long addr)
358{
359  DEBUG (1, "In write_pc");
360
361  registers[PC] = addr;
362  registers[NPC] = addr + 4;
363}
Note: See TracBrowser for help on using the repository browser.