Protoization.
[deliverable/binutils-gdb.git] / gdb / m32r-stub.c
CommitLineData
c906108c
SS
1/****************************************************************************
2
3 THIS SOFTWARE IS NOT COPYRIGHTED
4
5 HP offers the following for use in the public domain. HP makes no
6 warranty with regard to the software or it's performance and the
7 user accepts the software "AS IS" with all faults.
8
9 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
13****************************************************************************/
14
15/****************************************************************************
16 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17 *
18 * Module name: remcom.c $
19 * Revision: 1.34 $
20 * Date: 91/03/09 12:29:49 $
21 * Contributor: Lake Stevens Instrument Division$
22 *
23 * Description: low level support for gdb debugger. $
24 *
25 * Considerations: only works on target hardware $
26 *
27 * Written by: Glenn Engel $
28 * ModuleState: Experimental $
29 *
30 * NOTES: See Below $
31 *
32 * Modified for M32R by Michael Snyder, Cygnus Support.
33 *
34 * To enable debugger support, two things need to happen. One, a
35 * call to set_debug_traps() is necessary in order to allow any breakpoints
36 * or error conditions to be properly intercepted and reported to gdb.
37 * Two, a breakpoint needs to be generated to begin communication. This
38 * is most easily accomplished by a call to breakpoint(). Breakpoint()
39 * simulates a breakpoint by executing a trap #1.
40 *
41 * The external function exceptionHandler() is
42 * used to attach a specific handler to a specific M32R vector number.
43 * It should use the same privilege level it runs at. It should
44 * install it as an interrupt gate so that interrupts are masked
45 * while the handler runs.
46 *
47 * Because gdb will sometimes write to the stack area to execute function
48 * calls, this program cannot rely on using the supervisor stack so it
49 * uses it's own stack area reserved in the int array remcomStack.
50 *
51 *************
52 *
53 * The following gdb commands are supported:
54 *
55 * command function Return value
56 *
57 * g return the value of the CPU registers hex data or ENN
58 * G set the value of the CPU registers OK or ENN
59 *
60 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
61 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
62 * XAA..AA,LLLL: Write LLLL binary bytes at address OK or ENN
63 * AA..AA
64 *
65 * c Resume at current address SNN ( signal NN)
66 * cAA..AA Continue at address AA..AA SNN
67 *
68 * s Step one instruction SNN
69 * sAA..AA Step one instruction from AA..AA SNN
70 *
71 * k kill
72 *
73 * ? What was the last sigval ? SNN (signal NN)
74 *
75 * All commands and responses are sent with a packet which includes a
76 * checksum. A packet consists of
77 *
78 * $<packet info>#<checksum>.
79 *
80 * where
81 * <packet info> :: <characters representing the command or response>
82 * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
83 *
84 * When a packet is received, it is first acknowledged with either '+' or '-'.
85 * '+' indicates a successful transfer. '-' indicates a failed transfer.
86 *
87 * Example:
88 *
89 * Host: Reply:
90 * $m0,10#2a +$00010203040506070809101112131415#42
91 *
92 ****************************************************************************/
93
94
95/************************************************************************
96 *
97 * external low-level support routines
98 */
99extern void putDebugChar(); /* write a single character */
100extern int getDebugChar(); /* read and return a single char */
101extern void exceptionHandler(); /* assign an exception handler */
102
103/*****************************************************************************
104 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
105 * at least NUMREGBYTES*2 are needed for register packets
106 */
107#define BUFMAX 400
108
109static char initialized; /* boolean flag. != 0 means we've been initialized */
110
111int remote_debug;
112/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
113
114static const unsigned char hexchars[]="0123456789abcdef";
115
116#define NUMREGS 24
117
118/* Number of bytes of registers. */
119#define NUMREGBYTES (NUMREGS * 4)
120enum regnames { R0, R1, R2, R3, R4, R5, R6, R7,
121 R8, R9, R10, R11, R12, R13, R14, R15,
122 PSW, CBR, SPI, SPU, BPC, PC, ACCL, ACCH };
123
124enum SYS_calls {
125 SYS_null,
126 SYS_exit,
127 SYS_open,
128 SYS_close,
129 SYS_read,
130 SYS_write,
131 SYS_lseek,
132 SYS_unlink,
133 SYS_getpid,
134 SYS_kill,
135 SYS_fstat,
136 SYS_sbrk,
137 SYS_fork,
138 SYS_execve,
139 SYS_wait4,
140 SYS_link,
141 SYS_chdir,
142 SYS_stat,
143 SYS_utime,
144 SYS_chown,
145 SYS_chmod,
146 SYS_time,
147 SYS_pipe };
148
149static int registers[NUMREGS];
150
151#define STACKSIZE 8096
152static unsigned char remcomInBuffer[BUFMAX];
153static unsigned char remcomOutBuffer[BUFMAX];
154static int remcomStack[STACKSIZE/sizeof(int)];
155static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
156
157static unsigned int save_vectors[18]; /* previous exception vectors */
158
159/* Indicate to caller of mem2hex or hex2mem that there has been an error. */
160static volatile int mem_err = 0;
161
162/* Store the vector number here (since GDB only gets the signal
163 number through the usual means, and that's not very specific). */
164int gdb_m32r_vector = -1;
165
166#if 0
167#include "syscall.h" /* for SYS_exit, SYS_write etc. */
168#endif
169
170/* Global entry points:
171 */
172
173extern void handle_exception(int);
174extern void set_debug_traps(void);
175extern void breakpoint(void);
176
177/* Local functions:
178 */
179
180static int computeSignal(int);
181static void putpacket(unsigned char *);
d4f3574e 182static unsigned char *getpacket(void);
c906108c
SS
183
184static unsigned char *mem2hex(unsigned char *, unsigned char *, int, int);
185static unsigned char *hex2mem(unsigned char *, unsigned char *, int, int);
186static int hexToInt(unsigned char **, int *);
187static unsigned char *bin2mem(unsigned char *, unsigned char *, int, int);
188static void stash_registers(void);
189static void restore_registers(void);
190static int prepare_to_step(int);
191static int finish_from_step(void);
7a292a7a 192static unsigned long crc32 (unsigned char *, int, unsigned long);
c906108c
SS
193
194static void gdb_error(char *, char *);
195static int gdb_putchar(int), gdb_puts(char *), gdb_write(char *, int);
196
197static unsigned char *strcpy (unsigned char *, const unsigned char *);
198static int strlen (const unsigned char *);
199
200/*
201 * This function does all command procesing for interfacing to gdb.
202 */
203
204void
205handle_exception(int exceptionVector)
206{
104c1213 207 int sigval, stepping;
c906108c
SS
208 int addr, length, i;
209 unsigned char * ptr;
210 unsigned char buf[16];
211 int binary;
212
213 if (!finish_from_step())
214 return; /* "false step": let the target continue */
215
216 gdb_m32r_vector = exceptionVector;
217
218 if (remote_debug)
219 {
220 mem2hex((unsigned char *) &exceptionVector, buf, 4, 0);
221 gdb_error("Handle exception %s, ", buf);
222 mem2hex((unsigned char *) &registers[PC], buf, 4, 0);
223 gdb_error("PC == 0x%s\n", buf);
224 }
225
226 /* reply to host that an exception has occurred */
227 sigval = computeSignal( exceptionVector );
228
229 ptr = remcomOutBuffer;
230
231 *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
232 *ptr++ = hexchars[sigval >> 4];
233 *ptr++ = hexchars[sigval & 0xf];
234
235 *ptr++ = hexchars[PC >> 4];
236 *ptr++ = hexchars[PC & 0xf];
237 *ptr++ = ':';
238 ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0); /* PC */
239 *ptr++ = ';';
240
241 *ptr++ = hexchars[R13 >> 4];
242 *ptr++ = hexchars[R13 & 0xf];
243 *ptr++ = ':';
244 ptr = mem2hex((unsigned char *)&registers[R13], ptr, 4, 0); /* FP */
245 *ptr++ = ';';
246
247 *ptr++ = hexchars[R15 >> 4];
248 *ptr++ = hexchars[R15 & 0xf];
249 *ptr++ = ':';
250 ptr = mem2hex((unsigned char *)&registers[R15], ptr, 4, 0); /* SP */
251 *ptr++ = ';';
252 *ptr++ = 0;
253
254 if (exceptionVector == 0) /* simulated SYS call stuff */
255 {
256 mem2hex((unsigned char *) &registers[PC], buf, 4, 0);
257 switch (registers[R0]) {
258 case SYS_exit:
259 gdb_error("Target program has exited at %s\n", buf);
260 ptr = remcomOutBuffer;
261 *ptr++ = 'W';
262 sigval = registers[R1] & 0xff;
263 *ptr++ = hexchars[sigval >> 4];
264 *ptr++ = hexchars[sigval & 0xf];
265 *ptr++ = 0;
266 break;
267 case SYS_open:
268 gdb_error("Target attempts SYS_open call at %s\n", buf);
269 break;
270 case SYS_close:
271 gdb_error("Target attempts SYS_close call at %s\n", buf);
272 break;
273 case SYS_read:
274 gdb_error("Target attempts SYS_read call at %s\n", buf);
275 break;
276 case SYS_write:
277 if (registers[R1] == 1 || /* write to stdout */
278 registers[R1] == 2) /* write to stderr */
279 { /* (we can do that) */
280 registers[R0] = gdb_write((void *) registers[R2], registers[R3]);
281 return;
282 }
283 else
284 gdb_error("Target attempts SYS_write call at %s\n", buf);
285 break;
286 case SYS_lseek:
287 gdb_error("Target attempts SYS_lseek call at %s\n", buf);
288 break;
289 case SYS_unlink:
290 gdb_error("Target attempts SYS_unlink call at %s\n", buf);
291 break;
292 case SYS_getpid:
293 gdb_error("Target attempts SYS_getpid call at %s\n", buf);
294 break;
295 case SYS_kill:
296 gdb_error("Target attempts SYS_kill call at %s\n", buf);
297 break;
298 case SYS_fstat:
299 gdb_error("Target attempts SYS_fstat call at %s\n", buf);
300 break;
301 default:
302 gdb_error("Target attempts unknown SYS call at %s\n", buf);
303 break;
304 }
305 }
306
307 putpacket(remcomOutBuffer);
308
104c1213
JM
309 stepping = 0;
310
c906108c
SS
311 while (1==1) {
312 remcomOutBuffer[0] = 0;
d4f3574e 313 ptr = getpacket();
c906108c 314 binary = 0;
104c1213 315 switch (*ptr++) {
c906108c
SS
316 default: /* Unknown code. Return an empty reply message. */
317 break;
318 case 'R':
c906108c
SS
319 if (hexToInt (&ptr, &addr))
320 registers[PC] = addr;
321 strcpy(remcomOutBuffer, "OK");
322 break;
323 case '!':
324 strcpy(remcomOutBuffer, "OK");
325 break;
326 case 'X': /* XAA..AA,LLLL:<binary data>#cs */
327 binary = 1;
328 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
329 /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
330 {
c906108c
SS
331 if (hexToInt(&ptr,&addr))
332 if (*(ptr++) == ',')
333 if (hexToInt(&ptr,&length))
334 if (*(ptr++) == ':')
335 {
336 mem_err = 0;
337 if (binary)
338 bin2mem (ptr, (unsigned char *) addr, length, 1);
339 else
340 hex2mem(ptr, (unsigned char*) addr, length, 1);
341 if (mem_err) {
342 strcpy (remcomOutBuffer, "E03");
343 gdb_error ("memory fault", "");
344 } else {
345 strcpy(remcomOutBuffer,"OK");
346 }
347 ptr = 0;
348 }
349 if (ptr)
350 {
351 strcpy(remcomOutBuffer,"E02");
c906108c
SS
352 }
353 }
354 break;
355 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
356 /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
c906108c
SS
357 if (hexToInt(&ptr,&addr))
358 if (*(ptr++) == ',')
359 if (hexToInt(&ptr,&length))
360 {
361 ptr = 0;
362 mem_err = 0;
363 mem2hex((unsigned char*) addr, remcomOutBuffer, length, 1);
364 if (mem_err) {
365 strcpy (remcomOutBuffer, "E03");
366 gdb_error ("memory fault", "");
367 }
368 }
369 if (ptr)
370 {
371 strcpy(remcomOutBuffer,"E01");
c906108c
SS
372 }
373 break;
374 case '?':
375 remcomOutBuffer[0] = 'S';
376 remcomOutBuffer[1] = hexchars[sigval >> 4];
377 remcomOutBuffer[2] = hexchars[sigval % 16];
378 remcomOutBuffer[3] = 0;
379 break;
380 case 'd':
381 remote_debug = !(remote_debug); /* toggle debug flag */
382 break;
383 case 'g': /* return the value of the CPU registers */
384 mem2hex((unsigned char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
385 break;
386 case 'P': /* set the value of a single CPU register - return OK */
387 {
388 int regno;
389
c906108c
SS
390 if (hexToInt (&ptr, &regno) && *ptr++ == '=')
391 if (regno >= 0 && regno < NUMREGS)
392 {
393 int stackmode;
394
395 hex2mem (ptr, (unsigned char *) &registers[regno], 4, 0);
396 /*
397 * Since we just changed a single CPU register, let's
398 * make sure to keep the several stack pointers consistant.
399 */
400 stackmode = registers[PSW] & 0x80;
401 if (regno == R15) /* stack pointer changed */
402 { /* need to change SPI or SPU */
403 if (stackmode == 0)
404 registers[SPI] = registers[R15];
405 else
406 registers[SPU] = registers[R15];
407 }
408 else if (regno == SPU) /* "user" stack pointer changed */
409 {
410 if (stackmode != 0) /* stack in user mode: copy SP */
411 registers[R15] = registers[SPU];
412 }
413 else if (regno == SPI) /* "interrupt" stack pointer changed */
414 {
415 if (stackmode == 0) /* stack in interrupt mode: copy SP */
416 registers[R15] = registers[SPI];
417 }
418 else if (regno == PSW) /* stack mode may have changed! */
419 { /* force SP to either SPU or SPI */
420 if (stackmode == 0) /* stack in user mode */
421 registers[R15] = registers[SPI];
422 else /* stack in interrupt mode */
423 registers[R15] = registers[SPU];
424 }
425 strcpy (remcomOutBuffer, "OK");
426 break;
427 }
e9277ae8 428 strcpy (remcomOutBuffer, "E01");
c906108c
SS
429 break;
430 }
431 case 'G': /* set the value of the CPU registers - return OK */
6426a772 432 hex2mem(ptr, (unsigned char*) registers, NUMREGBYTES, 0);
c906108c
SS
433 strcpy(remcomOutBuffer,"OK");
434 break;
435 case 's': /* sAA..AA Step one instruction from AA..AA(optional) */
104c1213 436 stepping = 1;
c906108c
SS
437 case 'c': /* cAA..AA Continue from address AA..AA(optional) */
438 /* try to read optional parameter, pc unchanged if no parm */
c906108c
SS
439 if (hexToInt(&ptr,&addr))
440 registers[ PC ] = addr;
441
104c1213 442 if (stepping) /* single-stepping */
c906108c
SS
443 {
444 if (!prepare_to_step(0)) /* set up for single-step */
445 {
446 /* prepare_to_step has already emulated the target insn:
447 Send SIGTRAP to gdb, don't resume the target at all. */
448 ptr = remcomOutBuffer;
449 *ptr++ = 'T'; /* Simulate stopping with SIGTRAP */
450 *ptr++ = '0';
451 *ptr++ = '5';
452
453 *ptr++ = hexchars[PC >> 4]; /* send PC */
454 *ptr++ = hexchars[PC & 0xf];
455 *ptr++ = ':';
456 ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0);
457 *ptr++ = ';';
458
459 *ptr++ = hexchars[R13 >> 4]; /* send FP */
460 *ptr++ = hexchars[R13 & 0xf];
461 *ptr++ = ':';
462 ptr = mem2hex((unsigned char *)&registers[R13], ptr, 4, 0);
463 *ptr++ = ';';
464
465 *ptr++ = hexchars[R15 >> 4]; /* send SP */
466 *ptr++ = hexchars[R15 & 0xf];
467 *ptr++ = ':';
468 ptr = mem2hex((unsigned char *)&registers[R15], ptr, 4, 0);
469 *ptr++ = ';';
470 *ptr++ = 0;
471
472 break;
473 }
474 }
475 else /* continuing, not single-stepping */
476 {
477 /* OK, about to do a "continue". First check to see if the
478 target pc is on an odd boundary (second instruction in the
479 word). If so, we must do a single-step first, because
480 ya can't jump or return back to an odd boundary! */
481 if ((registers[PC] & 2) != 0)
482 prepare_to_step(1);
483 }
7a292a7a 484
c906108c
SS
485 return;
486
487 case 'D': /* Detach */
7a292a7a 488#if 0
c906108c
SS
489 /* I am interpreting this to mean, release the board from control
490 by the remote stub. To do this, I am restoring the original
491 (or at least previous) exception vectors.
492 */
493 for (i = 0; i < 18; i++)
494 exceptionHandler (i, save_vectors[i]);
495 putpacket ("OK");
496 return; /* continue the inferior */
7a292a7a
SS
497#else
498 strcpy(remcomOutBuffer,"OK");
499 break;
500#endif
501 case 'q':
7a292a7a
SS
502 if (*ptr++ == 'C' &&
503 *ptr++ == 'R' &&
504 *ptr++ == 'C' &&
505 *ptr++ == ':')
506 {
507 unsigned long start, len, our_crc;
508
509 if (hexToInt (&ptr, (int *) &start) &&
510 *ptr++ == ',' &&
511 hexToInt (&ptr, (int *) &len))
512 {
513 remcomOutBuffer[0] = 'C';
514 our_crc = crc32 ((unsigned char *) start, len, 0xffffffff);
515 mem2hex ((char *) &our_crc,
516 &remcomOutBuffer[1],
517 sizeof (long),
518 0);
519 } /* else do nothing */
520 } /* else do nothing */
521 break;
c906108c
SS
522
523 case 'k': /* kill the program */
524 continue;
525 } /* switch */
526
527 /* reply to the request */
528 putpacket(remcomOutBuffer);
529 }
530}
531
7a292a7a
SS
532/* qCRC support */
533
534/* Table used by the crc32 function to calcuate the checksum. */
535static unsigned long crc32_table[256] = {0, 0};
536
537static unsigned long
fba45db2 538crc32 (unsigned char *buf, int len, unsigned long crc)
7a292a7a
SS
539{
540 if (! crc32_table[1])
541 {
542 /* Initialize the CRC table and the decoding table. */
543 int i, j;
544 unsigned long c;
545
546 for (i = 0; i < 256; i++)
547 {
548 for (c = i << 24, j = 8; j > 0; --j)
549 c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
550 crc32_table[i] = c;
551 }
552 }
553
554 while (len--)
555 {
556 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
557 buf++;
558 }
559 return crc;
560}
561
c906108c 562static int
fba45db2 563hex (unsigned char ch)
c906108c
SS
564{
565 if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
566 if ((ch >= '0') && (ch <= '9')) return (ch-'0');
567 if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
568 return (-1);
569}
570
571/* scan for the sequence $<data>#<checksum> */
572
104c1213 573unsigned char *
fba45db2 574getpacket (void)
c906108c 575{
d4f3574e 576 unsigned char *buffer = &remcomInBuffer[0];
c906108c
SS
577 unsigned char checksum;
578 unsigned char xmitcsum;
104c1213
JM
579 int count;
580 char ch;
581
582 while (1)
583 {
584 /* wait around for the start character, ignore all other characters */
585 while ((ch = getDebugChar ()) != '$')
586 ;
587
588retry:
589 checksum = 0;
590 xmitcsum = -1;
591 count = 0;
592
593 /* now, read until a # or end of buffer is found */
594 while (count < BUFMAX)
595 {
596 ch = getDebugChar ();
597 if (ch == '$')
598 goto retry;
599 if (ch == '#')
600 break;
601 checksum = checksum + ch;
602 buffer[count] = ch;
603 count = count + 1;
604 }
605 buffer[count] = 0;
606
607 if (ch == '#')
608 {
609 ch = getDebugChar ();
610 xmitcsum = hex (ch) << 4;
611 ch = getDebugChar ();
612 xmitcsum += hex (ch);
613
614 if (checksum != xmitcsum)
615 {
616 if (remote_debug)
617 {
618 unsigned char buf[16];
619
620 mem2hex((unsigned char *) &checksum, buf, 4, 0);
621 gdb_error("Bad checksum: my count = %s, ", buf);
622 mem2hex((unsigned char *) &xmitcsum, buf, 4, 0);
623 gdb_error("sent count = %s\n", buf);
624 gdb_error(" -- Bad buffer: \"%s\"\n", buffer);
625 }
626 putDebugChar ('-'); /* failed checksum */
627 }
628 else
629 {
630 putDebugChar ('+'); /* successful transfer */
631
632 /* if a sequence char is present, reply the sequence ID */
633 if (buffer[2] == ':')
634 {
635 putDebugChar (buffer[0]);
636 putDebugChar (buffer[1]);
637
638 return &buffer[3];
639 }
640
641 return &buffer[0];
642 }
c906108c 643 }
c906108c 644 }
c906108c
SS
645}
646
647/* send the packet in buffer. */
648
649static void
fba45db2 650putpacket (unsigned char *buffer)
c906108c
SS
651{
652 unsigned char checksum;
653 int count;
654 char ch;
655
656 /* $<packet info>#<checksum>. */
657 do {
658 putDebugChar('$');
659 checksum = 0;
660 count = 0;
661
662 while (ch=buffer[count]) {
663 putDebugChar(ch);
664 checksum += ch;
665 count += 1;
666 }
667 putDebugChar('#');
668 putDebugChar(hexchars[checksum >> 4]);
669 putDebugChar(hexchars[checksum % 16]);
670 } while (getDebugChar() != '+');
671}
672
673/* Address of a routine to RTE to if we get a memory fault. */
674
675static void (*volatile mem_fault_routine)() = 0;
676
677static void
fba45db2 678set_mem_err (void)
c906108c
SS
679{
680 mem_err = 1;
681}
682
683/* Check the address for safe access ranges. As currently defined,
684 this routine will reject the "expansion bus" address range(s).
685 To make those ranges useable, someone must implement code to detect
686 whether there's anything connected to the expansion bus. */
687
688static int
fba45db2 689mem_safe (unsigned char *addr)
c906108c
SS
690{
691#define BAD_RANGE_ONE_START ((unsigned char *) 0x600000)
692#define BAD_RANGE_ONE_END ((unsigned char *) 0xa00000)
693#define BAD_RANGE_TWO_START ((unsigned char *) 0xff680000)
694#define BAD_RANGE_TWO_END ((unsigned char *) 0xff800000)
695
696 if (addr < BAD_RANGE_ONE_START) return 1; /* safe */
697 if (addr < BAD_RANGE_ONE_END) return 0; /* unsafe */
698 if (addr < BAD_RANGE_TWO_START) return 1; /* safe */
699 if (addr < BAD_RANGE_TWO_END) return 0; /* unsafe */
700}
701
702/* These are separate functions so that they are so short and sweet
703 that the compiler won't save any registers (if there is a fault
704 to mem_fault, they won't get restored, so there better not be any
705 saved). */
706static int
fba45db2 707get_char (unsigned char *addr)
c906108c
SS
708{
709#if 1
710 if (mem_fault_routine && !mem_safe(addr))
711 {
712 mem_fault_routine ();
713 return 0;
714 }
715#endif
716 return *addr;
717}
718
719static void
fba45db2 720set_char (unsigned char *addr, unsigned char val)
c906108c
SS
721{
722#if 1
723 if (mem_fault_routine && !mem_safe (addr))
724 {
725 mem_fault_routine ();
726 return;
727 }
728#endif
729 *addr = val;
730}
731
732/* Convert the memory pointed to by mem into hex, placing result in buf.
733 Return a pointer to the last char put in buf (null).
734 If MAY_FAULT is non-zero, then we should set mem_err in response to
735 a fault; if zero treat a fault like any other fault in the stub. */
736
737static unsigned char *
fba45db2 738mem2hex (unsigned char *mem, unsigned char *buf, int count, int may_fault)
c906108c
SS
739{
740 int i;
741 unsigned char ch;
742
743 if (may_fault)
744 mem_fault_routine = set_mem_err;
745 for (i=0;i<count;i++) {
746 ch = get_char (mem++);
747 if (may_fault && mem_err)
748 return (buf);
749 *buf++ = hexchars[ch >> 4];
750 *buf++ = hexchars[ch % 16];
751 }
752 *buf = 0;
753 if (may_fault)
754 mem_fault_routine = 0;
755 return(buf);
756}
757
758/* Convert the hex array pointed to by buf into binary to be placed in mem.
759 Return a pointer to the character AFTER the last byte written. */
760
761static unsigned char*
fba45db2 762hex2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
c906108c
SS
763{
764 int i;
765 unsigned char ch;
766
767 if (may_fault)
768 mem_fault_routine = set_mem_err;
769 for (i=0;i<count;i++) {
770 ch = hex(*buf++) << 4;
771 ch = ch + hex(*buf++);
772 set_char (mem++, ch);
773 if (may_fault && mem_err)
774 return (mem);
775 }
776 if (may_fault)
777 mem_fault_routine = 0;
778 return(mem);
779}
780
781/* Convert the binary stream in BUF to memory.
782
783 Gdb will escape $, #, and the escape char (0x7d).
784 COUNT is the total number of bytes to write into
785 memory. */
786static unsigned char *
fba45db2 787bin2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
c906108c
SS
788{
789 int i;
790 unsigned char ch;
791
792 if (may_fault)
793 mem_fault_routine = set_mem_err;
794 for (i = 0; i < count; i++)
795 {
796 /* Check for any escaped characters. Be paranoid and
797 only unescape chars that should be escaped. */
798 if (*buf == 0x7d)
799 {
800 switch (*(buf+1))
801 {
802 case 0x3: /* # */
803 case 0x4: /* $ */
804 case 0x5d: /* escape char */
805 buf++;
7a292a7a 806 *buf |= 0x20;
c906108c
SS
807 break;
808 default:
809 /* nothing */
810 break;
811 }
812 }
813
814 set_char (mem++, *buf++);
815
816 if (may_fault && mem_err)
817 return mem;
818 }
819
820 if (may_fault)
821 mem_fault_routine = 0;
822 return mem;
823}
824
825/* this function takes the m32r exception vector and attempts to
826 translate this number into a unix compatible signal value */
827
828static int
fba45db2 829computeSignal (int exceptionVector)
c906108c
SS
830{
831 int sigval;
832 switch (exceptionVector) {
833 case 0 : sigval = 23; break; /* I/O trap */
834 case 1 : sigval = 5; break; /* breakpoint */
835 case 2 : sigval = 5; break; /* breakpoint */
836 case 3 : sigval = 5; break; /* breakpoint */
837 case 4 : sigval = 5; break; /* breakpoint */
838 case 5 : sigval = 5; break; /* breakpoint */
839 case 6 : sigval = 5; break; /* breakpoint */
840 case 7 : sigval = 5; break; /* breakpoint */
841 case 8 : sigval = 5; break; /* breakpoint */
842 case 9 : sigval = 5; break; /* breakpoint */
843 case 10 : sigval = 5; break; /* breakpoint */
844 case 11 : sigval = 5; break; /* breakpoint */
845 case 12 : sigval = 5; break; /* breakpoint */
846 case 13 : sigval = 5; break; /* breakpoint */
847 case 14 : sigval = 5; break; /* breakpoint */
848 case 15 : sigval = 5; break; /* breakpoint */
849 case 16 : sigval = 10; break; /* BUS ERROR (alignment) */
850 case 17 : sigval = 2; break; /* INTerrupt */
851 default : sigval = 7; break; /* "software generated" */
852 }
853 return (sigval);
854}
855
856/**********************************************/
857/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
858/* RETURN NUMBER OF CHARS PROCESSED */
859/**********************************************/
860static int
fba45db2 861hexToInt (unsigned char **ptr, int *intValue)
c906108c
SS
862{
863 int numChars = 0;
864 int hexValue;
865
866 *intValue = 0;
867 while (**ptr)
868 {
869 hexValue = hex(**ptr);
870 if (hexValue >=0)
871 {
872 *intValue = (*intValue <<4) | hexValue;
873 numChars ++;
874 }
875 else
876 break;
877 (*ptr)++;
878 }
879 return (numChars);
880}
881
882/*
883 Table of branch instructions:
884
885 10B6 RTE return from trap or exception
886 1FCr JMP jump
887 1ECr JL jump and link
888 7Fxx BRA branch
889 FFxxxxxx BRA branch (long)
890 B09rxxxx BNEZ branch not-equal-zero
891 Br1rxxxx BNE branch not-equal
892 7Dxx BNC branch not-condition
893 FDxxxxxx BNC branch not-condition (long)
894 B0Arxxxx BLTZ branch less-than-zero
895 B0Crxxxx BLEZ branch less-equal-zero
896 7Exx BL branch and link
897 FExxxxxx BL branch and link (long)
898 B0Drxxxx BGTZ branch greater-than-zero
899 B0Brxxxx BGEZ branch greater-equal-zero
900 B08rxxxx BEQZ branch equal-zero
901 Br0rxxxx BEQ branch equal
902 7Cxx BC branch condition
903 FCxxxxxx BC branch condition (long)
904 */
905
906static int
fba45db2 907isShortBranch (unsigned char *instr)
c906108c
SS
908{
909 unsigned char instr0 = instr[0] & 0x7F; /* mask off high bit */
910
911 if (instr0 == 0x10 && instr[1] == 0xB6) /* RTE */
912 return 1; /* return from trap or exception */
913
914 if (instr0 == 0x1E || instr0 == 0x1F) /* JL or JMP */
915 if ((instr[1] & 0xF0) == 0xC0)
916 return 2; /* jump thru a register */
917
918 if (instr0 == 0x7C || instr0 == 0x7D || /* BC, BNC, BL, BRA */
919 instr0 == 0x7E || instr0 == 0x7F)
920 return 3; /* eight bit PC offset */
921
922 return 0;
923}
924
925static int
fba45db2 926isLongBranch (unsigned char *instr)
c906108c
SS
927{
928 if (instr[0] == 0xFC || instr[0] == 0xFD || /* BRA, BNC, BL, BC */
929 instr[0] == 0xFE || instr[0] == 0xFF) /* 24 bit relative */
930 return 4;
931 if ((instr[0] & 0xF0) == 0xB0) /* 16 bit relative */
932 {
933 if ((instr[1] & 0xF0) == 0x00 || /* BNE, BEQ */
934 (instr[1] & 0xF0) == 0x10)
935 return 5;
936 if (instr[0] == 0xB0) /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
937 if ((instr[1] & 0xF0) == 0x80 || (instr[1] & 0xF0) == 0x90 ||
938 (instr[1] & 0xF0) == 0xA0 || (instr[1] & 0xF0) == 0xB0 ||
939 (instr[1] & 0xF0) == 0xC0 || (instr[1] & 0xF0) == 0xD0)
940 return 6;
941 }
942 return 0;
943}
944
945/* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
946 then it's a 2-byte instruction, else it's a 4-byte instruction. */
947
948#define INSTRUCTION_SIZE(addr) \
949 ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
950
951static int
fba45db2 952isBranch (unsigned char *instr)
c906108c
SS
953{
954 if (INSTRUCTION_SIZE(instr) == 2)
955 return isShortBranch(instr);
956 else
957 return isLongBranch(instr);
958}
959
960static int
fba45db2 961willBranch (unsigned char *instr, int branchCode)
c906108c
SS
962{
963 switch (branchCode)
964 {
965 case 0: return 0; /* not a branch */
966 case 1: return 1; /* RTE */
967 case 2: return 1; /* JL or JMP */
968 case 3: /* BC, BNC, BL, BRA (short) */
969 case 4: /* BC, BNC, BL, BRA (long) */
970 switch (instr[0] & 0x0F)
971 {
972 case 0xC: /* Branch if Condition Register */
973 return (registers[CBR] != 0);
974 case 0xD: /* Branch if NOT Condition Register */
975 return (registers[CBR] == 0);
976 case 0xE: /* Branch and Link */
977 case 0xF: /* Branch (unconditional) */
978 return 1;
979 default: /* oops? */
980 return 0;
981 }
982 case 5: /* BNE, BEQ */
983 switch (instr[1] & 0xF0)
984 {
985 case 0x00: /* Branch if r1 equal to r2 */
986 return (registers[instr[0] & 0x0F] == registers[instr[1] & 0x0F]);
987 case 0x10: /* Branch if r1 NOT equal to r2 */
988 return (registers[instr[0] & 0x0F] != registers[instr[1] & 0x0F]);
989 default: /* oops? */
990 return 0;
991 }
992 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
993 switch (instr[1] & 0xF0)
994 {
995 case 0x80: /* Branch if reg equal to zero */
996 return (registers[instr[1] & 0x0F] == 0);
997 case 0x90: /* Branch if reg NOT equal to zero */
998 return (registers[instr[1] & 0x0F] != 0);
999 case 0xA0: /* Branch if reg less than zero */
1000 return (registers[instr[1] & 0x0F] < 0);
1001 case 0xB0: /* Branch if reg greater or equal to zero */
1002 return (registers[instr[1] & 0x0F] >= 0);
1003 case 0xC0: /* Branch if reg less than or equal to zero */
1004 return (registers[instr[1] & 0x0F] <= 0);
1005 case 0xD0: /* Branch if reg greater than zero */
1006 return (registers[instr[1] & 0x0F] > 0);
1007 default: /* oops? */
1008 return 0;
1009 }
1010 default: /* oops? */
1011 return 0;
1012 }
1013}
1014
1015static int
fba45db2 1016branchDestination (unsigned char *instr, int branchCode)
c906108c
SS
1017{
1018 switch (branchCode) {
1019 default:
1020 case 0: /* not a branch */
1021 return 0;
1022 case 1: /* RTE */
1023 return registers[BPC] & ~3; /* pop BPC into PC */
1024 case 2: /* JL or JMP */
1025 return registers[instr[1] & 0x0F] & ~3; /* jump thru a register */
1026 case 3: /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
7a292a7a 1027 return (((int) instr) & ~3) + ((char) instr[1] << 2);
c906108c
SS
1028 case 4: /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
1029 return ((int) instr +
7a292a7a 1030 ((((char) instr[1] << 16) | (instr[2] << 8) | (instr[3])) << 2));
c906108c
SS
1031 case 5: /* BNE, BEQ (16-bit relative offset) */
1032 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
7a292a7a 1033 return ((int) instr + ((((char) instr[2] << 8) | (instr[3])) << 2));
c906108c
SS
1034 }
1035
1036 /* An explanatory note: in the last three return expressions, I have
1037 cast the most-significant byte of the return offset to char.
1038 What this accomplishes is sign extension. If the other
1039 less-significant bytes were signed as well, they would get sign
1040 extended too and, if negative, their leading bits would clobber
1041 the bits of the more-significant bytes ahead of them. There are
1042 other ways I could have done this, but sign extension from
1043 odd-sized integers is always a pain. */
1044}
1045
1046static void
fba45db2 1047branchSideEffects (unsigned char *instr, int branchCode)
c906108c
SS
1048{
1049 switch (branchCode)
1050 {
1051 case 1: /* RTE */
1052 return; /* I <THINK> this is already handled... */
1053 case 2: /* JL (or JMP) */
1054 case 3: /* BL (or BC, BNC, BRA) */
1055 case 4:
1056 if ((instr[0] & 0x0F) == 0x0E) /* branch/jump and link */
1057 registers[R14] = (registers[PC] & ~3) + 4;
1058 return;
1059 default: /* any other branch has no side effects */
1060 return;
1061 }
1062}
1063
1064static struct STEPPING_CONTEXT {
1065 int stepping; /* true when we've started a single-step */
1066 unsigned long target_addr; /* the instr we're trying to execute */
1067 unsigned long target_size; /* the size of the target instr */
1068 unsigned long noop_addr; /* where we've inserted a no-op, if any */
1069 unsigned long trap1_addr; /* the trap following the target instr */
1070 unsigned long trap2_addr; /* the trap at a branch destination, if any */
1071 unsigned short noop_save; /* instruction overwritten by our no-op */
1072 unsigned short trap1_save; /* instruction overwritten by trap1 */
1073 unsigned short trap2_save; /* instruction overwritten by trap2 */
1074 unsigned short continue_p; /* true if NOT returning to gdb after step */
1075} stepping;
1076
1077/* Function: prepare_to_step
1078 Called from handle_exception to prepare the user program to single-step.
1079 Places a trap instruction after the target instruction, with special
1080 extra handling for branch instructions and for instructions in the
1081 second half-word of a word.
1082
1083 Returns: True if we should actually execute the instruction;
1084 False if we are going to emulate executing the instruction,
1085 in which case we simply report to GDB that the instruction
1086 has already been executed. */
1087
1088#define TRAP1 0x10f1; /* trap #1 instruction */
1089#define NOOP 0x7000; /* noop instruction */
1090
1091static unsigned short trap1 = TRAP1;
1092static unsigned short noop = NOOP;
1093
1094static int
1095prepare_to_step(continue_p)
1096 int continue_p; /* if this isn't REALLY a single-step (see below) */
1097{
1098 unsigned long pc = registers[PC];
1099 int branchCode = isBranch((unsigned char *) pc);
1100 unsigned char *p;
1101
1102 /* zero out the stepping context
1103 (paranoia -- it should already be zeroed) */
1104 for (p = (unsigned char *) &stepping;
1105 p < ((unsigned char *) &stepping) + sizeof(stepping);
1106 p++)
1107 *p = 0;
1108
1109 if (branchCode != 0) /* next instruction is a branch */
1110 {
1111 branchSideEffects((unsigned char *) pc, branchCode);
1112 if (willBranch((unsigned char *)pc, branchCode))
1113 registers[PC] = branchDestination((unsigned char *) pc, branchCode);
1114 else
1115 registers[PC] = pc + INSTRUCTION_SIZE(pc);
1116 return 0; /* branch "executed" -- just notify GDB */
1117 }
1118 else if (((int) pc & 2) != 0) /* "second-slot" instruction */
1119 {
1120 /* insert no-op before pc */
1121 stepping.noop_addr = pc - 2;
1122 stepping.noop_save = *(unsigned short *) stepping.noop_addr;
1123 *(unsigned short *) stepping.noop_addr = noop;
1124 /* insert trap after pc */
1125 stepping.trap1_addr = pc + 2;
1126 stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
1127 *(unsigned short *) stepping.trap1_addr = trap1;
1128 }
1129 else /* "first-slot" instruction */
1130 {
1131 /* insert trap after pc */
1132 stepping.trap1_addr = pc + INSTRUCTION_SIZE(pc);
1133 stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
1134 *(unsigned short *) stepping.trap1_addr = trap1;
1135 }
1136 /* "continue_p" means that we are actually doing a continue, and not
1137 being requested to single-step by GDB. Sometimes we have to do
1138 one single-step before continuing, because the PC is on a half-word
1139 boundary. There's no way to simply resume at such an address. */
1140 stepping.continue_p = continue_p;
1141 stepping.stepping = 1; /* starting a single-step */
1142 return 1;
1143}
1144
1145/* Function: finish_from_step
1146 Called from handle_exception to finish up when the user program
1147 returns from a single-step. Replaces the instructions that had
1148 been overwritten by traps or no-ops,
1149
1150 Returns: True if we should notify GDB that the target stopped.
1151 False if we only single-stepped because we had to before we
1152 could continue (ie. we were trying to continue at a
1153 half-word boundary). In that case don't notify GDB:
1154 just "continue continuing". */
1155
1156static int
fba45db2 1157finish_from_step (void)
c906108c
SS
1158{
1159 if (stepping.stepping) /* anything to do? */
1160 {
1161 int continue_p = stepping.continue_p;
1162 unsigned char *p;
1163
1164 if (stepping.noop_addr) /* replace instr "under" our no-op */
1165 *(unsigned short *) stepping.noop_addr = stepping.noop_save;
1166 if (stepping.trap1_addr) /* replace instr "under" our trap */
1167 *(unsigned short *) stepping.trap1_addr = stepping.trap1_save;
1168 if (stepping.trap2_addr) /* ditto our other trap, if any */
1169 *(unsigned short *) stepping.trap2_addr = stepping.trap2_save;
1170
1171 for (p = (unsigned char *) &stepping; /* zero out the stepping context */
1172 p < ((unsigned char *) &stepping) + sizeof(stepping);
1173 p++)
1174 *p = 0;
1175
1176 return !(continue_p);
1177 }
1178 else /* we didn't single-step, therefore this must be a legitimate stop */
1179 return 1;
1180}
1181
1182struct PSWreg { /* separate out the bit flags in the PSW register */
1183 int pad1 : 16;
1184 int bsm : 1;
1185 int bie : 1;
1186 int pad2 : 5;
1187 int bc : 1;
1188 int sm : 1;
1189 int ie : 1;
1190 int pad3 : 5;
1191 int c : 1;
1192} *psw;
1193
1194/* Upon entry the value for LR to save has been pushed.
1195 We unpush that so that the value for the stack pointer saved is correct.
1196 Upon entry, all other registers are assumed to have not been modified
1197 since the interrupt/trap occured. */
1198
1199asm ("
1200stash_registers:
1201 push r0
1202 push r1
1203 seth r1, #shigh(registers)
1204 add3 r1, r1, #low(registers)
1205 pop r0 ; r1
1206 st r0, @(4,r1)
1207 pop r0 ; r0
1208 st r0, @r1
1209 addi r1, #4 ; only add 4 as subsequent saves are `pre inc'
1210 st r2, @+r1
1211 st r3, @+r1
1212 st r4, @+r1
1213 st r5, @+r1
1214 st r6, @+r1
1215 st r7, @+r1
1216 st r8, @+r1
1217 st r9, @+r1
1218 st r10, @+r1
1219 st r11, @+r1
1220 st r12, @+r1
1221 st r13, @+r1 ; fp
1222 pop r0 ; lr (r14)
1223 st r0, @+r1
1224 st sp, @+r1 ; sp contains right value at this point
1225 mvfc r0, cr0
1226 st r0, @+r1 ; cr0 == PSW
1227 mvfc r0, cr1
1228 st r0, @+r1 ; cr1 == CBR
1229 mvfc r0, cr2
1230 st r0, @+r1 ; cr2 == SPI
1231 mvfc r0, cr3
1232 st r0, @+r1 ; cr3 == SPU
1233 mvfc r0, cr6
1234 st r0, @+r1 ; cr6 == BPC
1235 st r0, @+r1 ; PC == BPC
1236 mvfaclo r0
1237 st r0, @+r1 ; ACCL
1238 mvfachi r0
1239 st r0, @+r1 ; ACCH
1240 jmp lr");
1241
1242/* C routine to clean up what stash_registers did.
1243 It is called after calling stash_registers.
1244 This is separate from stash_registers as we want to do this in C
1245 but doing stash_registers in C isn't straightforward. */
1246
1247static void
fba45db2 1248cleanup_stash (void)
c906108c
SS
1249{
1250 psw = (struct PSWreg *) &registers[PSW]; /* fields of PSW register */
1251 psw->sm = psw->bsm; /* fix up pre-trap values of psw fields */
1252 psw->ie = psw->bie;
1253 psw->c = psw->bc;
1254 registers[CBR] = psw->bc; /* fix up pre-trap "C" register */
1255
1256#if 0 /* FIXME: Was in previous version. Necessary?
1257 (Remember that we use the "rte" insn to return from the
1258 trap/interrupt so the values of bsm, bie, bc are important. */
1259 psw->bsm = psw->bie = psw->bc = 0; /* zero post-trap values */
1260#endif
1261
1262 /* FIXME: Copied from previous version. This can probably be deleted
1263 since methinks stash_registers has already done this. */
1264 registers[PC] = registers[BPC]; /* pre-trap PC */
1265
1266 /* FIXME: Copied from previous version. Necessary? */
1267 if (psw->sm) /* copy R15 into (psw->sm ? SPU : SPI) */
1268 registers[SPU] = registers[R15];
1269 else
1270 registers[SPI] = registers[R15];
1271}
1272
1273asm ("
1274restore_and_return:
1275 seth r0, #shigh(registers+8)
1276 add3 r0, r0, #low(registers+8)
1277 ld r2, @r0+ ; restore r2
1278 ld r3, @r0+ ; restore r3
1279 ld r4, @r0+ ; restore r4
1280 ld r5, @r0+ ; restore r5
1281 ld r6, @r0+ ; restore r6
1282 ld r7, @r0+ ; restore r7
1283 ld r8, @r0+ ; restore r8
1284 ld r9, @r0+ ; restore r9
1285 ld r10, @r0+ ; restore r10
1286 ld r11, @r0+ ; restore r11
1287 ld r12, @r0+ ; restore r12
1288 ld r13, @r0+ ; restore r13
1289 ld r14, @r0+ ; restore r14
1290 ld r15, @r0+ ; restore r15
1291 ld r1, @r0+ ; restore cr0 == PSW
1292 mvtc r1, cr0
1293 ld r1, @r0+ ; restore cr1 == CBR (no-op, because it's read only)
1294 mvtc r1, cr1
1295 ld r1, @r0+ ; restore cr2 == SPI
1296 mvtc r1, cr2
1297 ld r1, @r0+ ; restore cr3 == SPU
1298 mvtc r1, cr3
1299 addi r0, #4 ; skip BPC
1300 ld r1, @r0+ ; restore cr6 (BPC) == PC
1301 mvtc r1, cr6
1302 ld r1, @r0+ ; restore ACCL
1303 mvtaclo r1
1304 ld r1, @r0+ ; restore ACCH
1305 mvtachi r1
1306 seth r0, #shigh(registers)
1307 add3 r0, r0, #low(registers)
1308 ld r1, @(4,r0) ; restore r1
1309 ld r0, @r0 ; restore r0
1310 rte");
1311
1312/* General trap handler, called after the registers have been stashed.
1313 NUM is the trap/exception number. */
1314
1315static void
fba45db2 1316process_exception (int num)
c906108c
SS
1317{
1318 cleanup_stash ();
1319 asm volatile ("
1320 seth r1, #shigh(stackPtr)
1321 add3 r1, r1, #low(stackPtr)
1322 ld r15, @r1 ; setup local stack (protect user stack)
1323 mv r0, %0
1324 bl handle_exception
1325 bl restore_and_return"
1326 : : "r" (num) : "r0", "r1");
1327}
1328
1329void _catchException0 ();
1330
1331asm ("
1332_catchException0:
1333 push lr
1334 bl stash_registers
1335 ; Note that at this point the pushed value of `lr' has been popped
1336 ldi r0, #0
1337 bl process_exception");
1338
1339void _catchException1 ();
1340
1341asm ("
1342_catchException1:
1343 push lr
1344 bl stash_registers
1345 ; Note that at this point the pushed value of `lr' has been popped
1346 bl cleanup_stash
1347 seth r1, #shigh(stackPtr)
1348 add3 r1, r1, #low(stackPtr)
1349 ld r15, @r1 ; setup local stack (protect user stack)
1350 seth r1, #shigh(registers + 21*4) ; PC
1351 add3 r1, r1, #low(registers + 21*4)
1352 ld r0, @r1
1353 addi r0, #-4 ; back up PC for breakpoint trap.
1354 st r0, @r1 ; FIXME: what about bp in right slot?
1355 ldi r0, #1
1356 bl handle_exception
1357 bl restore_and_return");
1358
1359void _catchException2 ();
1360
1361asm ("
1362_catchException2:
1363 push lr
1364 bl stash_registers
1365 ; Note that at this point the pushed value of `lr' has been popped
1366 ldi r0, #2
1367 bl process_exception");
1368
1369void _catchException3 ();
1370
1371asm ("
1372_catchException3:
1373 push lr
1374 bl stash_registers
1375 ; Note that at this point the pushed value of `lr' has been popped
1376 ldi r0, #3
1377 bl process_exception");
1378
1379void _catchException4 ();
1380
1381asm ("
1382_catchException4:
1383 push lr
1384 bl stash_registers
1385 ; Note that at this point the pushed value of `lr' has been popped
1386 ldi r0, #4
1387 bl process_exception");
1388
1389void _catchException5 ();
1390
1391asm ("
1392_catchException5:
1393 push lr
1394 bl stash_registers
1395 ; Note that at this point the pushed value of `lr' has been popped
1396 ldi r0, #5
1397 bl process_exception");
1398
1399void _catchException6 ();
1400
1401asm ("
1402_catchException6:
1403 push lr
1404 bl stash_registers
1405 ; Note that at this point the pushed value of `lr' has been popped
1406 ldi r0, #6
1407 bl process_exception");
1408
1409void _catchException7 ();
1410
1411asm ("
1412_catchException7:
1413 push lr
1414 bl stash_registers
1415 ; Note that at this point the pushed value of `lr' has been popped
1416 ldi r0, #7
1417 bl process_exception");
1418
1419void _catchException8 ();
1420
1421asm ("
1422_catchException8:
1423 push lr
1424 bl stash_registers
1425 ; Note that at this point the pushed value of `lr' has been popped
1426 ldi r0, #8
1427 bl process_exception");
1428
1429void _catchException9 ();
1430
1431asm ("
1432_catchException9:
1433 push lr
1434 bl stash_registers
1435 ; Note that at this point the pushed value of `lr' has been popped
1436 ldi r0, #9
1437 bl process_exception");
1438
1439void _catchException10 ();
1440
1441asm ("
1442_catchException10:
1443 push lr
1444 bl stash_registers
1445 ; Note that at this point the pushed value of `lr' has been popped
1446 ldi r0, #10
1447 bl process_exception");
1448
1449void _catchException11 ();
1450
1451asm ("
1452_catchException11:
1453 push lr
1454 bl stash_registers
1455 ; Note that at this point the pushed value of `lr' has been popped
1456 ldi r0, #11
1457 bl process_exception");
1458
1459void _catchException12 ();
1460
1461asm ("
1462_catchException12:
1463 push lr
1464 bl stash_registers
1465 ; Note that at this point the pushed value of `lr' has been popped
1466 ldi r0, #12
1467 bl process_exception");
1468
1469void _catchException13 ();
1470
1471asm ("
1472_catchException13:
1473 push lr
1474 bl stash_registers
1475 ; Note that at this point the pushed value of `lr' has been popped
1476 ldi r0, #13
1477 bl process_exception");
1478
1479void _catchException14 ();
1480
1481asm ("
1482_catchException14:
1483 push lr
1484 bl stash_registers
1485 ; Note that at this point the pushed value of `lr' has been popped
1486 ldi r0, #14
1487 bl process_exception");
1488
1489void _catchException15 ();
1490
1491asm ("
1492_catchException15:
1493 push lr
1494 bl stash_registers
1495 ; Note that at this point the pushed value of `lr' has been popped
1496 ldi r0, #15
1497 bl process_exception");
1498
1499void _catchException16 ();
1500
1501asm ("
1502_catchException16:
1503 push lr
1504 bl stash_registers
1505 ; Note that at this point the pushed value of `lr' has been popped
1506 ldi r0, #16
1507 bl process_exception");
1508
1509void _catchException17 ();
1510
1511asm ("
1512_catchException17:
1513 push lr
1514 bl stash_registers
1515 ; Note that at this point the pushed value of `lr' has been popped
1516 ldi r0, #17
1517 bl process_exception");
1518
1519
1520/* this function is used to set up exception handlers for tracing and
1521 breakpoints */
1522void
fba45db2 1523set_debug_traps (void)
c906108c
SS
1524{
1525 /* extern void remcomHandler(); */
1526 int i;
1527
1528 for (i = 0; i < 18; i++) /* keep a copy of old vectors */
1529 if (save_vectors[i] == 0) /* only copy them the first time */
1530 save_vectors[i] = getExceptionHandler (i);
1531
1532 stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
1533
1534 exceptionHandler (0, _catchException0);
1535 exceptionHandler (1, _catchException1);
1536 exceptionHandler (2, _catchException2);
1537 exceptionHandler (3, _catchException3);
1538 exceptionHandler (4, _catchException4);
1539 exceptionHandler (5, _catchException5);
1540 exceptionHandler (6, _catchException6);
1541 exceptionHandler (7, _catchException7);
1542 exceptionHandler (8, _catchException8);
1543 exceptionHandler (9, _catchException9);
1544 exceptionHandler (10, _catchException10);
1545 exceptionHandler (11, _catchException11);
1546 exceptionHandler (12, _catchException12);
1547 exceptionHandler (13, _catchException13);
1548 exceptionHandler (14, _catchException14);
1549 exceptionHandler (15, _catchException15);
1550 exceptionHandler (16, _catchException16);
1551 /* exceptionHandler (17, _catchException17); */
1552
c906108c
SS
1553 initialized = 1;
1554}
1555
1556/* This function will generate a breakpoint exception. It is used at the
1557 beginning of a program to sync up with a debugger and can be used
1558 otherwise as a quick means to stop program execution and "break" into
1559 the debugger. */
1560
1561#define BREAKPOINT() asm volatile (" trap #2");
1562
1563void
fba45db2 1564breakpoint (void)
c906108c
SS
1565{
1566 if (initialized)
1567 BREAKPOINT();
1568}
1569
1570/* STDOUT section:
1571 Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
1572 Functions: gdb_putchar(char ch)
1573 gdb_puts(char *str)
1574 gdb_write(char *str, int len)
1575 gdb_error(char *format, char *parm)
1576 */
1577
1578/* Function: gdb_putchar(int)
1579 Make gdb write a char to stdout.
1580 Returns: the char */
1581
1582static int
fba45db2 1583gdb_putchar (int ch)
c906108c
SS
1584{
1585 char buf[4];
1586
1587 buf[0] = 'O';
1588 buf[1] = hexchars[ch >> 4];
1589 buf[2] = hexchars[ch & 0x0F];
1590 buf[3] = 0;
1591 putpacket(buf);
1592 return ch;
1593}
1594
1595/* Function: gdb_write(char *, int)
1596 Make gdb write n bytes to stdout (not assumed to be null-terminated).
1597 Returns: number of bytes written */
1598
1599static int
fba45db2 1600gdb_write (char *data, int len)
c906108c
SS
1601{
1602 char *buf, *cpy;
1603 int i;
1604
1605 buf = remcomOutBuffer;
1606 buf[0] = 'O';
1607 i = 0;
1608 while (i < len)
1609 {
1610 for (cpy = buf+1;
1611 i < len && cpy < buf + sizeof(remcomOutBuffer) - 3;
1612 i++)
1613 {
1614 *cpy++ = hexchars[data[i] >> 4];
1615 *cpy++ = hexchars[data[i] & 0x0F];
1616 }
1617 *cpy = 0;
1618 putpacket(buf);
1619 }
1620 return len;
1621}
1622
1623/* Function: gdb_puts(char *)
1624 Make gdb write a null-terminated string to stdout.
1625 Returns: the length of the string */
1626
1627static int
fba45db2 1628gdb_puts (char *str)
c906108c
SS
1629{
1630 return gdb_write(str, strlen(str));
1631}
1632
1633/* Function: gdb_error(char *, char *)
1634 Send an error message to gdb's stdout.
1635 First string may have 1 (one) optional "%s" in it, which
1636 will cause the optional second string to be inserted. */
1637
1638static void
fba45db2 1639gdb_error (char *format, char *parm)
c906108c
SS
1640{
1641 char buf[400], *cpy;
1642 int len;
1643
1644 if (remote_debug)
1645 {
1646 if (format && *format)
1647 len = strlen(format);
1648 else
1649 return; /* empty input */
1650
1651 if (parm && *parm)
1652 len += strlen(parm);
1653
1654 for (cpy = buf; *format; )
1655 {
1656 if (format[0] == '%' && format[1] == 's') /* include second string */
1657 {
1658 format += 2; /* advance two chars instead of just one */
1659 while (parm && *parm)
1660 *cpy++ = *parm++;
1661 }
1662 else
1663 *cpy++ = *format++;
1664 }
1665 *cpy = '\0';
1666 gdb_puts(buf);
1667 }
1668}
1669
1670static unsigned char *
1671strcpy (unsigned char *dest, const unsigned char *src)
1672{
1673 unsigned char *ret = dest;
1674
1675 if (dest && src)
1676 {
1677 while (*src)
1678 *dest++ = *src++;
1679 *dest = 0;
1680 }
1681 return ret;
1682}
1683
1684static int
1685strlen (const unsigned char *src)
1686{
1687 int ret;
1688
1689 for (ret = 0; *src; src++)
1690 ret++;
1691
1692 return ret;
1693}
1694
1695#if 0
1696void exit (code)
1697 int code;
1698{
1699 _exit (code);
1700}
1701
1702int atexit (void *p)
1703{
1704 return 0;
1705}
1706
1707void abort (void)
1708{
1709 _exit (1);
1710}
1711#endif
This page took 0.194718 seconds and 4 git commands to generate.