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 unsigned char *getpacket(void);
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
)
207 int sigval
, stepping
;
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
);
312 remcomOutBuffer
[0] = 0;
316 default: /* Unknown code. Return an empty reply message. */
319 if (hexToInt (&ptr
, &addr
))
320 registers
[PC
] = addr
;
321 strcpy(remcomOutBuffer
, "OK");
324 strcpy(remcomOutBuffer
, "OK");
326 case 'X': /* XAA..AA,LLLL:<binary data>#cs */
328 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
329 /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
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");
355 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
356 /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
357 if (hexToInt(&ptr
,&addr
))
359 if (hexToInt(&ptr
,&length
))
363 mem2hex((unsigned char*) addr
, remcomOutBuffer
, length
, 1);
365 strcpy (remcomOutBuffer
, "E03");
366 gdb_error ("memory fault", "");
371 strcpy(remcomOutBuffer
,"E01");
375 remcomOutBuffer
[0] = 'S';
376 remcomOutBuffer
[1] = hexchars
[sigval
>> 4];
377 remcomOutBuffer
[2] = hexchars
[sigval
% 16];
378 remcomOutBuffer
[3] = 0;
381 remote_debug
= !(remote_debug
); /* toggle debug flag */
383 case 'g': /* return the value of the CPU registers */
384 mem2hex((unsigned char*) registers
, remcomOutBuffer
, NUMREGBYTES
, 0);
386 case 'P': /* set the value of a single CPU register - return OK */
390 if (hexToInt (&ptr
, ®no
) && *ptr
++ == '=')
391 if (regno
>= 0 && regno
< NUMREGS
)
395 hex2mem (ptr
, (unsigned char *) ®isters
[regno
], 4, 0);
397 * Since we just changed a single CPU register, let's
398 * make sure to keep the several stack pointers consistant.
400 stackmode
= registers
[PSW
] & 0x80;
401 if (regno
== R15
) /* stack pointer changed */
402 { /* need to change SPI or SPU */
404 registers
[SPI
] = registers
[R15
];
406 registers
[SPU
] = registers
[R15
];
408 else if (regno
== SPU
) /* "user" stack pointer changed */
410 if (stackmode
!= 0) /* stack in user mode: copy SP */
411 registers
[R15
] = registers
[SPU
];
413 else if (regno
== SPI
) /* "interrupt" stack pointer changed */
415 if (stackmode
== 0) /* stack in interrupt mode: copy SP */
416 registers
[R15
] = registers
[SPI
];
418 else if (regno
== PSW
) /* stack mode may have changed! */
419 { /* force SP to either SPU or SPI */
420 if (stackmode
== 0) /* stack in user mode */
421 registers
[R15
] = registers
[SPI
];
422 else /* stack in interrupt mode */
423 registers
[R15
] = registers
[SPU
];
425 strcpy (remcomOutBuffer
, "OK");
428 strcpy (remcomOutBuffer
, "E01");
431 case 'G': /* set the value of the CPU registers - return OK */
432 hex2mem(ptr
, (unsigned char*) registers
, NUMREGBYTES
, 0);
433 strcpy(remcomOutBuffer
,"OK");
435 case 's': /* sAA..AA Step one instruction from AA..AA(optional) */
437 case 'c': /* cAA..AA Continue from address AA..AA(optional) */
438 /* try to read optional parameter, pc unchanged if no parm */
439 if (hexToInt(&ptr
,&addr
))
440 registers
[ PC
] = addr
;
442 if (stepping
) /* single-stepping */
444 if (!prepare_to_step(0)) /* set up for single-step */
446 /* prepare_to_step has already emulated the target insn:
447 Send SIGTRAP to gdb, don't resume the target at all. */
448 ptr
= remcomOutBuffer
;
449 *ptr
++ = 'T'; /* Simulate stopping with SIGTRAP */
453 *ptr
++ = hexchars
[PC
>> 4]; /* send PC */
454 *ptr
++ = hexchars
[PC
& 0xf];
456 ptr
= mem2hex((unsigned char *)®isters
[PC
], ptr
, 4, 0);
459 *ptr
++ = hexchars
[R13
>> 4]; /* send FP */
460 *ptr
++ = hexchars
[R13
& 0xf];
462 ptr
= mem2hex((unsigned char *)®isters
[R13
], ptr
, 4, 0);
465 *ptr
++ = hexchars
[R15
>> 4]; /* send SP */
466 *ptr
++ = hexchars
[R15
& 0xf];
468 ptr
= mem2hex((unsigned char *)®isters
[R15
], ptr
, 4, 0);
475 else /* continuing, not single-stepping */
477 /* OK, about to do a "continue". First check to see if the
478 target pc is on an odd boundary (second instruction in the
479 word). If so, we must do a single-step first, because
480 ya can't jump or return back to an odd boundary! */
481 if ((registers
[PC
] & 2) != 0)
487 case 'D': /* Detach */
489 /* I am interpreting this to mean, release the board from control
490 by the remote stub. To do this, I am restoring the original
491 (or at least previous) exception vectors.
493 for (i
= 0; i
< 18; i
++)
494 exceptionHandler (i
, save_vectors
[i
]);
496 return; /* continue the inferior */
498 strcpy(remcomOutBuffer
,"OK");
507 unsigned long start
, len
, our_crc
;
509 if (hexToInt (&ptr
, (int *) &start
) &&
511 hexToInt (&ptr
, (int *) &len
))
513 remcomOutBuffer
[0] = 'C';
514 our_crc
= crc32 ((unsigned char *) start
, len
, 0xffffffff);
515 mem2hex ((char *) &our_crc
,
519 } /* else do nothing */
520 } /* else do nothing */
523 case 'k': /* kill the program */
527 /* reply to the request */
528 putpacket(remcomOutBuffer
);
534 /* Table used by the crc32 function to calcuate the checksum. */
535 static unsigned long crc32_table
[256] = {0, 0};
538 crc32 (unsigned char *buf
, int len
, unsigned long crc
)
540 if (! crc32_table
[1])
542 /* Initialize the CRC table and the decoding table. */
546 for (i
= 0; i
< 256; i
++)
548 for (c
= i
<< 24, j
= 8; j
> 0; --j
)
549 c
= c
& 0x80000000 ? (c
<< 1) ^ 0x04c11db7 : (c
<< 1);
556 crc
= (crc
<< 8) ^ crc32_table
[((crc
>> 24) ^ *buf
) & 255];
563 hex (unsigned char ch
)
565 if ((ch
>= 'a') && (ch
<= 'f')) return (ch
-'a'+10);
566 if ((ch
>= '0') && (ch
<= '9')) return (ch
-'0');
567 if ((ch
>= 'A') && (ch
<= 'F')) return (ch
-'A'+10);
571 /* scan for the sequence $<data>#<checksum> */
576 unsigned char *buffer
= &remcomInBuffer
[0];
577 unsigned char checksum
;
578 unsigned char xmitcsum
;
584 /* wait around for the start character, ignore all other characters */
585 while ((ch
= getDebugChar ()) != '$')
593 /* now, read until a # or end of buffer is found */
594 while (count
< BUFMAX
)
596 ch
= getDebugChar ();
601 checksum
= checksum
+ ch
;
609 ch
= getDebugChar ();
610 xmitcsum
= hex (ch
) << 4;
611 ch
= getDebugChar ();
612 xmitcsum
+= hex (ch
);
614 if (checksum
!= xmitcsum
)
618 unsigned char buf
[16];
620 mem2hex((unsigned char *) &checksum
, buf
, 4, 0);
621 gdb_error("Bad checksum: my count = %s, ", buf
);
622 mem2hex((unsigned char *) &xmitcsum
, buf
, 4, 0);
623 gdb_error("sent count = %s\n", buf
);
624 gdb_error(" -- Bad buffer: \"%s\"\n", buffer
);
626 putDebugChar ('-'); /* failed checksum */
630 putDebugChar ('+'); /* successful transfer */
632 /* if a sequence char is present, reply the sequence ID */
633 if (buffer
[2] == ':')
635 putDebugChar (buffer
[0]);
636 putDebugChar (buffer
[1]);
647 /* send the packet in buffer. */
650 putpacket (unsigned char *buffer
)
652 unsigned char checksum
;
656 /* $<packet info>#<checksum>. */
662 while (ch
=buffer
[count
]) {
668 putDebugChar(hexchars
[checksum
>> 4]);
669 putDebugChar(hexchars
[checksum
% 16]);
670 } while (getDebugChar() != '+');
673 /* Address of a routine to RTE to if we get a memory fault. */
675 static void (*volatile mem_fault_routine
)() = 0;
683 /* Check the address for safe access ranges. As currently defined,
684 this routine will reject the "expansion bus" address range(s).
685 To make those ranges useable, someone must implement code to detect
686 whether there's anything connected to the expansion bus. */
689 mem_safe (unsigned char *addr
)
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
707 get_char (unsigned char *addr
)
710 if (mem_fault_routine
&& !mem_safe(addr
))
712 mem_fault_routine ();
720 set_char (unsigned char *addr
, unsigned char val
)
723 if (mem_fault_routine
&& !mem_safe (addr
))
725 mem_fault_routine ();
732 /* Convert the memory pointed to by mem into hex, placing result in buf.
733 Return a pointer to the last char put in buf (null).
734 If MAY_FAULT is non-zero, then we should set mem_err in response to
735 a fault; if zero treat a fault like any other fault in the stub. */
737 static unsigned char *
738 mem2hex (unsigned char *mem
, unsigned char *buf
, int count
, int may_fault
)
744 mem_fault_routine
= set_mem_err
;
745 for (i
=0;i
<count
;i
++) {
746 ch
= get_char (mem
++);
747 if (may_fault
&& mem_err
)
749 *buf
++ = hexchars
[ch
>> 4];
750 *buf
++ = hexchars
[ch
% 16];
754 mem_fault_routine
= 0;
758 /* Convert the hex array pointed to by buf into binary to be placed in mem.
759 Return a pointer to the character AFTER the last byte written. */
761 static unsigned char*
762 hex2mem (unsigned char *buf
, unsigned char *mem
, int count
, int may_fault
)
768 mem_fault_routine
= set_mem_err
;
769 for (i
=0;i
<count
;i
++) {
770 ch
= hex(*buf
++) << 4;
771 ch
= ch
+ hex(*buf
++);
772 set_char (mem
++, ch
);
773 if (may_fault
&& mem_err
)
777 mem_fault_routine
= 0;
781 /* Convert the binary stream in BUF to memory.
783 Gdb will escape $, #, and the escape char (0x7d).
784 COUNT is the total number of bytes to write into
786 static unsigned char *
787 bin2mem (unsigned char *buf
, unsigned char *mem
, int count
, int may_fault
)
793 mem_fault_routine
= set_mem_err
;
794 for (i
= 0; i
< count
; i
++)
796 /* Check for any escaped characters. Be paranoid and
797 only unescape chars that should be escaped. */
804 case 0x5d: /* escape char */
814 set_char (mem
++, *buf
++);
816 if (may_fault
&& mem_err
)
821 mem_fault_routine
= 0;
825 /* this function takes the m32r exception vector and attempts to
826 translate this number into a unix compatible signal value */
829 computeSignal (int exceptionVector
)
832 switch (exceptionVector
) {
833 case 0 : sigval
= 23; break; /* I/O trap */
834 case 1 : sigval
= 5; break; /* breakpoint */
835 case 2 : sigval
= 5; break; /* breakpoint */
836 case 3 : sigval
= 5; break; /* breakpoint */
837 case 4 : sigval
= 5; break; /* breakpoint */
838 case 5 : sigval
= 5; break; /* breakpoint */
839 case 6 : sigval
= 5; break; /* breakpoint */
840 case 7 : sigval
= 5; break; /* breakpoint */
841 case 8 : sigval
= 5; break; /* breakpoint */
842 case 9 : sigval
= 5; break; /* breakpoint */
843 case 10 : sigval
= 5; break; /* breakpoint */
844 case 11 : sigval
= 5; break; /* breakpoint */
845 case 12 : sigval
= 5; break; /* breakpoint */
846 case 13 : sigval
= 5; break; /* breakpoint */
847 case 14 : sigval
= 5; break; /* breakpoint */
848 case 15 : sigval
= 5; break; /* breakpoint */
849 case 16 : sigval
= 10; break; /* BUS ERROR (alignment) */
850 case 17 : sigval
= 2; break; /* INTerrupt */
851 default : sigval
= 7; break; /* "software generated" */
856 /**********************************************/
857 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
858 /* RETURN NUMBER OF CHARS PROCESSED */
859 /**********************************************/
861 hexToInt (unsigned char **ptr
, int *intValue
)
869 hexValue
= hex(**ptr
);
872 *intValue
= (*intValue
<<4) | hexValue
;
883 Table of branch instructions:
885 10B6 RTE return from trap or exception
887 1ECr JL jump and link
889 FFxxxxxx BRA branch (long)
890 B09rxxxx BNEZ branch not-equal-zero
891 Br1rxxxx BNE branch not-equal
892 7Dxx BNC branch not-condition
893 FDxxxxxx BNC branch not-condition (long)
894 B0Arxxxx BLTZ branch less-than-zero
895 B0Crxxxx BLEZ branch less-equal-zero
896 7Exx BL branch and link
897 FExxxxxx BL branch and link (long)
898 B0Drxxxx BGTZ branch greater-than-zero
899 B0Brxxxx BGEZ branch greater-equal-zero
900 B08rxxxx BEQZ branch equal-zero
901 Br0rxxxx BEQ branch equal
902 7Cxx BC branch condition
903 FCxxxxxx BC branch condition (long)
907 isShortBranch (unsigned char *instr
)
909 unsigned char instr0
= instr
[0] & 0x7F; /* mask off high bit */
911 if (instr0
== 0x10 && instr
[1] == 0xB6) /* RTE */
912 return 1; /* return from trap or exception */
914 if (instr0
== 0x1E || instr0
== 0x1F) /* JL or JMP */
915 if ((instr
[1] & 0xF0) == 0xC0)
916 return 2; /* jump thru a register */
918 if (instr0
== 0x7C || instr0
== 0x7D || /* BC, BNC, BL, BRA */
919 instr0
== 0x7E || instr0
== 0x7F)
920 return 3; /* eight bit PC offset */
926 isLongBranch (unsigned char *instr
)
928 if (instr
[0] == 0xFC || instr
[0] == 0xFD || /* BRA, BNC, BL, BC */
929 instr
[0] == 0xFE || instr
[0] == 0xFF) /* 24 bit relative */
931 if ((instr
[0] & 0xF0) == 0xB0) /* 16 bit relative */
933 if ((instr
[1] & 0xF0) == 0x00 || /* BNE, BEQ */
934 (instr
[1] & 0xF0) == 0x10)
936 if (instr
[0] == 0xB0) /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
937 if ((instr
[1] & 0xF0) == 0x80 || (instr
[1] & 0xF0) == 0x90 ||
938 (instr
[1] & 0xF0) == 0xA0 || (instr
[1] & 0xF0) == 0xB0 ||
939 (instr
[1] & 0xF0) == 0xC0 || (instr
[1] & 0xF0) == 0xD0)
945 /* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
946 then it's a 2-byte instruction, else it's a 4-byte instruction. */
948 #define INSTRUCTION_SIZE(addr) \
949 ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
952 isBranch (unsigned char *instr
)
954 if (INSTRUCTION_SIZE(instr
) == 2)
955 return isShortBranch(instr
);
957 return isLongBranch(instr
);
961 willBranch (unsigned char *instr
, int branchCode
)
965 case 0: return 0; /* not a branch */
966 case 1: return 1; /* RTE */
967 case 2: return 1; /* JL or JMP */
968 case 3: /* BC, BNC, BL, BRA (short) */
969 case 4: /* BC, BNC, BL, BRA (long) */
970 switch (instr
[0] & 0x0F)
972 case 0xC: /* Branch if Condition Register */
973 return (registers
[CBR
] != 0);
974 case 0xD: /* Branch if NOT Condition Register */
975 return (registers
[CBR
] == 0);
976 case 0xE: /* Branch and Link */
977 case 0xF: /* Branch (unconditional) */
982 case 5: /* BNE, BEQ */
983 switch (instr
[1] & 0xF0)
985 case 0x00: /* Branch if r1 equal to r2 */
986 return (registers
[instr
[0] & 0x0F] == registers
[instr
[1] & 0x0F]);
987 case 0x10: /* Branch if r1 NOT equal to r2 */
988 return (registers
[instr
[0] & 0x0F] != registers
[instr
[1] & 0x0F]);
992 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
993 switch (instr
[1] & 0xF0)
995 case 0x80: /* Branch if reg equal to zero */
996 return (registers
[instr
[1] & 0x0F] == 0);
997 case 0x90: /* Branch if reg NOT equal to zero */
998 return (registers
[instr
[1] & 0x0F] != 0);
999 case 0xA0: /* Branch if reg less than zero */
1000 return (registers
[instr
[1] & 0x0F] < 0);
1001 case 0xB0: /* Branch if reg greater or equal to zero */
1002 return (registers
[instr
[1] & 0x0F] >= 0);
1003 case 0xC0: /* Branch if reg less than or equal to zero */
1004 return (registers
[instr
[1] & 0x0F] <= 0);
1005 case 0xD0: /* Branch if reg greater than zero */
1006 return (registers
[instr
[1] & 0x0F] > 0);
1007 default: /* oops? */
1010 default: /* oops? */
1016 branchDestination (unsigned char *instr
, int branchCode
)
1018 switch (branchCode
) {
1020 case 0: /* not a branch */
1023 return registers
[BPC
] & ~3; /* pop BPC into PC */
1024 case 2: /* JL or JMP */
1025 return registers
[instr
[1] & 0x0F] & ~3; /* jump thru a register */
1026 case 3: /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
1027 return (((int) instr
) & ~3) + ((char) instr
[1] << 2);
1028 case 4: /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
1029 return ((int) instr
+
1030 ((((char) instr
[1] << 16) | (instr
[2] << 8) | (instr
[3])) << 2));
1031 case 5: /* BNE, BEQ (16-bit relative offset) */
1032 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
1033 return ((int) instr
+ ((((char) instr
[2] << 8) | (instr
[3])) << 2));
1036 /* An explanatory note: in the last three return expressions, I have
1037 cast the most-significant byte of the return offset to char.
1038 What this accomplishes is sign extension. If the other
1039 less-significant bytes were signed as well, they would get sign
1040 extended too and, if negative, their leading bits would clobber
1041 the bits of the more-significant bytes ahead of them. There are
1042 other ways I could have done this, but sign extension from
1043 odd-sized integers is always a pain. */
1047 branchSideEffects (unsigned char *instr
, int branchCode
)
1052 return; /* I <THINK> this is already handled... */
1053 case 2: /* JL (or JMP) */
1054 case 3: /* BL (or BC, BNC, BRA) */
1056 if ((instr
[0] & 0x0F) == 0x0E) /* branch/jump and link */
1057 registers
[R14
] = (registers
[PC
] & ~3) + 4;
1059 default: /* any other branch has no side effects */
1064 static struct STEPPING_CONTEXT
{
1065 int stepping
; /* true when we've started a single-step */
1066 unsigned long target_addr
; /* the instr we're trying to execute */
1067 unsigned long target_size
; /* the size of the target instr */
1068 unsigned long noop_addr
; /* where we've inserted a no-op, if any */
1069 unsigned long trap1_addr
; /* the trap following the target instr */
1070 unsigned long trap2_addr
; /* the trap at a branch destination, if any */
1071 unsigned short noop_save
; /* instruction overwritten by our no-op */
1072 unsigned short trap1_save
; /* instruction overwritten by trap1 */
1073 unsigned short trap2_save
; /* instruction overwritten by trap2 */
1074 unsigned short continue_p
; /* true if NOT returning to gdb after step */
1077 /* Function: prepare_to_step
1078 Called from handle_exception to prepare the user program to single-step.
1079 Places a trap instruction after the target instruction, with special
1080 extra handling for branch instructions and for instructions in the
1081 second half-word of a word.
1083 Returns: True if we should actually execute the instruction;
1084 False if we are going to emulate executing the instruction,
1085 in which case we simply report to GDB that the instruction
1086 has already been executed. */
1088 #define TRAP1 0x10f1; /* trap #1 instruction */
1089 #define NOOP 0x7000; /* noop instruction */
1091 static unsigned short trap1
= TRAP1
;
1092 static unsigned short noop
= NOOP
;
1095 prepare_to_step(continue_p
)
1096 int continue_p
; /* if this isn't REALLY a single-step (see below) */
1098 unsigned long pc
= registers
[PC
];
1099 int branchCode
= isBranch((unsigned char *) pc
);
1102 /* zero out the stepping context
1103 (paranoia -- it should already be zeroed) */
1104 for (p
= (unsigned char *) &stepping
;
1105 p
< ((unsigned char *) &stepping
) + sizeof(stepping
);
1109 if (branchCode
!= 0) /* next instruction is a branch */
1111 branchSideEffects((unsigned char *) pc
, branchCode
);
1112 if (willBranch((unsigned char *)pc
, branchCode
))
1113 registers
[PC
] = branchDestination((unsigned char *) pc
, branchCode
);
1115 registers
[PC
] = pc
+ INSTRUCTION_SIZE(pc
);
1116 return 0; /* branch "executed" -- just notify GDB */
1118 else if (((int) pc
& 2) != 0) /* "second-slot" instruction */
1120 /* insert no-op before pc */
1121 stepping
.noop_addr
= pc
- 2;
1122 stepping
.noop_save
= *(unsigned short *) stepping
.noop_addr
;
1123 *(unsigned short *) stepping
.noop_addr
= noop
;
1124 /* insert trap after pc */
1125 stepping
.trap1_addr
= pc
+ 2;
1126 stepping
.trap1_save
= *(unsigned short *) stepping
.trap1_addr
;
1127 *(unsigned short *) stepping
.trap1_addr
= trap1
;
1129 else /* "first-slot" instruction */
1131 /* insert trap after pc */
1132 stepping
.trap1_addr
= pc
+ INSTRUCTION_SIZE(pc
);
1133 stepping
.trap1_save
= *(unsigned short *) stepping
.trap1_addr
;
1134 *(unsigned short *) stepping
.trap1_addr
= trap1
;
1136 /* "continue_p" means that we are actually doing a continue, and not
1137 being requested to single-step by GDB. Sometimes we have to do
1138 one single-step before continuing, because the PC is on a half-word
1139 boundary. There's no way to simply resume at such an address. */
1140 stepping
.continue_p
= continue_p
;
1141 stepping
.stepping
= 1; /* starting a single-step */
1145 /* Function: finish_from_step
1146 Called from handle_exception to finish up when the user program
1147 returns from a single-step. Replaces the instructions that had
1148 been overwritten by traps or no-ops,
1150 Returns: True if we should notify GDB that the target stopped.
1151 False if we only single-stepped because we had to before we
1152 could continue (ie. we were trying to continue at a
1153 half-word boundary). In that case don't notify GDB:
1154 just "continue continuing". */
1157 finish_from_step (void)
1159 if (stepping
.stepping
) /* anything to do? */
1161 int continue_p
= stepping
.continue_p
;
1164 if (stepping
.noop_addr
) /* replace instr "under" our no-op */
1165 *(unsigned short *) stepping
.noop_addr
= stepping
.noop_save
;
1166 if (stepping
.trap1_addr
) /* replace instr "under" our trap */
1167 *(unsigned short *) stepping
.trap1_addr
= stepping
.trap1_save
;
1168 if (stepping
.trap2_addr
) /* ditto our other trap, if any */
1169 *(unsigned short *) stepping
.trap2_addr
= stepping
.trap2_save
;
1171 for (p
= (unsigned char *) &stepping
; /* zero out the stepping context */
1172 p
< ((unsigned char *) &stepping
) + sizeof(stepping
);
1176 return !(continue_p
);
1178 else /* we didn't single-step, therefore this must be a legitimate stop */
1182 struct PSWreg
{ /* separate out the bit flags in the PSW register */
1194 /* Upon entry the value for LR to save has been pushed.
1195 We unpush that so that the value for the stack pointer saved is correct.
1196 Upon entry, all other registers are assumed to have not been modified
1197 since the interrupt/trap occured. */
1203 seth r1, #shigh(registers)
1204 add3 r1, r1, #low(registers)
1209 addi r1, #4 ; only add 4 as subsequent saves are `pre inc'
1224 st sp, @+r1 ; sp contains right value at this point
1226 st r0, @+r1 ; cr0 == PSW
1228 st r0, @+r1 ; cr1 == CBR
1230 st r0, @+r1 ; cr2 == SPI
1232 st r0, @+r1 ; cr3 == SPU
1234 st r0, @+r1 ; cr6 == BPC
1235 st r0, @+r1 ; PC == BPC
1242 /* C routine to clean up what stash_registers did.
1243 It is called after calling stash_registers.
1244 This is separate from stash_registers as we want to do this in C
1245 but doing stash_registers in C isn't straightforward. */
1248 cleanup_stash (void)
1250 psw
= (struct PSWreg
*) ®isters
[PSW
]; /* fields of PSW register */
1251 psw
->sm
= psw
->bsm
; /* fix up pre-trap values of psw fields */
1254 registers
[CBR
] = psw
->bc
; /* fix up pre-trap "C" register */
1256 #if 0 /* FIXME: Was in previous version. Necessary?
1257 (Remember that we use the "rte" insn to return from the
1258 trap/interrupt so the values of bsm, bie, bc are important. */
1259 psw
->bsm
= psw
->bie
= psw
->bc
= 0; /* zero post-trap values */
1262 /* FIXME: Copied from previous version. This can probably be deleted
1263 since methinks stash_registers has already done this. */
1264 registers
[PC
] = registers
[BPC
]; /* pre-trap PC */
1266 /* FIXME: Copied from previous version. Necessary? */
1267 if (psw
->sm
) /* copy R15 into (psw->sm ? SPU : SPI) */
1268 registers
[SPU
] = registers
[R15
];
1270 registers
[SPI
] = registers
[R15
];
1275 seth r0, #shigh(registers+8)
1276 add3 r0, r0, #low(registers+8)
1277 ld r2, @r0+ ; restore r2
1278 ld r3, @r0+ ; restore r3
1279 ld r4, @r0+ ; restore r4
1280 ld r5, @r0+ ; restore r5
1281 ld r6, @r0+ ; restore r6
1282 ld r7, @r0+ ; restore r7
1283 ld r8, @r0+ ; restore r8
1284 ld r9, @r0+ ; restore r9
1285 ld r10, @r0+ ; restore r10
1286 ld r11, @r0+ ; restore r11
1287 ld r12, @r0+ ; restore r12
1288 ld r13, @r0+ ; restore r13
1289 ld r14, @r0+ ; restore r14
1290 ld r15, @r0+ ; restore r15
1291 ld r1, @r0+ ; restore cr0 == PSW
1293 ld r1, @r0+ ; restore cr1 == CBR (no-op, because it's read only)
1295 ld r1, @r0+ ; restore cr2 == SPI
1297 ld r1, @r0+ ; restore cr3 == SPU
1299 addi r0, #4 ; skip BPC
1300 ld r1, @r0+ ; restore cr6 (BPC) == PC
1302 ld r1, @r0+ ; restore ACCL
1304 ld r1, @r0+ ; restore ACCH
1306 seth r0, #shigh(registers)
1307 add3 r0, r0, #low(registers)
1308 ld r1, @(4,r0) ; restore r1
1309 ld r0, @r0 ; restore r0
1312 /* General trap handler, called after the registers have been stashed.
1313 NUM is the trap/exception number. */
1316 process_exception (int num
)
1320 seth r1, #shigh(stackPtr)
1321 add3 r1, r1, #low(stackPtr)
1322 ld r15, @r1 ; setup local stack (protect user stack)
1325 bl restore_and_return"
1326 : : "r" (num
) : "r0", "r1");
1329 void _catchException0 ();
1335 ; Note that at this point the pushed value of `lr' has been popped
1337 bl process_exception");
1339 void _catchException1 ();
1345 ; Note that at this point the pushed value of `lr' has been popped
1347 seth r1, #shigh(stackPtr)
1348 add3 r1, r1, #low(stackPtr)
1349 ld r15, @r1 ; setup local stack (protect user stack)
1350 seth r1, #shigh(registers + 21*4) ; PC
1351 add3 r1, r1, #low(registers + 21*4)
1353 addi r0, #-4 ; back up PC for breakpoint trap.
1354 st r0, @r1 ; FIXME: what about bp in right slot?
1357 bl restore_and_return");
1359 void _catchException2 ();
1365 ; Note that at this point the pushed value of `lr' has been popped
1367 bl process_exception");
1369 void _catchException3 ();
1375 ; Note that at this point the pushed value of `lr' has been popped
1377 bl process_exception");
1379 void _catchException4 ();
1385 ; Note that at this point the pushed value of `lr' has been popped
1387 bl process_exception");
1389 void _catchException5 ();
1395 ; Note that at this point the pushed value of `lr' has been popped
1397 bl process_exception");
1399 void _catchException6 ();
1405 ; Note that at this point the pushed value of `lr' has been popped
1407 bl process_exception");
1409 void _catchException7 ();
1415 ; Note that at this point the pushed value of `lr' has been popped
1417 bl process_exception");
1419 void _catchException8 ();
1425 ; Note that at this point the pushed value of `lr' has been popped
1427 bl process_exception");
1429 void _catchException9 ();
1435 ; Note that at this point the pushed value of `lr' has been popped
1437 bl process_exception");
1439 void _catchException10 ();
1445 ; Note that at this point the pushed value of `lr' has been popped
1447 bl process_exception");
1449 void _catchException11 ();
1455 ; Note that at this point the pushed value of `lr' has been popped
1457 bl process_exception");
1459 void _catchException12 ();
1465 ; Note that at this point the pushed value of `lr' has been popped
1467 bl process_exception");
1469 void _catchException13 ();
1475 ; Note that at this point the pushed value of `lr' has been popped
1477 bl process_exception");
1479 void _catchException14 ();
1485 ; Note that at this point the pushed value of `lr' has been popped
1487 bl process_exception");
1489 void _catchException15 ();
1495 ; Note that at this point the pushed value of `lr' has been popped
1497 bl process_exception");
1499 void _catchException16 ();
1505 ; Note that at this point the pushed value of `lr' has been popped
1507 bl process_exception");
1509 void _catchException17 ();
1515 ; Note that at this point the pushed value of `lr' has been popped
1517 bl process_exception");
1520 /* this function is used to set up exception handlers for tracing and
1523 set_debug_traps (void)
1525 /* extern void remcomHandler(); */
1528 for (i
= 0; i
< 18; i
++) /* keep a copy of old vectors */
1529 if (save_vectors
[i
] == 0) /* only copy them the first time */
1530 save_vectors
[i
] = getExceptionHandler (i
);
1532 stackPtr
= &remcomStack
[STACKSIZE
/sizeof(int) - 1];
1534 exceptionHandler (0, _catchException0
);
1535 exceptionHandler (1, _catchException1
);
1536 exceptionHandler (2, _catchException2
);
1537 exceptionHandler (3, _catchException3
);
1538 exceptionHandler (4, _catchException4
);
1539 exceptionHandler (5, _catchException5
);
1540 exceptionHandler (6, _catchException6
);
1541 exceptionHandler (7, _catchException7
);
1542 exceptionHandler (8, _catchException8
);
1543 exceptionHandler (9, _catchException9
);
1544 exceptionHandler (10, _catchException10
);
1545 exceptionHandler (11, _catchException11
);
1546 exceptionHandler (12, _catchException12
);
1547 exceptionHandler (13, _catchException13
);
1548 exceptionHandler (14, _catchException14
);
1549 exceptionHandler (15, _catchException15
);
1550 exceptionHandler (16, _catchException16
);
1551 /* exceptionHandler (17, _catchException17); */
1556 /* This function will generate a breakpoint exception. It is used at the
1557 beginning of a program to sync up with a debugger and can be used
1558 otherwise as a quick means to stop program execution and "break" into
1561 #define BREAKPOINT() asm volatile (" trap #2");
1571 Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
1572 Functions: gdb_putchar(char ch)
1574 gdb_write(char *str, int len)
1575 gdb_error(char *format, char *parm)
1578 /* Function: gdb_putchar(int)
1579 Make gdb write a char to stdout.
1580 Returns: the char */
1583 gdb_putchar (int ch
)
1588 buf
[1] = hexchars
[ch
>> 4];
1589 buf
[2] = hexchars
[ch
& 0x0F];
1595 /* Function: gdb_write(char *, int)
1596 Make gdb write n bytes to stdout (not assumed to be null-terminated).
1597 Returns: number of bytes written */
1600 gdb_write (char *data
, int len
)
1605 buf
= remcomOutBuffer
;
1611 i
< len
&& cpy
< buf
+ sizeof(remcomOutBuffer
) - 3;
1614 *cpy
++ = hexchars
[data
[i
] >> 4];
1615 *cpy
++ = hexchars
[data
[i
] & 0x0F];
1623 /* Function: gdb_puts(char *)
1624 Make gdb write a null-terminated string to stdout.
1625 Returns: the length of the string */
1628 gdb_puts (char *str
)
1630 return gdb_write(str
, strlen(str
));
1633 /* Function: gdb_error(char *, char *)
1634 Send an error message to gdb's stdout.
1635 First string may have 1 (one) optional "%s" in it, which
1636 will cause the optional second string to be inserted. */
1639 gdb_error (char *format
, char *parm
)
1641 char buf
[400], *cpy
;
1646 if (format
&& *format
)
1647 len
= strlen(format
);
1649 return; /* empty input */
1652 len
+= strlen(parm
);
1654 for (cpy
= buf
; *format
; )
1656 if (format
[0] == '%' && format
[1] == 's') /* include second string */
1658 format
+= 2; /* advance two chars instead of just one */
1659 while (parm
&& *parm
)
1670 static unsigned char *
1671 strcpy (unsigned char *dest
, const unsigned char *src
)
1673 unsigned char *ret
= dest
;
1685 strlen (const unsigned char *src
)
1689 for (ret
= 0; *src
; src
++)
1702 int atexit (void *p
)
This page took 0.063757 seconds and 4 git commands to generate.