import gdb-1999-08-30 snapshot
[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 *);
104c1213 182static unsigned char *getpacket(unsigned char *);
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;
104c1213 313 ptr = getpacket(remcomInBuffer);
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 }
428 strcpy (remcomOutBuffer, "P01");
429 break;
430 }
431 case 'G': /* set the value of the CPU registers - return OK */
104c1213 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
538crc32 (buf, len, crc)
539 unsigned char *buf;
540 int len;
541 unsigned long crc;
542{
543 if (! crc32_table[1])
544 {
545 /* Initialize the CRC table and the decoding table. */
546 int i, j;
547 unsigned long c;
548
549 for (i = 0; i < 256; i++)
550 {
551 for (c = i << 24, j = 8; j > 0; --j)
552 c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
553 crc32_table[i] = c;
554 }
555 }
556
557 while (len--)
558 {
559 crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
560 buf++;
561 }
562 return crc;
563}
564
c906108c
SS
565static int
566hex(ch)
567 unsigned char ch;
568{
569 if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
570 if ((ch >= '0') && (ch <= '9')) return (ch-'0');
571 if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
572 return (-1);
573}
574
575/* scan for the sequence $<data>#<checksum> */
576
104c1213
JM
577unsigned char *
578getpacket (buffer)
579 unsigned char *buffer;
c906108c
SS
580{
581 unsigned char checksum;
582 unsigned char xmitcsum;
104c1213
JM
583 int count;
584 char ch;
585
586 while (1)
587 {
588 /* wait around for the start character, ignore all other characters */
589 while ((ch = getDebugChar ()) != '$')
590 ;
591
592retry:
593 checksum = 0;
594 xmitcsum = -1;
595 count = 0;
596
597 /* now, read until a # or end of buffer is found */
598 while (count < BUFMAX)
599 {
600 ch = getDebugChar ();
601 if (ch == '$')
602 goto retry;
603 if (ch == '#')
604 break;
605 checksum = checksum + ch;
606 buffer[count] = ch;
607 count = count + 1;
608 }
609 buffer[count] = 0;
610
611 if (ch == '#')
612 {
613 ch = getDebugChar ();
614 xmitcsum = hex (ch) << 4;
615 ch = getDebugChar ();
616 xmitcsum += hex (ch);
617
618 if (checksum != xmitcsum)
619 {
620 if (remote_debug)
621 {
622 unsigned char buf[16];
623
624 mem2hex((unsigned char *) &checksum, buf, 4, 0);
625 gdb_error("Bad checksum: my count = %s, ", buf);
626 mem2hex((unsigned char *) &xmitcsum, buf, 4, 0);
627 gdb_error("sent count = %s\n", buf);
628 gdb_error(" -- Bad buffer: \"%s\"\n", buffer);
629 }
630 putDebugChar ('-'); /* failed checksum */
631 }
632 else
633 {
634 putDebugChar ('+'); /* successful transfer */
635
636 /* if a sequence char is present, reply the sequence ID */
637 if (buffer[2] == ':')
638 {
639 putDebugChar (buffer[0]);
640 putDebugChar (buffer[1]);
641
642 return &buffer[3];
643 }
644
645 return &buffer[0];
646 }
c906108c 647 }
c906108c 648 }
c906108c
SS
649}
650
651/* send the packet in buffer. */
652
653static void
654putpacket(buffer)
655 unsigned char *buffer;
656{
657 unsigned char checksum;
658 int count;
659 char ch;
660
661 /* $<packet info>#<checksum>. */
662 do {
663 putDebugChar('$');
664 checksum = 0;
665 count = 0;
666
667 while (ch=buffer[count]) {
668 putDebugChar(ch);
669 checksum += ch;
670 count += 1;
671 }
672 putDebugChar('#');
673 putDebugChar(hexchars[checksum >> 4]);
674 putDebugChar(hexchars[checksum % 16]);
675 } while (getDebugChar() != '+');
676}
677
678/* Address of a routine to RTE to if we get a memory fault. */
679
680static void (*volatile mem_fault_routine)() = 0;
681
682static void
683set_mem_err ()
684{
685 mem_err = 1;
686}
687
688/* Check the address for safe access ranges. As currently defined,
689 this routine will reject the "expansion bus" address range(s).
690 To make those ranges useable, someone must implement code to detect
691 whether there's anything connected to the expansion bus. */
692
693static int
694mem_safe (addr)
695 unsigned char *addr;
696{
697#define BAD_RANGE_ONE_START ((unsigned char *) 0x600000)
698#define BAD_RANGE_ONE_END ((unsigned char *) 0xa00000)
699#define BAD_RANGE_TWO_START ((unsigned char *) 0xff680000)
700#define BAD_RANGE_TWO_END ((unsigned char *) 0xff800000)
701
702 if (addr < BAD_RANGE_ONE_START) return 1; /* safe */
703 if (addr < BAD_RANGE_ONE_END) return 0; /* unsafe */
704 if (addr < BAD_RANGE_TWO_START) return 1; /* safe */
705 if (addr < BAD_RANGE_TWO_END) return 0; /* unsafe */
706}
707
708/* These are separate functions so that they are so short and sweet
709 that the compiler won't save any registers (if there is a fault
710 to mem_fault, they won't get restored, so there better not be any
711 saved). */
712static int
713get_char (addr)
714 unsigned char *addr;
715{
716#if 1
717 if (mem_fault_routine && !mem_safe(addr))
718 {
719 mem_fault_routine ();
720 return 0;
721 }
722#endif
723 return *addr;
724}
725
726static void
727set_char (addr, val)
728 unsigned char *addr;
729 unsigned char val;
730{
731#if 1
732 if (mem_fault_routine && !mem_safe (addr))
733 {
734 mem_fault_routine ();
735 return;
736 }
737#endif
738 *addr = val;
739}
740
741/* Convert the memory pointed to by mem into hex, placing result in buf.
742 Return a pointer to the last char put in buf (null).
743 If MAY_FAULT is non-zero, then we should set mem_err in response to
744 a fault; if zero treat a fault like any other fault in the stub. */
745
746static unsigned char *
747mem2hex(mem, buf, count, may_fault)
748 unsigned char* mem;
749 unsigned char* buf;
750 int count;
751 int may_fault;
752{
753 int i;
754 unsigned char ch;
755
756 if (may_fault)
757 mem_fault_routine = set_mem_err;
758 for (i=0;i<count;i++) {
759 ch = get_char (mem++);
760 if (may_fault && mem_err)
761 return (buf);
762 *buf++ = hexchars[ch >> 4];
763 *buf++ = hexchars[ch % 16];
764 }
765 *buf = 0;
766 if (may_fault)
767 mem_fault_routine = 0;
768 return(buf);
769}
770
771/* Convert the hex array pointed to by buf into binary to be placed in mem.
772 Return a pointer to the character AFTER the last byte written. */
773
774static unsigned char*
775hex2mem(buf, mem, count, may_fault)
776 unsigned char* buf;
777 unsigned char* mem;
778 int count;
779 int may_fault;
780{
781 int i;
782 unsigned char ch;
783
784 if (may_fault)
785 mem_fault_routine = set_mem_err;
786 for (i=0;i<count;i++) {
787 ch = hex(*buf++) << 4;
788 ch = ch + hex(*buf++);
789 set_char (mem++, ch);
790 if (may_fault && mem_err)
791 return (mem);
792 }
793 if (may_fault)
794 mem_fault_routine = 0;
795 return(mem);
796}
797
798/* Convert the binary stream in BUF to memory.
799
800 Gdb will escape $, #, and the escape char (0x7d).
801 COUNT is the total number of bytes to write into
802 memory. */
803static unsigned char *
804bin2mem (buf, mem, count, may_fault)
805 unsigned char *buf;
806 unsigned char *mem;
807 int count;
808 int may_fault;
809{
810 int i;
811 unsigned char ch;
812
813 if (may_fault)
814 mem_fault_routine = set_mem_err;
815 for (i = 0; i < count; i++)
816 {
817 /* Check for any escaped characters. Be paranoid and
818 only unescape chars that should be escaped. */
819 if (*buf == 0x7d)
820 {
821 switch (*(buf+1))
822 {
823 case 0x3: /* # */
824 case 0x4: /* $ */
825 case 0x5d: /* escape char */
826 buf++;
7a292a7a 827 *buf |= 0x20;
c906108c
SS
828 break;
829 default:
830 /* nothing */
831 break;
832 }
833 }
834
835 set_char (mem++, *buf++);
836
837 if (may_fault && mem_err)
838 return mem;
839 }
840
841 if (may_fault)
842 mem_fault_routine = 0;
843 return mem;
844}
845
846/* this function takes the m32r exception vector and attempts to
847 translate this number into a unix compatible signal value */
848
849static int
850computeSignal(exceptionVector)
851 int exceptionVector;
852{
853 int sigval;
854 switch (exceptionVector) {
855 case 0 : sigval = 23; break; /* I/O trap */
856 case 1 : sigval = 5; break; /* breakpoint */
857 case 2 : sigval = 5; break; /* breakpoint */
858 case 3 : sigval = 5; break; /* breakpoint */
859 case 4 : sigval = 5; break; /* breakpoint */
860 case 5 : sigval = 5; break; /* breakpoint */
861 case 6 : sigval = 5; break; /* breakpoint */
862 case 7 : sigval = 5; break; /* breakpoint */
863 case 8 : sigval = 5; break; /* breakpoint */
864 case 9 : sigval = 5; break; /* breakpoint */
865 case 10 : sigval = 5; break; /* breakpoint */
866 case 11 : sigval = 5; break; /* breakpoint */
867 case 12 : sigval = 5; break; /* breakpoint */
868 case 13 : sigval = 5; break; /* breakpoint */
869 case 14 : sigval = 5; break; /* breakpoint */
870 case 15 : sigval = 5; break; /* breakpoint */
871 case 16 : sigval = 10; break; /* BUS ERROR (alignment) */
872 case 17 : sigval = 2; break; /* INTerrupt */
873 default : sigval = 7; break; /* "software generated" */
874 }
875 return (sigval);
876}
877
878/**********************************************/
879/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
880/* RETURN NUMBER OF CHARS PROCESSED */
881/**********************************************/
882static int
883hexToInt(ptr, intValue)
884 unsigned char **ptr;
885 int *intValue;
886{
887 int numChars = 0;
888 int hexValue;
889
890 *intValue = 0;
891 while (**ptr)
892 {
893 hexValue = hex(**ptr);
894 if (hexValue >=0)
895 {
896 *intValue = (*intValue <<4) | hexValue;
897 numChars ++;
898 }
899 else
900 break;
901 (*ptr)++;
902 }
903 return (numChars);
904}
905
906/*
907 Table of branch instructions:
908
909 10B6 RTE return from trap or exception
910 1FCr JMP jump
911 1ECr JL jump and link
912 7Fxx BRA branch
913 FFxxxxxx BRA branch (long)
914 B09rxxxx BNEZ branch not-equal-zero
915 Br1rxxxx BNE branch not-equal
916 7Dxx BNC branch not-condition
917 FDxxxxxx BNC branch not-condition (long)
918 B0Arxxxx BLTZ branch less-than-zero
919 B0Crxxxx BLEZ branch less-equal-zero
920 7Exx BL branch and link
921 FExxxxxx BL branch and link (long)
922 B0Drxxxx BGTZ branch greater-than-zero
923 B0Brxxxx BGEZ branch greater-equal-zero
924 B08rxxxx BEQZ branch equal-zero
925 Br0rxxxx BEQ branch equal
926 7Cxx BC branch condition
927 FCxxxxxx BC branch condition (long)
928 */
929
930static int
931isShortBranch(instr)
932 unsigned char *instr;
933{
934 unsigned char instr0 = instr[0] & 0x7F; /* mask off high bit */
935
936 if (instr0 == 0x10 && instr[1] == 0xB6) /* RTE */
937 return 1; /* return from trap or exception */
938
939 if (instr0 == 0x1E || instr0 == 0x1F) /* JL or JMP */
940 if ((instr[1] & 0xF0) == 0xC0)
941 return 2; /* jump thru a register */
942
943 if (instr0 == 0x7C || instr0 == 0x7D || /* BC, BNC, BL, BRA */
944 instr0 == 0x7E || instr0 == 0x7F)
945 return 3; /* eight bit PC offset */
946
947 return 0;
948}
949
950static int
951isLongBranch(instr)
952 unsigned char *instr;
953{
954 if (instr[0] == 0xFC || instr[0] == 0xFD || /* BRA, BNC, BL, BC */
955 instr[0] == 0xFE || instr[0] == 0xFF) /* 24 bit relative */
956 return 4;
957 if ((instr[0] & 0xF0) == 0xB0) /* 16 bit relative */
958 {
959 if ((instr[1] & 0xF0) == 0x00 || /* BNE, BEQ */
960 (instr[1] & 0xF0) == 0x10)
961 return 5;
962 if (instr[0] == 0xB0) /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
963 if ((instr[1] & 0xF0) == 0x80 || (instr[1] & 0xF0) == 0x90 ||
964 (instr[1] & 0xF0) == 0xA0 || (instr[1] & 0xF0) == 0xB0 ||
965 (instr[1] & 0xF0) == 0xC0 || (instr[1] & 0xF0) == 0xD0)
966 return 6;
967 }
968 return 0;
969}
970
971/* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
972 then it's a 2-byte instruction, else it's a 4-byte instruction. */
973
974#define INSTRUCTION_SIZE(addr) \
975 ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
976
977static int
978isBranch(instr)
979 unsigned char *instr;
980{
981 if (INSTRUCTION_SIZE(instr) == 2)
982 return isShortBranch(instr);
983 else
984 return isLongBranch(instr);
985}
986
987static int
988willBranch(instr, branchCode)
989 unsigned char *instr;
990{
991 switch (branchCode)
992 {
993 case 0: return 0; /* not a branch */
994 case 1: return 1; /* RTE */
995 case 2: return 1; /* JL or JMP */
996 case 3: /* BC, BNC, BL, BRA (short) */
997 case 4: /* BC, BNC, BL, BRA (long) */
998 switch (instr[0] & 0x0F)
999 {
1000 case 0xC: /* Branch if Condition Register */
1001 return (registers[CBR] != 0);
1002 case 0xD: /* Branch if NOT Condition Register */
1003 return (registers[CBR] == 0);
1004 case 0xE: /* Branch and Link */
1005 case 0xF: /* Branch (unconditional) */
1006 return 1;
1007 default: /* oops? */
1008 return 0;
1009 }
1010 case 5: /* BNE, BEQ */
1011 switch (instr[1] & 0xF0)
1012 {
1013 case 0x00: /* Branch if r1 equal to r2 */
1014 return (registers[instr[0] & 0x0F] == registers[instr[1] & 0x0F]);
1015 case 0x10: /* Branch if r1 NOT equal to r2 */
1016 return (registers[instr[0] & 0x0F] != registers[instr[1] & 0x0F]);
1017 default: /* oops? */
1018 return 0;
1019 }
1020 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
1021 switch (instr[1] & 0xF0)
1022 {
1023 case 0x80: /* Branch if reg equal to zero */
1024 return (registers[instr[1] & 0x0F] == 0);
1025 case 0x90: /* Branch if reg NOT equal to zero */
1026 return (registers[instr[1] & 0x0F] != 0);
1027 case 0xA0: /* Branch if reg less than zero */
1028 return (registers[instr[1] & 0x0F] < 0);
1029 case 0xB0: /* Branch if reg greater or equal to zero */
1030 return (registers[instr[1] & 0x0F] >= 0);
1031 case 0xC0: /* Branch if reg less than or equal to zero */
1032 return (registers[instr[1] & 0x0F] <= 0);
1033 case 0xD0: /* Branch if reg greater than zero */
1034 return (registers[instr[1] & 0x0F] > 0);
1035 default: /* oops? */
1036 return 0;
1037 }
1038 default: /* oops? */
1039 return 0;
1040 }
1041}
1042
1043static int
1044branchDestination(instr, branchCode)
1045 unsigned char *instr;
1046{
1047 switch (branchCode) {
1048 default:
1049 case 0: /* not a branch */
1050 return 0;
1051 case 1: /* RTE */
1052 return registers[BPC] & ~3; /* pop BPC into PC */
1053 case 2: /* JL or JMP */
1054 return registers[instr[1] & 0x0F] & ~3; /* jump thru a register */
1055 case 3: /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
7a292a7a 1056 return (((int) instr) & ~3) + ((char) instr[1] << 2);
c906108c
SS
1057 case 4: /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
1058 return ((int) instr +
7a292a7a 1059 ((((char) instr[1] << 16) | (instr[2] << 8) | (instr[3])) << 2));
c906108c
SS
1060 case 5: /* BNE, BEQ (16-bit relative offset) */
1061 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
7a292a7a 1062 return ((int) instr + ((((char) instr[2] << 8) | (instr[3])) << 2));
c906108c
SS
1063 }
1064
1065 /* An explanatory note: in the last three return expressions, I have
1066 cast the most-significant byte of the return offset to char.
1067 What this accomplishes is sign extension. If the other
1068 less-significant bytes were signed as well, they would get sign
1069 extended too and, if negative, their leading bits would clobber
1070 the bits of the more-significant bytes ahead of them. There are
1071 other ways I could have done this, but sign extension from
1072 odd-sized integers is always a pain. */
1073}
1074
1075static void
1076branchSideEffects(instr, branchCode)
1077 unsigned char *instr;
1078 int branchCode;
1079{
1080 switch (branchCode)
1081 {
1082 case 1: /* RTE */
1083 return; /* I <THINK> this is already handled... */
1084 case 2: /* JL (or JMP) */
1085 case 3: /* BL (or BC, BNC, BRA) */
1086 case 4:
1087 if ((instr[0] & 0x0F) == 0x0E) /* branch/jump and link */
1088 registers[R14] = (registers[PC] & ~3) + 4;
1089 return;
1090 default: /* any other branch has no side effects */
1091 return;
1092 }
1093}
1094
1095static struct STEPPING_CONTEXT {
1096 int stepping; /* true when we've started a single-step */
1097 unsigned long target_addr; /* the instr we're trying to execute */
1098 unsigned long target_size; /* the size of the target instr */
1099 unsigned long noop_addr; /* where we've inserted a no-op, if any */
1100 unsigned long trap1_addr; /* the trap following the target instr */
1101 unsigned long trap2_addr; /* the trap at a branch destination, if any */
1102 unsigned short noop_save; /* instruction overwritten by our no-op */
1103 unsigned short trap1_save; /* instruction overwritten by trap1 */
1104 unsigned short trap2_save; /* instruction overwritten by trap2 */
1105 unsigned short continue_p; /* true if NOT returning to gdb after step */
1106} stepping;
1107
1108/* Function: prepare_to_step
1109 Called from handle_exception to prepare the user program to single-step.
1110 Places a trap instruction after the target instruction, with special
1111 extra handling for branch instructions and for instructions in the
1112 second half-word of a word.
1113
1114 Returns: True if we should actually execute the instruction;
1115 False if we are going to emulate executing the instruction,
1116 in which case we simply report to GDB that the instruction
1117 has already been executed. */
1118
1119#define TRAP1 0x10f1; /* trap #1 instruction */
1120#define NOOP 0x7000; /* noop instruction */
1121
1122static unsigned short trap1 = TRAP1;
1123static unsigned short noop = NOOP;
1124
1125static int
1126prepare_to_step(continue_p)
1127 int continue_p; /* if this isn't REALLY a single-step (see below) */
1128{
1129 unsigned long pc = registers[PC];
1130 int branchCode = isBranch((unsigned char *) pc);
1131 unsigned char *p;
1132
1133 /* zero out the stepping context
1134 (paranoia -- it should already be zeroed) */
1135 for (p = (unsigned char *) &stepping;
1136 p < ((unsigned char *) &stepping) + sizeof(stepping);
1137 p++)
1138 *p = 0;
1139
1140 if (branchCode != 0) /* next instruction is a branch */
1141 {
1142 branchSideEffects((unsigned char *) pc, branchCode);
1143 if (willBranch((unsigned char *)pc, branchCode))
1144 registers[PC] = branchDestination((unsigned char *) pc, branchCode);
1145 else
1146 registers[PC] = pc + INSTRUCTION_SIZE(pc);
1147 return 0; /* branch "executed" -- just notify GDB */
1148 }
1149 else if (((int) pc & 2) != 0) /* "second-slot" instruction */
1150 {
1151 /* insert no-op before pc */
1152 stepping.noop_addr = pc - 2;
1153 stepping.noop_save = *(unsigned short *) stepping.noop_addr;
1154 *(unsigned short *) stepping.noop_addr = noop;
1155 /* insert trap after pc */
1156 stepping.trap1_addr = pc + 2;
1157 stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
1158 *(unsigned short *) stepping.trap1_addr = trap1;
1159 }
1160 else /* "first-slot" instruction */
1161 {
1162 /* insert trap after pc */
1163 stepping.trap1_addr = pc + INSTRUCTION_SIZE(pc);
1164 stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
1165 *(unsigned short *) stepping.trap1_addr = trap1;
1166 }
1167 /* "continue_p" means that we are actually doing a continue, and not
1168 being requested to single-step by GDB. Sometimes we have to do
1169 one single-step before continuing, because the PC is on a half-word
1170 boundary. There's no way to simply resume at such an address. */
1171 stepping.continue_p = continue_p;
1172 stepping.stepping = 1; /* starting a single-step */
1173 return 1;
1174}
1175
1176/* Function: finish_from_step
1177 Called from handle_exception to finish up when the user program
1178 returns from a single-step. Replaces the instructions that had
1179 been overwritten by traps or no-ops,
1180
1181 Returns: True if we should notify GDB that the target stopped.
1182 False if we only single-stepped because we had to before we
1183 could continue (ie. we were trying to continue at a
1184 half-word boundary). In that case don't notify GDB:
1185 just "continue continuing". */
1186
1187static int
1188finish_from_step()
1189{
1190 if (stepping.stepping) /* anything to do? */
1191 {
1192 int continue_p = stepping.continue_p;
1193 unsigned char *p;
1194
1195 if (stepping.noop_addr) /* replace instr "under" our no-op */
1196 *(unsigned short *) stepping.noop_addr = stepping.noop_save;
1197 if (stepping.trap1_addr) /* replace instr "under" our trap */
1198 *(unsigned short *) stepping.trap1_addr = stepping.trap1_save;
1199 if (stepping.trap2_addr) /* ditto our other trap, if any */
1200 *(unsigned short *) stepping.trap2_addr = stepping.trap2_save;
1201
1202 for (p = (unsigned char *) &stepping; /* zero out the stepping context */
1203 p < ((unsigned char *) &stepping) + sizeof(stepping);
1204 p++)
1205 *p = 0;
1206
1207 return !(continue_p);
1208 }
1209 else /* we didn't single-step, therefore this must be a legitimate stop */
1210 return 1;
1211}
1212
1213struct PSWreg { /* separate out the bit flags in the PSW register */
1214 int pad1 : 16;
1215 int bsm : 1;
1216 int bie : 1;
1217 int pad2 : 5;
1218 int bc : 1;
1219 int sm : 1;
1220 int ie : 1;
1221 int pad3 : 5;
1222 int c : 1;
1223} *psw;
1224
1225/* Upon entry the value for LR to save has been pushed.
1226 We unpush that so that the value for the stack pointer saved is correct.
1227 Upon entry, all other registers are assumed to have not been modified
1228 since the interrupt/trap occured. */
1229
1230asm ("
1231stash_registers:
1232 push r0
1233 push r1
1234 seth r1, #shigh(registers)
1235 add3 r1, r1, #low(registers)
1236 pop r0 ; r1
1237 st r0, @(4,r1)
1238 pop r0 ; r0
1239 st r0, @r1
1240 addi r1, #4 ; only add 4 as subsequent saves are `pre inc'
1241 st r2, @+r1
1242 st r3, @+r1
1243 st r4, @+r1
1244 st r5, @+r1
1245 st r6, @+r1
1246 st r7, @+r1
1247 st r8, @+r1
1248 st r9, @+r1
1249 st r10, @+r1
1250 st r11, @+r1
1251 st r12, @+r1
1252 st r13, @+r1 ; fp
1253 pop r0 ; lr (r14)
1254 st r0, @+r1
1255 st sp, @+r1 ; sp contains right value at this point
1256 mvfc r0, cr0
1257 st r0, @+r1 ; cr0 == PSW
1258 mvfc r0, cr1
1259 st r0, @+r1 ; cr1 == CBR
1260 mvfc r0, cr2
1261 st r0, @+r1 ; cr2 == SPI
1262 mvfc r0, cr3
1263 st r0, @+r1 ; cr3 == SPU
1264 mvfc r0, cr6
1265 st r0, @+r1 ; cr6 == BPC
1266 st r0, @+r1 ; PC == BPC
1267 mvfaclo r0
1268 st r0, @+r1 ; ACCL
1269 mvfachi r0
1270 st r0, @+r1 ; ACCH
1271 jmp lr");
1272
1273/* C routine to clean up what stash_registers did.
1274 It is called after calling stash_registers.
1275 This is separate from stash_registers as we want to do this in C
1276 but doing stash_registers in C isn't straightforward. */
1277
1278static void
1279cleanup_stash ()
1280{
1281 psw = (struct PSWreg *) &registers[PSW]; /* fields of PSW register */
1282 psw->sm = psw->bsm; /* fix up pre-trap values of psw fields */
1283 psw->ie = psw->bie;
1284 psw->c = psw->bc;
1285 registers[CBR] = psw->bc; /* fix up pre-trap "C" register */
1286
1287#if 0 /* FIXME: Was in previous version. Necessary?
1288 (Remember that we use the "rte" insn to return from the
1289 trap/interrupt so the values of bsm, bie, bc are important. */
1290 psw->bsm = psw->bie = psw->bc = 0; /* zero post-trap values */
1291#endif
1292
1293 /* FIXME: Copied from previous version. This can probably be deleted
1294 since methinks stash_registers has already done this. */
1295 registers[PC] = registers[BPC]; /* pre-trap PC */
1296
1297 /* FIXME: Copied from previous version. Necessary? */
1298 if (psw->sm) /* copy R15 into (psw->sm ? SPU : SPI) */
1299 registers[SPU] = registers[R15];
1300 else
1301 registers[SPI] = registers[R15];
1302}
1303
1304asm ("
1305restore_and_return:
1306 seth r0, #shigh(registers+8)
1307 add3 r0, r0, #low(registers+8)
1308 ld r2, @r0+ ; restore r2
1309 ld r3, @r0+ ; restore r3
1310 ld r4, @r0+ ; restore r4
1311 ld r5, @r0+ ; restore r5
1312 ld r6, @r0+ ; restore r6
1313 ld r7, @r0+ ; restore r7
1314 ld r8, @r0+ ; restore r8
1315 ld r9, @r0+ ; restore r9
1316 ld r10, @r0+ ; restore r10
1317 ld r11, @r0+ ; restore r11
1318 ld r12, @r0+ ; restore r12
1319 ld r13, @r0+ ; restore r13
1320 ld r14, @r0+ ; restore r14
1321 ld r15, @r0+ ; restore r15
1322 ld r1, @r0+ ; restore cr0 == PSW
1323 mvtc r1, cr0
1324 ld r1, @r0+ ; restore cr1 == CBR (no-op, because it's read only)
1325 mvtc r1, cr1
1326 ld r1, @r0+ ; restore cr2 == SPI
1327 mvtc r1, cr2
1328 ld r1, @r0+ ; restore cr3 == SPU
1329 mvtc r1, cr3
1330 addi r0, #4 ; skip BPC
1331 ld r1, @r0+ ; restore cr6 (BPC) == PC
1332 mvtc r1, cr6
1333 ld r1, @r0+ ; restore ACCL
1334 mvtaclo r1
1335 ld r1, @r0+ ; restore ACCH
1336 mvtachi r1
1337 seth r0, #shigh(registers)
1338 add3 r0, r0, #low(registers)
1339 ld r1, @(4,r0) ; restore r1
1340 ld r0, @r0 ; restore r0
1341 rte");
1342
1343/* General trap handler, called after the registers have been stashed.
1344 NUM is the trap/exception number. */
1345
1346static void
1347process_exception (num)
1348 int num;
1349{
1350 cleanup_stash ();
1351 asm volatile ("
1352 seth r1, #shigh(stackPtr)
1353 add3 r1, r1, #low(stackPtr)
1354 ld r15, @r1 ; setup local stack (protect user stack)
1355 mv r0, %0
1356 bl handle_exception
1357 bl restore_and_return"
1358 : : "r" (num) : "r0", "r1");
1359}
1360
1361void _catchException0 ();
1362
1363asm ("
1364_catchException0:
1365 push lr
1366 bl stash_registers
1367 ; Note that at this point the pushed value of `lr' has been popped
1368 ldi r0, #0
1369 bl process_exception");
1370
1371void _catchException1 ();
1372
1373asm ("
1374_catchException1:
1375 push lr
1376 bl stash_registers
1377 ; Note that at this point the pushed value of `lr' has been popped
1378 bl cleanup_stash
1379 seth r1, #shigh(stackPtr)
1380 add3 r1, r1, #low(stackPtr)
1381 ld r15, @r1 ; setup local stack (protect user stack)
1382 seth r1, #shigh(registers + 21*4) ; PC
1383 add3 r1, r1, #low(registers + 21*4)
1384 ld r0, @r1
1385 addi r0, #-4 ; back up PC for breakpoint trap.
1386 st r0, @r1 ; FIXME: what about bp in right slot?
1387 ldi r0, #1
1388 bl handle_exception
1389 bl restore_and_return");
1390
1391void _catchException2 ();
1392
1393asm ("
1394_catchException2:
1395 push lr
1396 bl stash_registers
1397 ; Note that at this point the pushed value of `lr' has been popped
1398 ldi r0, #2
1399 bl process_exception");
1400
1401void _catchException3 ();
1402
1403asm ("
1404_catchException3:
1405 push lr
1406 bl stash_registers
1407 ; Note that at this point the pushed value of `lr' has been popped
1408 ldi r0, #3
1409 bl process_exception");
1410
1411void _catchException4 ();
1412
1413asm ("
1414_catchException4:
1415 push lr
1416 bl stash_registers
1417 ; Note that at this point the pushed value of `lr' has been popped
1418 ldi r0, #4
1419 bl process_exception");
1420
1421void _catchException5 ();
1422
1423asm ("
1424_catchException5:
1425 push lr
1426 bl stash_registers
1427 ; Note that at this point the pushed value of `lr' has been popped
1428 ldi r0, #5
1429 bl process_exception");
1430
1431void _catchException6 ();
1432
1433asm ("
1434_catchException6:
1435 push lr
1436 bl stash_registers
1437 ; Note that at this point the pushed value of `lr' has been popped
1438 ldi r0, #6
1439 bl process_exception");
1440
1441void _catchException7 ();
1442
1443asm ("
1444_catchException7:
1445 push lr
1446 bl stash_registers
1447 ; Note that at this point the pushed value of `lr' has been popped
1448 ldi r0, #7
1449 bl process_exception");
1450
1451void _catchException8 ();
1452
1453asm ("
1454_catchException8:
1455 push lr
1456 bl stash_registers
1457 ; Note that at this point the pushed value of `lr' has been popped
1458 ldi r0, #8
1459 bl process_exception");
1460
1461void _catchException9 ();
1462
1463asm ("
1464_catchException9:
1465 push lr
1466 bl stash_registers
1467 ; Note that at this point the pushed value of `lr' has been popped
1468 ldi r0, #9
1469 bl process_exception");
1470
1471void _catchException10 ();
1472
1473asm ("
1474_catchException10:
1475 push lr
1476 bl stash_registers
1477 ; Note that at this point the pushed value of `lr' has been popped
1478 ldi r0, #10
1479 bl process_exception");
1480
1481void _catchException11 ();
1482
1483asm ("
1484_catchException11:
1485 push lr
1486 bl stash_registers
1487 ; Note that at this point the pushed value of `lr' has been popped
1488 ldi r0, #11
1489 bl process_exception");
1490
1491void _catchException12 ();
1492
1493asm ("
1494_catchException12:
1495 push lr
1496 bl stash_registers
1497 ; Note that at this point the pushed value of `lr' has been popped
1498 ldi r0, #12
1499 bl process_exception");
1500
1501void _catchException13 ();
1502
1503asm ("
1504_catchException13:
1505 push lr
1506 bl stash_registers
1507 ; Note that at this point the pushed value of `lr' has been popped
1508 ldi r0, #13
1509 bl process_exception");
1510
1511void _catchException14 ();
1512
1513asm ("
1514_catchException14:
1515 push lr
1516 bl stash_registers
1517 ; Note that at this point the pushed value of `lr' has been popped
1518 ldi r0, #14
1519 bl process_exception");
1520
1521void _catchException15 ();
1522
1523asm ("
1524_catchException15:
1525 push lr
1526 bl stash_registers
1527 ; Note that at this point the pushed value of `lr' has been popped
1528 ldi r0, #15
1529 bl process_exception");
1530
1531void _catchException16 ();
1532
1533asm ("
1534_catchException16:
1535 push lr
1536 bl stash_registers
1537 ; Note that at this point the pushed value of `lr' has been popped
1538 ldi r0, #16
1539 bl process_exception");
1540
1541void _catchException17 ();
1542
1543asm ("
1544_catchException17:
1545 push lr
1546 bl stash_registers
1547 ; Note that at this point the pushed value of `lr' has been popped
1548 ldi r0, #17
1549 bl process_exception");
1550
1551
1552/* this function is used to set up exception handlers for tracing and
1553 breakpoints */
1554void
1555set_debug_traps()
1556{
1557 /* extern void remcomHandler(); */
1558 int i;
1559
1560 for (i = 0; i < 18; i++) /* keep a copy of old vectors */
1561 if (save_vectors[i] == 0) /* only copy them the first time */
1562 save_vectors[i] = getExceptionHandler (i);
1563
1564 stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
1565
1566 exceptionHandler (0, _catchException0);
1567 exceptionHandler (1, _catchException1);
1568 exceptionHandler (2, _catchException2);
1569 exceptionHandler (3, _catchException3);
1570 exceptionHandler (4, _catchException4);
1571 exceptionHandler (5, _catchException5);
1572 exceptionHandler (6, _catchException6);
1573 exceptionHandler (7, _catchException7);
1574 exceptionHandler (8, _catchException8);
1575 exceptionHandler (9, _catchException9);
1576 exceptionHandler (10, _catchException10);
1577 exceptionHandler (11, _catchException11);
1578 exceptionHandler (12, _catchException12);
1579 exceptionHandler (13, _catchException13);
1580 exceptionHandler (14, _catchException14);
1581 exceptionHandler (15, _catchException15);
1582 exceptionHandler (16, _catchException16);
1583 /* exceptionHandler (17, _catchException17); */
1584
c906108c
SS
1585 initialized = 1;
1586}
1587
1588/* This function will generate a breakpoint exception. It is used at the
1589 beginning of a program to sync up with a debugger and can be used
1590 otherwise as a quick means to stop program execution and "break" into
1591 the debugger. */
1592
1593#define BREAKPOINT() asm volatile (" trap #2");
1594
1595void
1596breakpoint()
1597{
1598 if (initialized)
1599 BREAKPOINT();
1600}
1601
1602/* STDOUT section:
1603 Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
1604 Functions: gdb_putchar(char ch)
1605 gdb_puts(char *str)
1606 gdb_write(char *str, int len)
1607 gdb_error(char *format, char *parm)
1608 */
1609
1610/* Function: gdb_putchar(int)
1611 Make gdb write a char to stdout.
1612 Returns: the char */
1613
1614static int
1615gdb_putchar(ch)
1616 int ch;
1617{
1618 char buf[4];
1619
1620 buf[0] = 'O';
1621 buf[1] = hexchars[ch >> 4];
1622 buf[2] = hexchars[ch & 0x0F];
1623 buf[3] = 0;
1624 putpacket(buf);
1625 return ch;
1626}
1627
1628/* Function: gdb_write(char *, int)
1629 Make gdb write n bytes to stdout (not assumed to be null-terminated).
1630 Returns: number of bytes written */
1631
1632static int
1633gdb_write(data, len)
1634 char *data;
1635 int len;
1636{
1637 char *buf, *cpy;
1638 int i;
1639
1640 buf = remcomOutBuffer;
1641 buf[0] = 'O';
1642 i = 0;
1643 while (i < len)
1644 {
1645 for (cpy = buf+1;
1646 i < len && cpy < buf + sizeof(remcomOutBuffer) - 3;
1647 i++)
1648 {
1649 *cpy++ = hexchars[data[i] >> 4];
1650 *cpy++ = hexchars[data[i] & 0x0F];
1651 }
1652 *cpy = 0;
1653 putpacket(buf);
1654 }
1655 return len;
1656}
1657
1658/* Function: gdb_puts(char *)
1659 Make gdb write a null-terminated string to stdout.
1660 Returns: the length of the string */
1661
1662static int
1663gdb_puts(str)
1664 char *str;
1665{
1666 return gdb_write(str, strlen(str));
1667}
1668
1669/* Function: gdb_error(char *, char *)
1670 Send an error message to gdb's stdout.
1671 First string may have 1 (one) optional "%s" in it, which
1672 will cause the optional second string to be inserted. */
1673
1674static void
1675gdb_error(format, parm)
1676 char * format;
1677 char * parm;
1678{
1679 char buf[400], *cpy;
1680 int len;
1681
1682 if (remote_debug)
1683 {
1684 if (format && *format)
1685 len = strlen(format);
1686 else
1687 return; /* empty input */
1688
1689 if (parm && *parm)
1690 len += strlen(parm);
1691
1692 for (cpy = buf; *format; )
1693 {
1694 if (format[0] == '%' && format[1] == 's') /* include second string */
1695 {
1696 format += 2; /* advance two chars instead of just one */
1697 while (parm && *parm)
1698 *cpy++ = *parm++;
1699 }
1700 else
1701 *cpy++ = *format++;
1702 }
1703 *cpy = '\0';
1704 gdb_puts(buf);
1705 }
1706}
1707
1708static unsigned char *
1709strcpy (unsigned char *dest, const unsigned char *src)
1710{
1711 unsigned char *ret = dest;
1712
1713 if (dest && src)
1714 {
1715 while (*src)
1716 *dest++ = *src++;
1717 *dest = 0;
1718 }
1719 return ret;
1720}
1721
1722static int
1723strlen (const unsigned char *src)
1724{
1725 int ret;
1726
1727 for (ret = 0; *src; src++)
1728 ret++;
1729
1730 return ret;
1731}
1732
1733#if 0
1734void exit (code)
1735 int code;
1736{
1737 _exit (code);
1738}
1739
1740int atexit (void *p)
1741{
1742 return 0;
1743}
1744
1745void abort (void)
1746{
1747 _exit (1);
1748}
1749#endif
This page took 0.146408 seconds and 4 git commands to generate.