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