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)
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
153 static int registers
[NUMREGS
];
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];
161 static unsigned int save_vectors
[18]; /* previous exception vectors */
163 /* Indicate to caller of mem2hex or hex2mem that there has been an error. */
164 static volatile int mem_err
= 0;
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;
171 #include "syscall.h" /* for SYS_exit, SYS_write etc. */
174 /* Global entry points:
177 extern void handle_exception (int);
178 extern void set_debug_traps (void);
179 extern void breakpoint (void);
184 static int computeSignal (int);
185 static void putpacket (unsigned char *);
186 static unsigned char *getpacket (void);
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);
198 static void gdb_error (char *, char *);
199 static int gdb_putchar (int), gdb_puts (char *), gdb_write (char *, int);
201 static unsigned char *strcpy (unsigned char *, const unsigned char *);
202 static int strlen (const unsigned char *);
205 * This function does all command procesing for interfacing to gdb.
209 handle_exception (int exceptionVector
)
211 int sigval
, stepping
;
214 unsigned char buf
[16];
217 if (!finish_from_step ())
218 return; /* "false step": let the target continue */
220 gdb_m32r_vector
= exceptionVector
;
224 mem2hex ((unsigned char *) &exceptionVector
, buf
, 4, 0);
225 gdb_error ("Handle exception %s, ", buf
);
226 mem2hex ((unsigned char *) ®isters
[PC
], buf
, 4, 0);
227 gdb_error ("PC == 0x%s\n", buf
);
230 /* reply to host that an exception has occurred */
231 sigval
= computeSignal (exceptionVector
);
233 ptr
= remcomOutBuffer
;
235 *ptr
++ = 'T'; /* notify gdb with signo, PC, FP and SP */
236 *ptr
++ = hexchars
[sigval
>> 4];
237 *ptr
++ = hexchars
[sigval
& 0xf];
239 *ptr
++ = hexchars
[PC
>> 4];
240 *ptr
++ = hexchars
[PC
& 0xf];
242 ptr
= mem2hex ((unsigned char *) ®isters
[PC
], ptr
, 4, 0); /* PC */
245 *ptr
++ = hexchars
[R13
>> 4];
246 *ptr
++ = hexchars
[R13
& 0xf];
248 ptr
= mem2hex ((unsigned char *) ®isters
[R13
], ptr
, 4, 0); /* FP */
251 *ptr
++ = hexchars
[R15
>> 4];
252 *ptr
++ = hexchars
[R15
& 0xf];
254 ptr
= mem2hex ((unsigned char *) ®isters
[R15
], ptr
, 4, 0); /* SP */
258 if (exceptionVector
== 0) /* simulated SYS call stuff */
260 mem2hex ((unsigned char *) ®isters
[PC
], buf
, 4, 0);
261 switch (registers
[R0
])
264 gdb_error ("Target program has exited at %s\n", buf
);
265 ptr
= remcomOutBuffer
;
267 sigval
= registers
[R1
] & 0xff;
268 *ptr
++ = hexchars
[sigval
>> 4];
269 *ptr
++ = hexchars
[sigval
& 0xf];
273 gdb_error ("Target attempts SYS_open call at %s\n", buf
);
276 gdb_error ("Target attempts SYS_close call at %s\n", buf
);
279 gdb_error ("Target attempts SYS_read call at %s\n", buf
);
282 if (registers
[R1
] == 1 || /* write to stdout */
283 registers
[R1
] == 2) /* write to stderr */
284 { /* (we can do that) */
286 gdb_write ((void *) registers
[R2
], registers
[R3
]);
290 gdb_error ("Target attempts SYS_write call at %s\n", buf
);
293 gdb_error ("Target attempts SYS_lseek call at %s\n", buf
);
296 gdb_error ("Target attempts SYS_unlink call at %s\n", buf
);
299 gdb_error ("Target attempts SYS_getpid call at %s\n", buf
);
302 gdb_error ("Target attempts SYS_kill call at %s\n", buf
);
305 gdb_error ("Target attempts SYS_fstat call at %s\n", buf
);
308 gdb_error ("Target attempts unknown SYS call at %s\n", buf
);
313 putpacket (remcomOutBuffer
);
319 remcomOutBuffer
[0] = 0;
324 default: /* Unknown code. Return an empty reply message. */
327 if (hexToInt (&ptr
, &addr
))
328 registers
[PC
] = addr
;
329 strcpy (remcomOutBuffer
, "OK");
332 strcpy (remcomOutBuffer
, "OK");
334 case 'X': /* XAA..AA,LLLL:<binary data>#cs */
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 */
339 if (hexToInt (&ptr
, &addr
))
341 if (hexToInt (&ptr
, &length
))
346 bin2mem (ptr
, (unsigned char *) addr
, length
, 1);
348 hex2mem (ptr
, (unsigned char *) addr
, length
, 1);
351 strcpy (remcomOutBuffer
, "E03");
352 gdb_error ("memory fault", "");
356 strcpy (remcomOutBuffer
, "OK");
362 strcpy (remcomOutBuffer
, "E02");
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
))
370 if (hexToInt (&ptr
, &length
))
374 mem2hex ((unsigned char *) addr
, remcomOutBuffer
, length
,
378 strcpy (remcomOutBuffer
, "E03");
379 gdb_error ("memory fault", "");
384 strcpy (remcomOutBuffer
, "E01");
388 remcomOutBuffer
[0] = 'S';
389 remcomOutBuffer
[1] = hexchars
[sigval
>> 4];
390 remcomOutBuffer
[2] = hexchars
[sigval
% 16];
391 remcomOutBuffer
[3] = 0;
394 remote_debug
= !(remote_debug
); /* toggle debug flag */
396 case 'g': /* return the value of the CPU registers */
397 mem2hex ((unsigned char *) registers
, remcomOutBuffer
, NUMREGBYTES
,
400 case 'P': /* set the value of a single CPU register - return OK */
404 if (hexToInt (&ptr
, ®no
) && *ptr
++ == '=')
405 if (regno
>= 0 && regno
< NUMREGS
)
409 hex2mem (ptr
, (unsigned char *) ®isters
[regno
], 4, 0);
411 * Since we just changed a single CPU register, let's
412 * make sure to keep the several stack pointers consistant.
414 stackmode
= registers
[PSW
] & 0x80;
415 if (regno
== R15
) /* stack pointer changed */
416 { /* need to change SPI or SPU */
418 registers
[SPI
] = registers
[R15
];
420 registers
[SPU
] = registers
[R15
];
422 else if (regno
== SPU
) /* "user" stack pointer changed */
424 if (stackmode
!= 0) /* stack in user mode: copy SP */
425 registers
[R15
] = registers
[SPU
];
427 else if (regno
== SPI
) /* "interrupt" stack pointer changed */
429 if (stackmode
== 0) /* stack in interrupt mode: copy SP */
430 registers
[R15
] = registers
[SPI
];
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
];
439 strcpy (remcomOutBuffer
, "OK");
442 strcpy (remcomOutBuffer
, "E01");
445 case 'G': /* set the value of the CPU registers - return OK */
446 hex2mem (ptr
, (unsigned char *) registers
, NUMREGBYTES
, 0);
447 strcpy (remcomOutBuffer
, "OK");
449 case 's': /* sAA..AA Step one instruction from AA..AA(optional) */
451 case 'c': /* cAA..AA Continue from address AA..AA(optional) */
452 /* try to read optional parameter, pc unchanged if no parm */
453 if (hexToInt (&ptr
, &addr
))
454 registers
[PC
] = addr
;
456 if (stepping
) /* single-stepping */
458 if (!prepare_to_step (0)) /* set up for single-step */
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 */
467 *ptr
++ = hexchars
[PC
>> 4]; /* send PC */
468 *ptr
++ = hexchars
[PC
& 0xf];
470 ptr
= mem2hex ((unsigned char *) ®isters
[PC
], ptr
, 4, 0);
473 *ptr
++ = hexchars
[R13
>> 4]; /* send FP */
474 *ptr
++ = hexchars
[R13
& 0xf];
477 mem2hex ((unsigned char *) ®isters
[R13
], ptr
, 4, 0);
480 *ptr
++ = hexchars
[R15
>> 4]; /* send SP */
481 *ptr
++ = hexchars
[R15
& 0xf];
484 mem2hex ((unsigned char *) ®isters
[R15
], ptr
, 4, 0);
491 else /* continuing, not single-stepping */
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)
503 case 'D': /* Detach */
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.
509 for (i
= 0; i
< 18; i
++)
510 exceptionHandler (i
, save_vectors
[i
]);
512 return; /* continue the inferior */
514 strcpy (remcomOutBuffer
, "OK");
519 *ptr
++ == 'R' && *ptr
++ == 'C' && *ptr
++ == ':')
521 unsigned long start
, len
, our_crc
;
523 if (hexToInt (&ptr
, (int *) &start
) &&
524 *ptr
++ == ',' && hexToInt (&ptr
, (int *) &len
))
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 */
534 case 'k': /* kill the program */
538 /* reply to the request */
539 putpacket (remcomOutBuffer
);
545 /* Table used by the crc32 function to calcuate the checksum. */
546 static unsigned long crc32_table
[256] = { 0, 0 };
549 crc32 (unsigned char *buf
, int len
, unsigned long crc
)
553 /* Initialize the CRC table and the decoding table. */
557 for (i
= 0; i
< 256; i
++)
559 for (c
= i
<< 24, j
= 8; j
> 0; --j
)
560 c
= c
& 0x80000000 ? (c
<< 1) ^ 0x04c11db7 : (c
<< 1);
567 crc
= (crc
<< 8) ^ crc32_table
[((crc
>> 24) ^ *buf
) & 255];
574 hex (unsigned char ch
)
576 if ((ch
>= 'a') && (ch
<= 'f'))
577 return (ch
- 'a' + 10);
578 if ((ch
>= '0') && (ch
<= '9'))
580 if ((ch
>= 'A') && (ch
<= 'F'))
581 return (ch
- 'A' + 10);
585 /* scan for the sequence $<data>#<checksum> */
590 unsigned char *buffer
= &remcomInBuffer
[0];
591 unsigned char checksum
;
592 unsigned char xmitcsum
;
598 /* wait around for the start character, ignore all other characters */
599 while ((ch
= getDebugChar ()) != '$')
607 /* now, read until a # or end of buffer is found */
608 while (count
< BUFMAX
- 1)
610 ch
= getDebugChar ();
615 checksum
= checksum
+ ch
;
623 ch
= getDebugChar ();
624 xmitcsum
= hex (ch
) << 4;
625 ch
= getDebugChar ();
626 xmitcsum
+= hex (ch
);
628 if (checksum
!= xmitcsum
)
632 unsigned char buf
[16];
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
);
640 putDebugChar ('-'); /* failed checksum */
644 putDebugChar ('+'); /* successful transfer */
646 /* if a sequence char is present, reply the sequence ID */
647 if (buffer
[2] == ':')
649 putDebugChar (buffer
[0]);
650 putDebugChar (buffer
[1]);
661 /* send the packet in buffer. */
664 putpacket (unsigned char *buffer
)
666 unsigned char checksum
;
670 /* $<packet info>#<checksum>. */
677 while (ch
= buffer
[count
])
684 putDebugChar (hexchars
[checksum
>> 4]);
685 putDebugChar (hexchars
[checksum
% 16]);
687 while (getDebugChar () != '+');
690 /* Address of a routine to RTE to if we get a memory fault. */
692 static void (*volatile mem_fault_routine
) () = 0;
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. */
706 mem_safe (unsigned char *addr
)
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)
713 if (addr
< BAD_RANGE_ONE_START
)
715 if (addr
< BAD_RANGE_ONE_END
)
716 return 0; /* unsafe */
717 if (addr
< BAD_RANGE_TWO_START
)
719 if (addr
< BAD_RANGE_TWO_END
)
720 return 0; /* unsafe */
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
728 get_char (unsigned char *addr
)
731 if (mem_fault_routine
&& !mem_safe (addr
))
733 mem_fault_routine ();
741 set_char (unsigned char *addr
, unsigned char val
)
744 if (mem_fault_routine
&& !mem_safe (addr
))
746 mem_fault_routine ();
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. */
758 static unsigned char *
759 mem2hex (unsigned char *mem
, unsigned char *buf
, int count
, int may_fault
)
765 mem_fault_routine
= set_mem_err
;
766 for (i
= 0; i
< count
; i
++)
768 ch
= get_char (mem
++);
769 if (may_fault
&& mem_err
)
771 *buf
++ = hexchars
[ch
>> 4];
772 *buf
++ = hexchars
[ch
% 16];
776 mem_fault_routine
= 0;
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. */
783 static unsigned char *
784 hex2mem (unsigned char *buf
, unsigned char *mem
, int count
, int may_fault
)
790 mem_fault_routine
= set_mem_err
;
791 for (i
= 0; i
< count
; i
++)
793 ch
= hex (*buf
++) << 4;
794 ch
= ch
+ hex (*buf
++);
795 set_char (mem
++, ch
);
796 if (may_fault
&& mem_err
)
800 mem_fault_routine
= 0;
804 /* Convert the binary stream in BUF to memory.
806 Gdb will escape $, #, and the escape char (0x7d).
807 COUNT is the total number of bytes to write into
809 static unsigned char *
810 bin2mem (unsigned char *buf
, unsigned char *mem
, int count
, int may_fault
)
816 mem_fault_routine
= set_mem_err
;
817 for (i
= 0; i
< count
; i
++)
819 /* Check for any escaped characters. Be paranoid and
820 only unescape chars that should be escaped. */
827 case 0x5d: /* escape char */
837 set_char (mem
++, *buf
++);
839 if (may_fault
&& mem_err
)
844 mem_fault_routine
= 0;
848 /* this function takes the m32r exception vector and attempts to
849 translate this number into a unix compatible signal value */
852 computeSignal (int exceptionVector
)
855 switch (exceptionVector
)
859 break; /* I/O trap */
862 break; /* breakpoint */
865 break; /* breakpoint */
868 break; /* breakpoint */
871 break; /* breakpoint */
874 break; /* breakpoint */
877 break; /* breakpoint */
880 break; /* breakpoint */
883 break; /* breakpoint */
886 break; /* breakpoint */
889 break; /* breakpoint */
892 break; /* breakpoint */
895 break; /* breakpoint */
898 break; /* breakpoint */
901 break; /* breakpoint */
904 break; /* breakpoint */
907 break; /* BUS ERROR (alignment) */
910 break; /* INTerrupt */
913 break; /* "software generated" */
918 /**********************************************/
919 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
920 /* RETURN NUMBER OF CHARS PROCESSED */
921 /**********************************************/
923 hexToInt (unsigned char **ptr
, int *intValue
)
931 hexValue
= hex (**ptr
);
934 *intValue
= (*intValue
<< 4) | hexValue
;
945 Table of branch instructions:
947 10B6 RTE return from trap or exception
949 1ECr JL jump and link
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)
969 isShortBranch (unsigned char *instr
)
971 unsigned char instr0
= instr
[0] & 0x7F; /* mask off high bit */
973 if (instr0
== 0x10 && instr
[1] == 0xB6) /* RTE */
974 return 1; /* return from trap or exception */
976 if (instr0
== 0x1E || instr0
== 0x1F) /* JL or JMP */
977 if ((instr
[1] & 0xF0) == 0xC0)
978 return 2; /* jump thru a register */
980 if (instr0
== 0x7C || instr0
== 0x7D || /* BC, BNC, BL, BRA */
981 instr0
== 0x7E || instr0
== 0x7F)
982 return 3; /* eight bit PC offset */
988 isLongBranch (unsigned char *instr
)
990 if (instr
[0] == 0xFC || instr
[0] == 0xFD || /* BRA, BNC, BL, BC */
991 instr
[0] == 0xFE || instr
[0] == 0xFF) /* 24 bit relative */
993 if ((instr
[0] & 0xF0) == 0xB0) /* 16 bit relative */
995 if ((instr
[1] & 0xF0) == 0x00 || /* BNE, BEQ */
996 (instr
[1] & 0xF0) == 0x10)
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)
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. */
1010 #define INSTRUCTION_SIZE(addr) \
1011 ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
1014 isBranch (unsigned char *instr
)
1016 if (INSTRUCTION_SIZE (instr
) == 2)
1017 return isShortBranch (instr
);
1019 return isLongBranch (instr
);
1023 willBranch (unsigned char *instr
, int branchCode
)
1028 return 0; /* not a branch */
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)
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) */
1044 default: /* oops? */
1047 case 5: /* BNE, BEQ */
1048 switch (instr
[1] & 0xF0)
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? */
1057 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
1058 switch (instr
[1] & 0xF0)
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? */
1075 default: /* oops? */
1081 branchDestination (unsigned char *instr
, int branchCode
)
1086 case 0: /* not a branch */
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 offset) */
1093 return (((int) instr
) & ~3) + ((char) instr
[1] << 2);
1094 case 4: /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
1095 return ((int) instr
+
1096 ((((char) instr
[1] << 16) | (instr
[2] << 8) | (instr
[3])) <<
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));
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. */
1114 branchSideEffects (unsigned char *instr
, int branchCode
)
1119 return; /* I <THINK> this is already handled... */
1120 case 2: /* JL (or JMP) */
1121 case 3: /* BL (or BC, BNC, BRA) */
1123 if ((instr
[0] & 0x0F) == 0x0E) /* branch/jump and link */
1124 registers
[R14
] = (registers
[PC
] & ~3) + 4;
1126 default: /* any other branch has no side effects */
1131 static struct STEPPING_CONTEXT
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 */
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.
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. */
1156 #define TRAP1 0x10f1; /* trap #1 instruction */
1157 #define NOOP 0x7000; /* noop instruction */
1159 static unsigned short trap1
= TRAP1
;
1160 static unsigned short noop
= NOOP
;
1163 prepare_to_step (continue_p
)
1164 int continue_p
; /* if this isn't REALLY a single-step (see below) */
1166 unsigned long pc
= registers
[PC
];
1167 int branchCode
= isBranch ((unsigned char *) pc
);
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
++)
1176 if (branchCode
!= 0) /* next instruction is a branch */
1178 branchSideEffects ((unsigned char *) pc
, branchCode
);
1179 if (willBranch ((unsigned char *) pc
, branchCode
))
1180 registers
[PC
] = branchDestination ((unsigned char *) pc
, branchCode
);
1182 registers
[PC
] = pc
+ INSTRUCTION_SIZE (pc
);
1183 return 0; /* branch "executed" -- just notify GDB */
1185 else if (((int) pc
& 2) != 0) /* "second-slot" instruction */
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
;
1196 else /* "first-slot" instruction */
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
;
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 */
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,
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". */
1224 finish_from_step (void)
1226 if (stepping
.stepping
) /* anything to do? */
1228 int continue_p
= stepping
.continue_p
;
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
;
1238 for (p
= (unsigned char *) &stepping
; /* zero out the stepping context */
1239 p
< ((unsigned char *) &stepping
) + sizeof (stepping
); p
++)
1242 return !(continue_p
);
1244 else /* we didn't single-step, therefore this must be a legitimate stop */
1249 { /* separate out the bit flags in the PSW register */
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. */
1270 seth r1, #shigh(registers)\n\
1271 add3 r1, r1, #low(registers)\n\
1276 addi r1, #4 ; only add 4 as subsequent saves are `pre inc'\n\
1288 st r13, @+r1 ; fp\n\
1289 pop r0 ; lr (r14)\n\
1291 st sp, @+r1 ; sp contains right value at this point\n\
1293 st r0, @+r1 ; cr0 == PSW\n\
1295 st r0, @+r1 ; cr1 == CBR\n\
1297 st r0, @+r1 ; cr2 == SPI\n\
1299 st r0, @+r1 ; cr3 == SPU\n\
1301 st r0, @+r1 ; cr6 == BPC\n\
1302 st r0, @+r1 ; PC == BPC\n\
1304 st r0, @+r1 ; ACCL\n\
1306 st r0, @+r1 ; ACCH\n\
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. */
1315 cleanup_stash (void)
1317 psw
= (struct PSWreg
*) ®isters
[PSW
]; /* fields of PSW register */
1318 psw
->sm
= psw
->bsm
; /* fix up pre-trap values of psw fields */
1321 registers
[CBR
] = psw
->bc
; /* fix up pre-trap "C" register */
1323 #if 0 /* FIXME: Was in previous version. Necessary?
1324 (Remember that we use the "rte" insn to return 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 */
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 */
1333 /* FIXME: Copied from previous version. Necessary? */
1334 if (psw
->sm
) /* copy R15 into (psw->sm ? SPU : SPI) */
1335 registers
[SPU
] = registers
[R15
];
1337 registers
[SPI
] = registers
[R15
];
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\
1360 ld r1, @r0+ ; restore cr1 == CBR (no-op, because it's read only)\n\
1362 ld r1, @r0+ ; restore cr2 == SPI\n\
1364 ld r1, @r0+ ; restore cr3 == SPU\n\
1366 addi r0, #4 ; skip BPC\n\
1367 ld r1, @r0+ ; restore cr6 (BPC) == PC\n\
1369 ld r1, @r0+ ; restore ACCL\n\
1371 ld r1, @r0+ ; restore ACCH\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\
1379 /* General trap handler, called after the registers have been stashed.
1380 NUM is the trap/exception number. */
1383 process_exception (int num
)
1387 seth r1, #shigh(stackPtr)\n\
1388 add3 r1, r1, #low(stackPtr)\n\
1389 ld r15, @r1 ; setup local stack (protect user stack)\n\
1391 bl handle_exception\n\
1392 bl restore_and_return"::"r" (num
):"r0", "r1");
1395 void _catchException0 ();
1398 _catchException0:\n\
1400 bl stash_registers\n\
1401 ; Note that at this point the pushed value of `lr' has been popped\n\
1403 bl process_exception");
1405 void _catchException1 ();
1408 _catchException1:\n\
1410 bl stash_registers\n\
1411 ; Note that at this point the pushed value of `lr' has been popped\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\
1419 addi r0, #-4 ; back up PC for breakpoint trap.\n\
1420 st r0, @r1 ; FIXME: what about bp in right slot?\n\
1422 bl handle_exception\n\
1423 bl restore_and_return");
1425 void _catchException2 ();
1428 _catchException2:\n\
1430 bl stash_registers\n\
1431 ; Note that at this point the pushed value of `lr' has been popped\n\
1433 bl process_exception");
1435 void _catchException3 ();
1438 _catchException3:\n\
1440 bl stash_registers\n\
1441 ; Note that at this point the pushed value of `lr' has been popped\n\
1443 bl process_exception");
1445 void _catchException4 ();
1448 _catchException4:\n\
1450 bl stash_registers\n\
1451 ; Note that at this point the pushed value of `lr' has been popped\n\
1453 bl process_exception");
1455 void _catchException5 ();
1458 _catchException5:\n\
1460 bl stash_registers\n\
1461 ; Note that at this point the pushed value of `lr' has been popped\n\
1463 bl process_exception");
1465 void _catchException6 ();
1468 _catchException6:\n\
1470 bl stash_registers\n\
1471 ; Note that at this point the pushed value of `lr' has been popped\n\
1473 bl process_exception");
1475 void _catchException7 ();
1478 _catchException7:\n\
1480 bl stash_registers\n\
1481 ; Note that at this point the pushed value of `lr' has been popped\n\
1483 bl process_exception");
1485 void _catchException8 ();
1488 _catchException8:\n\
1490 bl stash_registers\n\
1491 ; Note that at this point the pushed value of `lr' has been popped\n\
1493 bl process_exception");
1495 void _catchException9 ();
1498 _catchException9:\n\
1500 bl stash_registers\n\
1501 ; Note that at this point the pushed value of `lr' has been popped\n\
1503 bl process_exception");
1505 void _catchException10 ();
1508 _catchException10:\n\
1510 bl stash_registers\n\
1511 ; Note that at this point the pushed value of `lr' has been popped\n\
1513 bl process_exception");
1515 void _catchException11 ();
1518 _catchException11:\n\
1520 bl stash_registers\n\
1521 ; Note that at this point the pushed value of `lr' has been popped\n\
1523 bl process_exception");
1525 void _catchException12 ();
1528 _catchException12:\n\
1530 bl stash_registers\n\
1531 ; Note that at this point the pushed value of `lr' has been popped\n\
1533 bl process_exception");
1535 void _catchException13 ();
1538 _catchException13:\n\
1540 bl stash_registers\n\
1541 ; Note that at this point the pushed value of `lr' has been popped\n\
1543 bl process_exception");
1545 void _catchException14 ();
1548 _catchException14:\n\
1550 bl stash_registers\n\
1551 ; Note that at this point the pushed value of `lr' has been popped\n\
1553 bl process_exception");
1555 void _catchException15 ();
1558 _catchException15:\n\
1560 bl stash_registers\n\
1561 ; Note that at this point the pushed value of `lr' has been popped\n\
1563 bl process_exception");
1565 void _catchException16 ();
1568 _catchException16:\n\
1570 bl stash_registers\n\
1571 ; Note that at this point the pushed value of `lr' has been popped\n\
1573 bl process_exception");
1575 void _catchException17 ();
1578 _catchException17:\n\
1580 bl stash_registers\n\
1581 ; Note that at this point the pushed value of `lr' has been popped\n\
1583 bl process_exception");
1586 /* this function is used to set up exception handlers for tracing and
1589 set_debug_traps (void)
1591 /* extern void remcomHandler(); */
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
);
1598 stackPtr
= &remcomStack
[STACKSIZE
/ sizeof (int) - 1];
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); */
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
1627 #define BREAKPOINT() asm volatile (" trap #2");
1637 Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
1638 Functions: gdb_putchar(char ch)
1640 gdb_write(char *str, int len)
1641 gdb_error(char *format, char *parm)
1644 /* Function: gdb_putchar(int)
1645 Make gdb write a char to stdout.
1646 Returns: the char */
1649 gdb_putchar (int ch
)
1654 buf
[1] = hexchars
[ch
>> 4];
1655 buf
[2] = hexchars
[ch
& 0x0F];
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 */
1666 gdb_write (char *data
, int len
)
1671 buf
= remcomOutBuffer
;
1677 i
< len
&& cpy
< buf
+ sizeof (remcomOutBuffer
) - 3; i
++)
1679 *cpy
++ = hexchars
[data
[i
] >> 4];
1680 *cpy
++ = hexchars
[data
[i
] & 0x0F];
1688 /* Function: gdb_puts(char *)
1689 Make gdb write a null-terminated string to stdout.
1690 Returns: the length of the string */
1693 gdb_puts (char *str
)
1695 return gdb_write (str
, strlen (str
));
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. */
1704 gdb_error (char *format
, char *parm
)
1706 char buf
[400], *cpy
;
1711 if (format
&& *format
)
1712 len
= strlen (format
);
1714 return; /* empty input */
1717 len
+= strlen (parm
);
1719 for (cpy
= buf
; *format
;)
1721 if (format
[0] == '%' && format
[1] == 's') /* include second string */
1723 format
+= 2; /* advance two chars instead of just one */
1724 while (parm
&& *parm
)
1735 static unsigned char *
1736 strcpy (unsigned char *dest
, const unsigned char *src
)
1738 unsigned char *ret
= dest
;
1750 strlen (const unsigned char *src
)
1754 for (ret
= 0; *src
; src
++)
This page took 0.067239 seconds and 4 git commands to generate.