OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.18.0/] [libgloss/] [sparc/] [erc32-stub.c] - Blame information for rev 645

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
/*
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
 
21
extern unsigned long rdtbr();
22
extern struct trap_entry fltr_proto;
23
extern void trap_low();
24
exception_t default_trap_hook = trap_low;
25
void target_reset();
26
void flush_i_cache();
27
char *target_read_registers(unsigned long *);
28
char *target_write_registers(unsigned long *);
29
char *target_dump_state(unsigned long *);
30
 
31
#define NUMREGS 72
32
 
33
/* Number of bytes of registers.  */
34
#define NUMREGBYTES (NUMREGS * 4)
35
 
36
enum 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
 */
51
struct 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
 */
64
struct 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
 
77
extern struct trap_entry fltr_proto;
78
void
79
exception_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
 */
103
void
104
set_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
 */
126
extern void breakinst();
127
 
128
void
129
handle_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
 */
175
void
176
breakpoint()
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
 */
193
void
194
bad_trap(tt)
195
int 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
 */
209
void
210
soft_trap(tt)
211
int 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
 
231
void
232
flush_i_cache ()
233
{
234
}
235
 
236
/*
237
 * This will reset the processor, so we never return from here.
238
 */
239
void
240
target_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
 */
251
char *
252
target_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
 */
275
char *
276
target_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
 
311
char *
312
target_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
 
356
void
357
write_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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.