1 /****************************************************************************
3 THIS SOFTWARE IS NOT COPYRIGHTED
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.
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.
13 ****************************************************************************/
15 /****************************************************************************
16 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
18 * Module name: remcom.c $
20 * Date: 91/03/09 12:29:49 $
21 * Contributor: Lake Stevens Instrument Division$
23 * Description: low level support for gdb debugger. $
25 * Considerations: only works on target hardware $
27 * Written by: Glenn Engel $
28 * ModuleState: Experimental $
32 * Modified for M32R by Michael Snyder, Cygnus Support.
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.
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.
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.
53 * The following gdb commands are supported:
55 * command function Return value
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
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
65 * c Resume at current address SNN ( signal NN)
66 * cAA..AA Continue at address AA..AA SNN
68 * s Step one instruction SNN
69 * sAA..AA Step one instruction from AA..AA SNN
73 * ? What was the last sigval ? SNN (signal NN)
75 * All commands and responses are sent with a packet which includes a
76 * checksum. A packet consists of
78 * $<packet info>#<checksum>.
81 * <packet info> :: <characters representing the command or response>
82 * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
84 * When a packet is received, it is first acknowledged with either '+' or '-'.
85 * '+' indicates a successful transfer. '-' indicates a failed transfer.
90 * $m0,10#2a +$00010203040506070809101112131415#42
92 ****************************************************************************/
95 /************************************************************************
97 * external low-level support routines
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 */
103 /*****************************************************************************
104 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
105 * at least NUMREGBYTES*2 are needed for register packets
109 static char initialized
; /* boolean flag. != 0 means we've been initialized */
112 /* debug > 0 prints ill-formed commands in valid packets & checksum errors */
114 static const unsigned char hexchars
[]="0123456789abcdef";
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
};
149 static int registers
[NUMREGS
];
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];
157 static unsigned int save_vectors
[18]; /* previous exception vectors */
159 /* Indicate to caller of mem2hex or hex2mem that there has been an error. */
160 static volatile int mem_err
= 0;
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;
167 #include "syscall.h" /* for SYS_exit, SYS_write etc. */
170 /* Global entry points:
173 extern void handle_exception(int);
174 extern void set_debug_traps(void);
175 extern void breakpoint(void);
180 static int computeSignal(int);
181 static void putpacket(unsigned char *);
182 static void getpacket(unsigned char *);
184 static unsigned char *mem2hex(unsigned char *, unsigned char *, int, int);
185 static unsigned char *hex2mem(unsigned char *, unsigned char *, int, int);
186 static int hexToInt(unsigned char **, int *);
187 static unsigned char *bin2mem(unsigned char *, unsigned char *, int, int);
188 static void stash_registers(void);
189 static void restore_registers(void);
190 static int prepare_to_step(int);
191 static int finish_from_step(void);
192 static unsigned long crc32 (unsigned char *, int, unsigned long);
194 static void gdb_error(char *, char *);
195 static int gdb_putchar(int), gdb_puts(char *), gdb_write(char *, int);
197 static unsigned char *strcpy (unsigned char *, const unsigned char *);
198 static int strlen (const unsigned char *);
201 * This function does all command procesing for interfacing to gdb.
205 handle_exception(int exceptionVector
)
210 unsigned char buf
[16];
213 if (!finish_from_step())
214 return; /* "false step": let the target continue */
216 gdb_m32r_vector
= exceptionVector
;
220 mem2hex((unsigned char *) &exceptionVector
, buf
, 4, 0);
221 gdb_error("Handle exception %s, ", buf
);
222 mem2hex((unsigned char *) ®isters
[PC
], buf
, 4, 0);
223 gdb_error("PC == 0x%s\n", buf
);
226 /* reply to host that an exception has occurred */
227 sigval
= computeSignal( exceptionVector
);
229 ptr
= remcomOutBuffer
;
231 *ptr
++ = 'T'; /* notify gdb with signo, PC, FP and SP */
232 *ptr
++ = hexchars
[sigval
>> 4];
233 *ptr
++ = hexchars
[sigval
& 0xf];
235 *ptr
++ = hexchars
[PC
>> 4];
236 *ptr
++ = hexchars
[PC
& 0xf];
238 ptr
= mem2hex((unsigned char *)®isters
[PC
], ptr
, 4, 0); /* PC */
241 *ptr
++ = hexchars
[R13
>> 4];
242 *ptr
++ = hexchars
[R13
& 0xf];
244 ptr
= mem2hex((unsigned char *)®isters
[R13
], ptr
, 4, 0); /* FP */
247 *ptr
++ = hexchars
[R15
>> 4];
248 *ptr
++ = hexchars
[R15
& 0xf];
250 ptr
= mem2hex((unsigned char *)®isters
[R15
], ptr
, 4, 0); /* SP */
254 if (exceptionVector
== 0) /* simulated SYS call stuff */
256 mem2hex((unsigned char *) ®isters
[PC
], buf
, 4, 0);
257 switch (registers
[R0
]) {
259 gdb_error("Target program has exited at %s\n", buf
);
260 ptr
= remcomOutBuffer
;
262 sigval
= registers
[R1
] & 0xff;
263 *ptr
++ = hexchars
[sigval
>> 4];
264 *ptr
++ = hexchars
[sigval
& 0xf];
268 gdb_error("Target attempts SYS_open call at %s\n", buf
);
271 gdb_error("Target attempts SYS_close call at %s\n", buf
);
274 gdb_error("Target attempts SYS_read call at %s\n", buf
);
277 if (registers
[R1
] == 1 || /* write to stdout */
278 registers
[R1
] == 2) /* write to stderr */
279 { /* (we can do that) */
280 registers
[R0
] = gdb_write((void *) registers
[R2
], registers
[R3
]);
284 gdb_error("Target attempts SYS_write call at %s\n", buf
);
287 gdb_error("Target attempts SYS_lseek call at %s\n", buf
);
290 gdb_error("Target attempts SYS_unlink call at %s\n", buf
);
293 gdb_error("Target attempts SYS_getpid call at %s\n", buf
);
296 gdb_error("Target attempts SYS_kill call at %s\n", buf
);
299 gdb_error("Target attempts SYS_fstat call at %s\n", buf
);
302 gdb_error("Target attempts unknown SYS call at %s\n", buf
);
307 putpacket(remcomOutBuffer
);
310 remcomOutBuffer
[0] = 0;
311 getpacket(remcomInBuffer
);
313 switch (remcomInBuffer
[0]) {
314 default: /* Unknown code. Return an empty reply message. */
317 ptr
= &remcomInBuffer
[1];
318 if (hexToInt (&ptr
, &addr
))
319 registers
[PC
] = addr
;
320 strcpy(remcomOutBuffer
, "OK");
323 strcpy(remcomOutBuffer
, "OK");
325 case 'X': /* XAA..AA,LLLL:<binary data>#cs */
327 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
328 /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
330 ptr
= &remcomInBuffer
[1];
331 if (hexToInt(&ptr
,&addr
))
333 if (hexToInt(&ptr
,&length
))
338 bin2mem (ptr
, (unsigned char *) addr
, length
, 1);
340 hex2mem(ptr
, (unsigned char*) addr
, length
, 1);
342 strcpy (remcomOutBuffer
, "E03");
343 gdb_error ("memory fault", "");
345 strcpy(remcomOutBuffer
,"OK");
351 strcpy(remcomOutBuffer
,"E02");
352 gdb_error("malformed write memory command: %s",
357 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
358 /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
359 ptr
= &remcomInBuffer
[1];
360 if (hexToInt(&ptr
,&addr
))
362 if (hexToInt(&ptr
,&length
))
366 mem2hex((unsigned char*) addr
, remcomOutBuffer
, length
, 1);
368 strcpy (remcomOutBuffer
, "E03");
369 gdb_error ("memory fault", "");
374 strcpy(remcomOutBuffer
,"E01");
375 gdb_error("malformed read memory command: %s",
380 remcomOutBuffer
[0] = 'S';
381 remcomOutBuffer
[1] = hexchars
[sigval
>> 4];
382 remcomOutBuffer
[2] = hexchars
[sigval
% 16];
383 remcomOutBuffer
[3] = 0;
386 remote_debug
= !(remote_debug
); /* toggle debug flag */
388 case 'g': /* return the value of the CPU registers */
389 mem2hex((unsigned char*) registers
, remcomOutBuffer
, NUMREGBYTES
, 0);
391 case 'P': /* set the value of a single CPU register - return OK */
395 ptr
= &remcomInBuffer
[1];
396 if (hexToInt (&ptr
, ®no
) && *ptr
++ == '=')
397 if (regno
>= 0 && regno
< NUMREGS
)
401 hex2mem (ptr
, (unsigned char *) ®isters
[regno
], 4, 0);
403 * Since we just changed a single CPU register, let's
404 * make sure to keep the several stack pointers consistant.
406 stackmode
= registers
[PSW
] & 0x80;
407 if (regno
== R15
) /* stack pointer changed */
408 { /* need to change SPI or SPU */
410 registers
[SPI
] = registers
[R15
];
412 registers
[SPU
] = registers
[R15
];
414 else if (regno
== SPU
) /* "user" stack pointer changed */
416 if (stackmode
!= 0) /* stack in user mode: copy SP */
417 registers
[R15
] = registers
[SPU
];
419 else if (regno
== SPI
) /* "interrupt" stack pointer changed */
421 if (stackmode
== 0) /* stack in interrupt mode: copy SP */
422 registers
[R15
] = registers
[SPI
];
424 else if (regno
== PSW
) /* stack mode may have changed! */
425 { /* force SP to either SPU or SPI */
426 if (stackmode
== 0) /* stack in user mode */
427 registers
[R15
] = registers
[SPI
];
428 else /* stack in interrupt mode */
429 registers
[R15
] = registers
[SPU
];
431 strcpy (remcomOutBuffer
, "OK");
434 strcpy (remcomOutBuffer
, "P01");
437 case 'G': /* set the value of the CPU registers - return OK */
438 hex2mem(&remcomInBuffer
[1], (unsigned char*) registers
, NUMREGBYTES
, 0);
439 strcpy(remcomOutBuffer
,"OK");
441 case 's': /* sAA..AA Step one instruction from AA..AA(optional) */
442 case 'c': /* cAA..AA Continue from address AA..AA(optional) */
443 /* try to read optional parameter, pc unchanged if no parm */
444 ptr
= &remcomInBuffer
[1];
445 if (hexToInt(&ptr
,&addr
))
446 registers
[ PC
] = addr
;
448 if (remcomInBuffer
[0] == 's') /* single-stepping */
450 if (!prepare_to_step(0)) /* set up for single-step */
452 /* prepare_to_step has already emulated the target insn:
453 Send SIGTRAP to gdb, don't resume the target at all. */
454 ptr
= remcomOutBuffer
;
455 *ptr
++ = 'T'; /* Simulate stopping with SIGTRAP */
459 *ptr
++ = hexchars
[PC
>> 4]; /* send PC */
460 *ptr
++ = hexchars
[PC
& 0xf];
462 ptr
= mem2hex((unsigned char *)®isters
[PC
], ptr
, 4, 0);
465 *ptr
++ = hexchars
[R13
>> 4]; /* send FP */
466 *ptr
++ = hexchars
[R13
& 0xf];
468 ptr
= mem2hex((unsigned char *)®isters
[R13
], ptr
, 4, 0);
471 *ptr
++ = hexchars
[R15
>> 4]; /* send SP */
472 *ptr
++ = hexchars
[R15
& 0xf];
474 ptr
= mem2hex((unsigned char *)®isters
[R15
], ptr
, 4, 0);
481 else /* continuing, not single-stepping */
483 /* OK, about to do a "continue". First check to see if the
484 target pc is on an odd boundary (second instruction in the
485 word). If so, we must do a single-step first, because
486 ya can't jump or return back to an odd boundary! */
487 if ((registers
[PC
] & 2) != 0)
493 case 'D': /* Detach */
495 /* I am interpreting this to mean, release the board from control
496 by the remote stub. To do this, I am restoring the original
497 (or at least previous) exception vectors.
499 for (i
= 0; i
< 18; i
++)
500 exceptionHandler (i
, save_vectors
[i
]);
502 return; /* continue the inferior */
504 strcpy(remcomOutBuffer
,"OK");
508 ptr
= &remcomInBuffer
[1];
514 unsigned long start
, len
, our_crc
;
516 if (hexToInt (&ptr
, (int *) &start
) &&
518 hexToInt (&ptr
, (int *) &len
))
520 remcomOutBuffer
[0] = 'C';
521 our_crc
= crc32 ((unsigned char *) start
, len
, 0xffffffff);
522 mem2hex ((char *) &our_crc
,
526 } /* else do nothing */
527 } /* else do nothing */
530 case 'k': /* kill the program */
534 /* reply to the request */
535 putpacket(remcomOutBuffer
);
541 /* Table used by the crc32 function to calcuate the checksum. */
542 static unsigned long crc32_table
[256] = {0, 0};
545 crc32 (buf
, len
, crc
)
550 if (! crc32_table
[1])
552 /* Initialize the CRC table and the decoding table. */
556 for (i
= 0; i
< 256; i
++)
558 for (c
= i
<< 24, j
= 8; j
> 0; --j
)
559 c
= c
& 0x80000000 ? (c
<< 1) ^ 0x04c11db7 : (c
<< 1);
566 crc
= (crc
<< 8) ^ crc32_table
[((crc
>> 24) ^ *buf
) & 255];
576 if ((ch
>= 'a') && (ch
<= 'f')) return (ch
-'a'+10);
577 if ((ch
>= '0') && (ch
<= '9')) return (ch
-'0');
578 if ((ch
>= 'A') && (ch
<= 'F')) return (ch
-'A'+10);
582 /* scan for the sequence $<data>#<checksum> */
586 unsigned char * buffer
;
588 unsigned char checksum
;
589 unsigned char xmitcsum
;
595 /* wait around for the start character, ignore all other characters */
596 while ((ch
= getDebugChar()) != '$');
602 /* now, read until a # or end of buffer is found */
603 while (count
< BUFMAX
) {
606 if (ch
== '#' && (count
== 0 || buffer
[count
-1] != 0x7d))
609 checksum
= checksum
+ ch
;
616 xmitcsum
= hex(getDebugChar()) << 4;
617 xmitcsum
+= hex(getDebugChar());
618 if (checksum
!= xmitcsum
) {
620 unsigned char buf
[16];
622 mem2hex((unsigned char *) &checksum
, buf
, 4, 0);
623 gdb_error("Bad checksum: my count = %s, ", buf
);
624 mem2hex((unsigned char *) &xmitcsum
, buf
, 4, 0);
625 gdb_error("sent count = %s\n", buf
);
626 gdb_error(" -- Bad buffer: \"%s\"\n", buffer
);
629 putDebugChar('-'); /* failed checksum */
631 putDebugChar('+'); /* successful transfer */
632 /* if a sequence char is present, reply the sequence ID */
633 if (buffer
[2] == ':') {
634 putDebugChar( buffer
[0] );
635 putDebugChar( buffer
[1] );
636 /* remove sequence chars from buffer */
637 count
= strlen(buffer
);
638 for (i
=3; i
<= count
; i
++) buffer
[i
-3] = buffer
[i
];
642 } while (checksum
!= xmitcsum
);
645 /* send the packet in buffer. */
649 unsigned char *buffer
;
651 unsigned char checksum
;
655 /* $<packet info>#<checksum>. */
661 while (ch
=buffer
[count
]) {
667 putDebugChar(hexchars
[checksum
>> 4]);
668 putDebugChar(hexchars
[checksum
% 16]);
669 } while (getDebugChar() != '+');
672 /* Address of a routine to RTE to if we get a memory fault. */
674 static void (*volatile mem_fault_routine
)() = 0;
682 /* Check the address for safe access ranges. As currently defined,
683 this routine will reject the "expansion bus" address range(s).
684 To make those ranges useable, someone must implement code to detect
685 whether there's anything connected to the expansion bus. */
691 #define BAD_RANGE_ONE_START ((unsigned char *) 0x600000)
692 #define BAD_RANGE_ONE_END ((unsigned char *) 0xa00000)
693 #define BAD_RANGE_TWO_START ((unsigned char *) 0xff680000)
694 #define BAD_RANGE_TWO_END ((unsigned char *) 0xff800000)
696 if (addr
< BAD_RANGE_ONE_START
) return 1; /* safe */
697 if (addr
< BAD_RANGE_ONE_END
) return 0; /* unsafe */
698 if (addr
< BAD_RANGE_TWO_START
) return 1; /* safe */
699 if (addr
< BAD_RANGE_TWO_END
) return 0; /* unsafe */
702 /* These are separate functions so that they are so short and sweet
703 that the compiler won't save any registers (if there is a fault
704 to mem_fault, they won't get restored, so there better not be any
711 if (mem_fault_routine
&& !mem_safe(addr
))
713 mem_fault_routine ();
726 if (mem_fault_routine
&& !mem_safe (addr
))
728 mem_fault_routine ();
735 /* Convert the memory pointed to by mem into hex, placing result in buf.
736 Return a pointer to the last char put in buf (null).
737 If MAY_FAULT is non-zero, then we should set mem_err in response to
738 a fault; if zero treat a fault like any other fault in the stub. */
740 static unsigned char *
741 mem2hex(mem
, buf
, count
, may_fault
)
751 mem_fault_routine
= set_mem_err
;
752 for (i
=0;i
<count
;i
++) {
753 ch
= get_char (mem
++);
754 if (may_fault
&& mem_err
)
756 *buf
++ = hexchars
[ch
>> 4];
757 *buf
++ = hexchars
[ch
% 16];
761 mem_fault_routine
= 0;
765 /* Convert the hex array pointed to by buf into binary to be placed in mem.
766 Return a pointer to the character AFTER the last byte written. */
768 static unsigned char*
769 hex2mem(buf
, mem
, count
, may_fault
)
779 mem_fault_routine
= set_mem_err
;
780 for (i
=0;i
<count
;i
++) {
781 ch
= hex(*buf
++) << 4;
782 ch
= ch
+ hex(*buf
++);
783 set_char (mem
++, ch
);
784 if (may_fault
&& mem_err
)
788 mem_fault_routine
= 0;
792 /* Convert the binary stream in BUF to memory.
794 Gdb will escape $, #, and the escape char (0x7d).
795 COUNT is the total number of bytes to write into
797 static unsigned char *
798 bin2mem (buf
, mem
, count
, may_fault
)
808 mem_fault_routine
= set_mem_err
;
809 for (i
= 0; i
< count
; i
++)
811 /* Check for any escaped characters. Be paranoid and
812 only unescape chars that should be escaped. */
819 case 0x5d: /* escape char */
829 set_char (mem
++, *buf
++);
831 if (may_fault
&& mem_err
)
836 mem_fault_routine
= 0;
840 /* this function takes the m32r exception vector and attempts to
841 translate this number into a unix compatible signal value */
844 computeSignal(exceptionVector
)
848 switch (exceptionVector
) {
849 case 0 : sigval
= 23; break; /* I/O trap */
850 case 1 : sigval
= 5; break; /* breakpoint */
851 case 2 : sigval
= 5; break; /* breakpoint */
852 case 3 : sigval
= 5; break; /* breakpoint */
853 case 4 : sigval
= 5; break; /* breakpoint */
854 case 5 : sigval
= 5; break; /* breakpoint */
855 case 6 : sigval
= 5; break; /* breakpoint */
856 case 7 : sigval
= 5; break; /* breakpoint */
857 case 8 : sigval
= 5; break; /* breakpoint */
858 case 9 : sigval
= 5; break; /* breakpoint */
859 case 10 : sigval
= 5; break; /* breakpoint */
860 case 11 : sigval
= 5; break; /* breakpoint */
861 case 12 : sigval
= 5; break; /* breakpoint */
862 case 13 : sigval
= 5; break; /* breakpoint */
863 case 14 : sigval
= 5; break; /* breakpoint */
864 case 15 : sigval
= 5; break; /* breakpoint */
865 case 16 : sigval
= 10; break; /* BUS ERROR (alignment) */
866 case 17 : sigval
= 2; break; /* INTerrupt */
867 default : sigval
= 7; break; /* "software generated" */
872 /**********************************************/
873 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
874 /* RETURN NUMBER OF CHARS PROCESSED */
875 /**********************************************/
877 hexToInt(ptr
, intValue
)
887 hexValue
= hex(**ptr
);
890 *intValue
= (*intValue
<<4) | hexValue
;
901 Table of branch instructions:
903 10B6 RTE return from trap or exception
905 1ECr JL jump and link
907 FFxxxxxx BRA branch (long)
908 B09rxxxx BNEZ branch not-equal-zero
909 Br1rxxxx BNE branch not-equal
910 7Dxx BNC branch not-condition
911 FDxxxxxx BNC branch not-condition (long)
912 B0Arxxxx BLTZ branch less-than-zero
913 B0Crxxxx BLEZ branch less-equal-zero
914 7Exx BL branch and link
915 FExxxxxx BL branch and link (long)
916 B0Drxxxx BGTZ branch greater-than-zero
917 B0Brxxxx BGEZ branch greater-equal-zero
918 B08rxxxx BEQZ branch equal-zero
919 Br0rxxxx BEQ branch equal
920 7Cxx BC branch condition
921 FCxxxxxx BC branch condition (long)
926 unsigned char *instr
;
928 unsigned char instr0
= instr
[0] & 0x7F; /* mask off high bit */
930 if (instr0
== 0x10 && instr
[1] == 0xB6) /* RTE */
931 return 1; /* return from trap or exception */
933 if (instr0
== 0x1E || instr0
== 0x1F) /* JL or JMP */
934 if ((instr
[1] & 0xF0) == 0xC0)
935 return 2; /* jump thru a register */
937 if (instr0
== 0x7C || instr0
== 0x7D || /* BC, BNC, BL, BRA */
938 instr0
== 0x7E || instr0
== 0x7F)
939 return 3; /* eight bit PC offset */
946 unsigned char *instr
;
948 if (instr
[0] == 0xFC || instr
[0] == 0xFD || /* BRA, BNC, BL, BC */
949 instr
[0] == 0xFE || instr
[0] == 0xFF) /* 24 bit relative */
951 if ((instr
[0] & 0xF0) == 0xB0) /* 16 bit relative */
953 if ((instr
[1] & 0xF0) == 0x00 || /* BNE, BEQ */
954 (instr
[1] & 0xF0) == 0x10)
956 if (instr
[0] == 0xB0) /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
957 if ((instr
[1] & 0xF0) == 0x80 || (instr
[1] & 0xF0) == 0x90 ||
958 (instr
[1] & 0xF0) == 0xA0 || (instr
[1] & 0xF0) == 0xB0 ||
959 (instr
[1] & 0xF0) == 0xC0 || (instr
[1] & 0xF0) == 0xD0)
965 /* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
966 then it's a 2-byte instruction, else it's a 4-byte instruction. */
968 #define INSTRUCTION_SIZE(addr) \
969 ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
973 unsigned char *instr
;
975 if (INSTRUCTION_SIZE(instr
) == 2)
976 return isShortBranch(instr
);
978 return isLongBranch(instr
);
982 willBranch(instr
, branchCode
)
983 unsigned char *instr
;
987 case 0: return 0; /* not a branch */
988 case 1: return 1; /* RTE */
989 case 2: return 1; /* JL or JMP */
990 case 3: /* BC, BNC, BL, BRA (short) */
991 case 4: /* BC, BNC, BL, BRA (long) */
992 switch (instr
[0] & 0x0F)
994 case 0xC: /* Branch if Condition Register */
995 return (registers
[CBR
] != 0);
996 case 0xD: /* Branch if NOT Condition Register */
997 return (registers
[CBR
] == 0);
998 case 0xE: /* Branch and Link */
999 case 0xF: /* Branch (unconditional) */
1001 default: /* oops? */
1004 case 5: /* BNE, BEQ */
1005 switch (instr
[1] & 0xF0)
1007 case 0x00: /* Branch if r1 equal to r2 */
1008 return (registers
[instr
[0] & 0x0F] == registers
[instr
[1] & 0x0F]);
1009 case 0x10: /* Branch if r1 NOT equal to r2 */
1010 return (registers
[instr
[0] & 0x0F] != registers
[instr
[1] & 0x0F]);
1011 default: /* oops? */
1014 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
1015 switch (instr
[1] & 0xF0)
1017 case 0x80: /* Branch if reg equal to zero */
1018 return (registers
[instr
[1] & 0x0F] == 0);
1019 case 0x90: /* Branch if reg NOT equal to zero */
1020 return (registers
[instr
[1] & 0x0F] != 0);
1021 case 0xA0: /* Branch if reg less than zero */
1022 return (registers
[instr
[1] & 0x0F] < 0);
1023 case 0xB0: /* Branch if reg greater or equal to zero */
1024 return (registers
[instr
[1] & 0x0F] >= 0);
1025 case 0xC0: /* Branch if reg less than or equal to zero */
1026 return (registers
[instr
[1] & 0x0F] <= 0);
1027 case 0xD0: /* Branch if reg greater than zero */
1028 return (registers
[instr
[1] & 0x0F] > 0);
1029 default: /* oops? */
1032 default: /* oops? */
1038 branchDestination(instr
, branchCode
)
1039 unsigned char *instr
;
1041 switch (branchCode
) {
1043 case 0: /* not a branch */
1046 return registers
[BPC
] & ~3; /* pop BPC into PC */
1047 case 2: /* JL or JMP */
1048 return registers
[instr
[1] & 0x0F] & ~3; /* jump thru a register */
1049 case 3: /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
1050 return (((int) instr
) & ~3) + ((char) instr
[1] << 2);
1051 case 4: /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
1052 return ((int) instr
+
1053 ((((char) instr
[1] << 16) | (instr
[2] << 8) | (instr
[3])) << 2));
1054 case 5: /* BNE, BEQ (16-bit relative offset) */
1055 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
1056 return ((int) instr
+ ((((char) instr
[2] << 8) | (instr
[3])) << 2));
1059 /* An explanatory note: in the last three return expressions, I have
1060 cast the most-significant byte of the return offset to char.
1061 What this accomplishes is sign extension. If the other
1062 less-significant bytes were signed as well, they would get sign
1063 extended too and, if negative, their leading bits would clobber
1064 the bits of the more-significant bytes ahead of them. There are
1065 other ways I could have done this, but sign extension from
1066 odd-sized integers is always a pain. */
1070 branchSideEffects(instr
, branchCode
)
1071 unsigned char *instr
;
1077 return; /* I <THINK> this is already handled... */
1078 case 2: /* JL (or JMP) */
1079 case 3: /* BL (or BC, BNC, BRA) */
1081 if ((instr
[0] & 0x0F) == 0x0E) /* branch/jump and link */
1082 registers
[R14
] = (registers
[PC
] & ~3) + 4;
1084 default: /* any other branch has no side effects */
1089 static struct STEPPING_CONTEXT
{
1090 int stepping
; /* true when we've started a single-step */
1091 unsigned long target_addr
; /* the instr we're trying to execute */
1092 unsigned long target_size
; /* the size of the target instr */
1093 unsigned long noop_addr
; /* where we've inserted a no-op, if any */
1094 unsigned long trap1_addr
; /* the trap following the target instr */
1095 unsigned long trap2_addr
; /* the trap at a branch destination, if any */
1096 unsigned short noop_save
; /* instruction overwritten by our no-op */
1097 unsigned short trap1_save
; /* instruction overwritten by trap1 */
1098 unsigned short trap2_save
; /* instruction overwritten by trap2 */
1099 unsigned short continue_p
; /* true if NOT returning to gdb after step */
1102 /* Function: prepare_to_step
1103 Called from handle_exception to prepare the user program to single-step.
1104 Places a trap instruction after the target instruction, with special
1105 extra handling for branch instructions and for instructions in the
1106 second half-word of a word.
1108 Returns: True if we should actually execute the instruction;
1109 False if we are going to emulate executing the instruction,
1110 in which case we simply report to GDB that the instruction
1111 has already been executed. */
1113 #define TRAP1 0x10f1; /* trap #1 instruction */
1114 #define NOOP 0x7000; /* noop instruction */
1116 static unsigned short trap1
= TRAP1
;
1117 static unsigned short noop
= NOOP
;
1120 prepare_to_step(continue_p
)
1121 int continue_p
; /* if this isn't REALLY a single-step (see below) */
1123 unsigned long pc
= registers
[PC
];
1124 int branchCode
= isBranch((unsigned char *) pc
);
1127 /* zero out the stepping context
1128 (paranoia -- it should already be zeroed) */
1129 for (p
= (unsigned char *) &stepping
;
1130 p
< ((unsigned char *) &stepping
) + sizeof(stepping
);
1134 if (branchCode
!= 0) /* next instruction is a branch */
1136 branchSideEffects((unsigned char *) pc
, branchCode
);
1137 if (willBranch((unsigned char *)pc
, branchCode
))
1138 registers
[PC
] = branchDestination((unsigned char *) pc
, branchCode
);
1140 registers
[PC
] = pc
+ INSTRUCTION_SIZE(pc
);
1141 return 0; /* branch "executed" -- just notify GDB */
1143 else if (((int) pc
& 2) != 0) /* "second-slot" instruction */
1145 /* insert no-op before pc */
1146 stepping
.noop_addr
= pc
- 2;
1147 stepping
.noop_save
= *(unsigned short *) stepping
.noop_addr
;
1148 *(unsigned short *) stepping
.noop_addr
= noop
;
1149 /* insert trap after pc */
1150 stepping
.trap1_addr
= pc
+ 2;
1151 stepping
.trap1_save
= *(unsigned short *) stepping
.trap1_addr
;
1152 *(unsigned short *) stepping
.trap1_addr
= trap1
;
1154 else /* "first-slot" instruction */
1156 /* insert trap after pc */
1157 stepping
.trap1_addr
= pc
+ INSTRUCTION_SIZE(pc
);
1158 stepping
.trap1_save
= *(unsigned short *) stepping
.trap1_addr
;
1159 *(unsigned short *) stepping
.trap1_addr
= trap1
;
1161 /* "continue_p" means that we are actually doing a continue, and not
1162 being requested to single-step by GDB. Sometimes we have to do
1163 one single-step before continuing, because the PC is on a half-word
1164 boundary. There's no way to simply resume at such an address. */
1165 stepping
.continue_p
= continue_p
;
1166 stepping
.stepping
= 1; /* starting a single-step */
1170 /* Function: finish_from_step
1171 Called from handle_exception to finish up when the user program
1172 returns from a single-step. Replaces the instructions that had
1173 been overwritten by traps or no-ops,
1175 Returns: True if we should notify GDB that the target stopped.
1176 False if we only single-stepped because we had to before we
1177 could continue (ie. we were trying to continue at a
1178 half-word boundary). In that case don't notify GDB:
1179 just "continue continuing". */
1184 if (stepping
.stepping
) /* anything to do? */
1186 int continue_p
= stepping
.continue_p
;
1189 if (stepping
.noop_addr
) /* replace instr "under" our no-op */
1190 *(unsigned short *) stepping
.noop_addr
= stepping
.noop_save
;
1191 if (stepping
.trap1_addr
) /* replace instr "under" our trap */
1192 *(unsigned short *) stepping
.trap1_addr
= stepping
.trap1_save
;
1193 if (stepping
.trap2_addr
) /* ditto our other trap, if any */
1194 *(unsigned short *) stepping
.trap2_addr
= stepping
.trap2_save
;
1196 for (p
= (unsigned char *) &stepping
; /* zero out the stepping context */
1197 p
< ((unsigned char *) &stepping
) + sizeof(stepping
);
1201 return !(continue_p
);
1203 else /* we didn't single-step, therefore this must be a legitimate stop */
1207 struct PSWreg
{ /* separate out the bit flags in the PSW register */
1219 /* Upon entry the value for LR to save has been pushed.
1220 We unpush that so that the value for the stack pointer saved is correct.
1221 Upon entry, all other registers are assumed to have not been modified
1222 since the interrupt/trap occured. */
1228 seth r1, #shigh(registers)
1229 add3 r1, r1, #low(registers)
1234 addi r1, #4 ; only add 4 as subsequent saves are `pre inc'
1249 st sp, @+r1 ; sp contains right value at this point
1251 st r0, @+r1 ; cr0 == PSW
1253 st r0, @+r1 ; cr1 == CBR
1255 st r0, @+r1 ; cr2 == SPI
1257 st r0, @+r1 ; cr3 == SPU
1259 st r0, @+r1 ; cr6 == BPC
1260 st r0, @+r1 ; PC == BPC
1267 /* C routine to clean up what stash_registers did.
1268 It is called after calling stash_registers.
1269 This is separate from stash_registers as we want to do this in C
1270 but doing stash_registers in C isn't straightforward. */
1275 psw
= (struct PSWreg
*) ®isters
[PSW
]; /* fields of PSW register */
1276 psw
->sm
= psw
->bsm
; /* fix up pre-trap values of psw fields */
1279 registers
[CBR
] = psw
->bc
; /* fix up pre-trap "C" register */
1281 #if 0 /* FIXME: Was in previous version. Necessary?
1282 (Remember that we use the "rte" insn to return from the
1283 trap/interrupt so the values of bsm, bie, bc are important. */
1284 psw
->bsm
= psw
->bie
= psw
->bc
= 0; /* zero post-trap values */
1287 /* FIXME: Copied from previous version. This can probably be deleted
1288 since methinks stash_registers has already done this. */
1289 registers
[PC
] = registers
[BPC
]; /* pre-trap PC */
1291 /* FIXME: Copied from previous version. Necessary? */
1292 if (psw
->sm
) /* copy R15 into (psw->sm ? SPU : SPI) */
1293 registers
[SPU
] = registers
[R15
];
1295 registers
[SPI
] = registers
[R15
];
1300 seth r0, #shigh(registers+8)
1301 add3 r0, r0, #low(registers+8)
1302 ld r2, @r0+ ; restore r2
1303 ld r3, @r0+ ; restore r3
1304 ld r4, @r0+ ; restore r4
1305 ld r5, @r0+ ; restore r5
1306 ld r6, @r0+ ; restore r6
1307 ld r7, @r0+ ; restore r7
1308 ld r8, @r0+ ; restore r8
1309 ld r9, @r0+ ; restore r9
1310 ld r10, @r0+ ; restore r10
1311 ld r11, @r0+ ; restore r11
1312 ld r12, @r0+ ; restore r12
1313 ld r13, @r0+ ; restore r13
1314 ld r14, @r0+ ; restore r14
1315 ld r15, @r0+ ; restore r15
1316 ld r1, @r0+ ; restore cr0 == PSW
1318 ld r1, @r0+ ; restore cr1 == CBR (no-op, because it's read only)
1320 ld r1, @r0+ ; restore cr2 == SPI
1322 ld r1, @r0+ ; restore cr3 == SPU
1324 addi r0, #4 ; skip BPC
1325 ld r1, @r0+ ; restore cr6 (BPC) == PC
1327 ld r1, @r0+ ; restore ACCL
1329 ld r1, @r0+ ; restore ACCH
1331 seth r0, #shigh(registers)
1332 add3 r0, r0, #low(registers)
1333 ld r1, @(4,r0) ; restore r1
1334 ld r0, @r0 ; restore r0
1337 /* General trap handler, called after the registers have been stashed.
1338 NUM is the trap/exception number. */
1341 process_exception (num
)
1346 seth r1, #shigh(stackPtr)
1347 add3 r1, r1, #low(stackPtr)
1348 ld r15, @r1 ; setup local stack (protect user stack)
1351 bl restore_and_return"
1352 : : "r" (num
) : "r0", "r1");
1355 void _catchException0 ();
1361 ; Note that at this point the pushed value of `lr' has been popped
1363 bl process_exception");
1365 void _catchException1 ();
1371 ; Note that at this point the pushed value of `lr' has been popped
1373 seth r1, #shigh(stackPtr)
1374 add3 r1, r1, #low(stackPtr)
1375 ld r15, @r1 ; setup local stack (protect user stack)
1376 seth r1, #shigh(registers + 21*4) ; PC
1377 add3 r1, r1, #low(registers + 21*4)
1379 addi r0, #-4 ; back up PC for breakpoint trap.
1380 st r0, @r1 ; FIXME: what about bp in right slot?
1383 bl restore_and_return");
1385 void _catchException2 ();
1391 ; Note that at this point the pushed value of `lr' has been popped
1393 bl process_exception");
1395 void _catchException3 ();
1401 ; Note that at this point the pushed value of `lr' has been popped
1403 bl process_exception");
1405 void _catchException4 ();
1411 ; Note that at this point the pushed value of `lr' has been popped
1413 bl process_exception");
1415 void _catchException5 ();
1421 ; Note that at this point the pushed value of `lr' has been popped
1423 bl process_exception");
1425 void _catchException6 ();
1431 ; Note that at this point the pushed value of `lr' has been popped
1433 bl process_exception");
1435 void _catchException7 ();
1441 ; Note that at this point the pushed value of `lr' has been popped
1443 bl process_exception");
1445 void _catchException8 ();
1451 ; Note that at this point the pushed value of `lr' has been popped
1453 bl process_exception");
1455 void _catchException9 ();
1461 ; Note that at this point the pushed value of `lr' has been popped
1463 bl process_exception");
1465 void _catchException10 ();
1471 ; Note that at this point the pushed value of `lr' has been popped
1473 bl process_exception");
1475 void _catchException11 ();
1481 ; Note that at this point the pushed value of `lr' has been popped
1483 bl process_exception");
1485 void _catchException12 ();
1491 ; Note that at this point the pushed value of `lr' has been popped
1493 bl process_exception");
1495 void _catchException13 ();
1501 ; Note that at this point the pushed value of `lr' has been popped
1503 bl process_exception");
1505 void _catchException14 ();
1511 ; Note that at this point the pushed value of `lr' has been popped
1513 bl process_exception");
1515 void _catchException15 ();
1521 ; Note that at this point the pushed value of `lr' has been popped
1523 bl process_exception");
1525 void _catchException16 ();
1531 ; Note that at this point the pushed value of `lr' has been popped
1533 bl process_exception");
1535 void _catchException17 ();
1541 ; Note that at this point the pushed value of `lr' has been popped
1543 bl process_exception");
1546 /* this function is used to set up exception handlers for tracing and
1551 /* extern void remcomHandler(); */
1554 for (i
= 0; i
< 18; i
++) /* keep a copy of old vectors */
1555 if (save_vectors
[i
] == 0) /* only copy them the first time */
1556 save_vectors
[i
] = getExceptionHandler (i
);
1558 stackPtr
= &remcomStack
[STACKSIZE
/sizeof(int) - 1];
1560 exceptionHandler (0, _catchException0
);
1561 exceptionHandler (1, _catchException1
);
1562 exceptionHandler (2, _catchException2
);
1563 exceptionHandler (3, _catchException3
);
1564 exceptionHandler (4, _catchException4
);
1565 exceptionHandler (5, _catchException5
);
1566 exceptionHandler (6, _catchException6
);
1567 exceptionHandler (7, _catchException7
);
1568 exceptionHandler (8, _catchException8
);
1569 exceptionHandler (9, _catchException9
);
1570 exceptionHandler (10, _catchException10
);
1571 exceptionHandler (11, _catchException11
);
1572 exceptionHandler (12, _catchException12
);
1573 exceptionHandler (13, _catchException13
);
1574 exceptionHandler (14, _catchException14
);
1575 exceptionHandler (15, _catchException15
);
1576 exceptionHandler (16, _catchException16
);
1577 /* exceptionHandler (17, _catchException17); */
1579 /* In case GDB is started before us, ack any packets (presumably
1580 "$?#xx") sitting there. */
1586 /* This function will generate a breakpoint exception. It is used at the
1587 beginning of a program to sync up with a debugger and can be used
1588 otherwise as a quick means to stop program execution and "break" into
1591 #define BREAKPOINT() asm volatile (" trap #2");
1601 Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
1602 Functions: gdb_putchar(char ch)
1604 gdb_write(char *str, int len)
1605 gdb_error(char *format, char *parm)
1608 /* Function: gdb_putchar(int)
1609 Make gdb write a char to stdout.
1610 Returns: the char */
1619 buf
[1] = hexchars
[ch
>> 4];
1620 buf
[2] = hexchars
[ch
& 0x0F];
1626 /* Function: gdb_write(char *, int)
1627 Make gdb write n bytes to stdout (not assumed to be null-terminated).
1628 Returns: number of bytes written */
1631 gdb_write(data
, len
)
1638 buf
= remcomOutBuffer
;
1644 i
< len
&& cpy
< buf
+ sizeof(remcomOutBuffer
) - 3;
1647 *cpy
++ = hexchars
[data
[i
] >> 4];
1648 *cpy
++ = hexchars
[data
[i
] & 0x0F];
1656 /* Function: gdb_puts(char *)
1657 Make gdb write a null-terminated string to stdout.
1658 Returns: the length of the string */
1664 return gdb_write(str
, strlen(str
));
1667 /* Function: gdb_error(char *, char *)
1668 Send an error message to gdb's stdout.
1669 First string may have 1 (one) optional "%s" in it, which
1670 will cause the optional second string to be inserted. */
1673 gdb_error(format
, parm
)
1677 char buf
[400], *cpy
;
1682 if (format
&& *format
)
1683 len
= strlen(format
);
1685 return; /* empty input */
1688 len
+= strlen(parm
);
1690 for (cpy
= buf
; *format
; )
1692 if (format
[0] == '%' && format
[1] == 's') /* include second string */
1694 format
+= 2; /* advance two chars instead of just one */
1695 while (parm
&& *parm
)
1706 static unsigned char *
1707 strcpy (unsigned char *dest
, const unsigned char *src
)
1709 unsigned char *ret
= dest
;
1721 strlen (const unsigned char *src
)
1725 for (ret
= 0; *src
; src
++)
1738 int atexit (void *p
)
This page took 0.076797 seconds and 4 git commands to generate.