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 
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
exception_handler(int tt,unsigned long routine)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
set_mem_fault_trap(enable)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
handle_exception(registers)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
breakpoint()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
bad_trap(tt)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
soft_trap(tt)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
flush_i_cache()232 flush_i_cache ()
233 {
234 }
235 
236 /*
237  * This will reset the processor, so we never return from here.
238  */
239 void
target_reset()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 *
target_read_registers(unsigned long * registers)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 *
target_write_registers(unsigned long * registers)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 *
target_dump_state(unsigned long * registers)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
write_pc(unsigned long * registers,unsigned long addr)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 }
364