Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(981)

Side by Side Diff: gdb/m32r-stub.c

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

Powered by Google App Engine
This is Rietveld 408576698