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