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 /* Do not call finish_from_step() if this is not a trap #1
214 * (breakpoint trap). Without this check, the finish_from_step()
215 * might interpret a system call trap as a single step trap. This
216 * can happen if: the stub receives 's' and exits, but an interrupt
217 * was pending; the interrupt is now handled and causes the stub to
218 * be reentered because some function makes a system call.
220 if (exceptionVector
== 1) /* Trap exception? */
221 if (!finish_from_step()) /* Go see if stepping state needs update. */
222 return; /* "false step": let the target continue */
224 gdb_m32r_vector
= exceptionVector
;
228 mem2hex((unsigned char *) &exceptionVector
, buf
, 4, 0);
229 gdb_error("Handle exception %s, ", buf
);
230 mem2hex((unsigned char *) ®isters
[PC
], buf
, 4, 0);
231 gdb_error("PC == 0x%s\n", buf
);
234 /* reply to host that an exception has occurred */
235 sigval
= computeSignal( exceptionVector
);
237 ptr
= remcomOutBuffer
;
239 *ptr
++ = 'T'; /* notify gdb with signo, PC, FP and SP */
240 *ptr
++ = hexchars
[sigval
>> 4];
241 *ptr
++ = hexchars
[sigval
& 0xf];
243 *ptr
++ = hexchars
[PC
>> 4];
244 *ptr
++ = hexchars
[PC
& 0xf];
246 ptr
= mem2hex((unsigned char *)®isters
[PC
], ptr
, 4, 0); /* PC */
249 *ptr
++ = hexchars
[R13
>> 4];
250 *ptr
++ = hexchars
[R13
& 0xf];
252 ptr
= mem2hex((unsigned char *)®isters
[R13
], ptr
, 4, 0); /* FP */
255 *ptr
++ = hexchars
[R15
>> 4];
256 *ptr
++ = hexchars
[R15
& 0xf];
258 ptr
= mem2hex((unsigned char *)®isters
[R15
], ptr
, 4, 0); /* SP */
262 if (exceptionVector
== 0) /* simulated SYS call stuff */
264 mem2hex((unsigned char *) ®isters
[PC
], buf
, 4, 0);
265 switch (registers
[R0
]) {
267 gdb_error("Target program has exited at %s\n", buf
);
268 ptr
= remcomOutBuffer
;
270 sigval
= registers
[R1
] & 0xff;
271 *ptr
++ = hexchars
[sigval
>> 4];
272 *ptr
++ = hexchars
[sigval
& 0xf];
276 gdb_error("Target attempts SYS_open call at %s\n", buf
);
279 gdb_error("Target attempts SYS_close call at %s\n", buf
);
282 gdb_error("Target attempts SYS_read call at %s\n", buf
);
285 if (registers
[R1
] == 1 || /* write to stdout */
286 registers
[R1
] == 2) /* write to stderr */
287 { /* (we can do that) */
288 registers
[R0
] = gdb_write((void *) registers
[R2
], registers
[R3
]);
292 gdb_error("Target attempts SYS_write call at %s\n", buf
);
295 gdb_error("Target attempts SYS_lseek call at %s\n", buf
);
298 gdb_error("Target attempts SYS_unlink call at %s\n", buf
);
301 gdb_error("Target attempts SYS_getpid call at %s\n", buf
);
304 gdb_error("Target attempts SYS_kill call at %s\n", buf
);
307 gdb_error("Target attempts SYS_fstat call at %s\n", buf
);
310 gdb_error("Target attempts unknown SYS call at %s\n", buf
);
315 putpacket(remcomOutBuffer
);
320 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);
350 strcpy (remcomOutBuffer
, "E03");
351 gdb_error ("memory fault", "");
353 strcpy(remcomOutBuffer
,"OK");
359 strcpy(remcomOutBuffer
,"E02");
363 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
364 /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
365 if (hexToInt(&ptr
,&addr
))
367 if (hexToInt(&ptr
,&length
))
371 mem2hex((unsigned char*) addr
, remcomOutBuffer
, length
, 1);
373 strcpy (remcomOutBuffer
, "E03");
374 gdb_error ("memory fault", "");
379 strcpy(remcomOutBuffer
,"E01");
383 remcomOutBuffer
[0] = 'S';
384 remcomOutBuffer
[1] = hexchars
[sigval
>> 4];
385 remcomOutBuffer
[2] = hexchars
[sigval
% 16];
386 remcomOutBuffer
[3] = 0;
389 remote_debug
= !(remote_debug
); /* toggle debug flag */
391 case 'g': /* return the value of the CPU registers */
392 mem2hex((unsigned char*) registers
, remcomOutBuffer
, NUMREGBYTES
, 0);
394 case 'P': /* set the value of a single CPU register - return OK */
398 if (hexToInt (&ptr
, ®no
) && *ptr
++ == '=')
399 if (regno
>= 0 && regno
< NUMREGS
)
403 hex2mem (ptr
, (unsigned char *) ®isters
[regno
], 4, 0);
405 * Since we just changed a single CPU register, let's
406 * make sure to keep the several stack pointers consistant.
408 stackmode
= registers
[PSW
] & 0x80;
409 if (regno
== R15
) /* stack pointer changed */
410 { /* need to change SPI or SPU */
412 registers
[SPI
] = registers
[R15
];
414 registers
[SPU
] = registers
[R15
];
416 else if (regno
== SPU
) /* "user" stack pointer changed */
418 if (stackmode
!= 0) /* stack in user mode: copy SP */
419 registers
[R15
] = registers
[SPU
];
421 else if (regno
== SPI
) /* "interrupt" stack pointer changed */
423 if (stackmode
== 0) /* stack in interrupt mode: copy SP */
424 registers
[R15
] = registers
[SPI
];
426 else if (regno
== PSW
) /* stack mode may have changed! */
427 { /* force SP to either SPU or SPI */
428 if (stackmode
== 0) /* stack in user mode */
429 registers
[R15
] = registers
[SPI
];
430 else /* stack in interrupt mode */
431 registers
[R15
] = registers
[SPU
];
433 strcpy (remcomOutBuffer
, "OK");
436 strcpy (remcomOutBuffer
, "E01");
439 case 'G': /* set the value of the CPU registers - return OK */
440 hex2mem(ptr
, (unsigned char*) registers
, NUMREGBYTES
, 0);
441 strcpy(remcomOutBuffer
,"OK");
443 case 's': /* sAA..AA Step one instruction from AA..AA(optional) */
445 case 'c': /* cAA..AA Continue from address AA..AA(optional) */
446 /* try to read optional parameter, pc unchanged if no parm */
447 if (hexToInt(&ptr
,&addr
))
448 registers
[ PC
] = addr
;
450 if (stepping
) /* single-stepping */
452 if (!prepare_to_step(0)) /* set up for single-step */
454 /* prepare_to_step has already emulated the target insn:
455 Send SIGTRAP to gdb, don't resume the target at all. */
456 ptr
= remcomOutBuffer
;
457 *ptr
++ = 'T'; /* Simulate stopping with SIGTRAP */
461 *ptr
++ = hexchars
[PC
>> 4]; /* send PC */
462 *ptr
++ = hexchars
[PC
& 0xf];
464 ptr
= mem2hex((unsigned char *)®isters
[PC
], ptr
, 4, 0);
467 *ptr
++ = hexchars
[R13
>> 4]; /* send FP */
468 *ptr
++ = hexchars
[R13
& 0xf];
470 ptr
= mem2hex((unsigned char *)®isters
[R13
], ptr
, 4, 0);
473 *ptr
++ = hexchars
[R15
>> 4]; /* send SP */
474 *ptr
++ = hexchars
[R15
& 0xf];
476 ptr
= mem2hex((unsigned char *)®isters
[R15
], ptr
, 4, 0);
483 else /* continuing, not single-stepping */
485 /* OK, about to do a "continue". First check to see if the
486 target pc is on an odd boundary (second instruction in the
487 word). If so, we must do a single-step first, because
488 ya can't jump or return back to an odd boundary! */
489 if ((registers
[PC
] & 2) != 0)
495 case 'D': /* Detach */
497 /* I am interpreting this to mean, release the board from control
498 by the remote stub. To do this, I am restoring the original
499 (or at least previous) exception vectors.
501 for (i
= 0; i
< 18; i
++)
502 exceptionHandler (i
, save_vectors
[i
]);
504 return; /* continue the inferior */
506 strcpy(remcomOutBuffer
,"OK");
515 unsigned long start
, len
, our_crc
;
517 if (hexToInt (&ptr
, (int *) &start
) &&
519 hexToInt (&ptr
, (int *) &len
))
521 remcomOutBuffer
[0] = 'C';
522 our_crc
= crc32 ((unsigned char *) start
, len
, 0xffffffff);
523 mem2hex ((char *) &our_crc
,
527 } /* else do nothing */
528 } /* else do nothing */
531 case 'k': /* kill the program */
535 /* reply to the request */
536 putpacket(remcomOutBuffer
);
542 /* Table used by the crc32 function to calcuate the checksum. */
543 static unsigned long crc32_table
[256] = {0, 0};
546 crc32 (unsigned char *buf
, int len
, unsigned long crc
)
548 if (! crc32_table
[1])
550 /* Initialize the CRC table and the decoding table. */
554 for (i
= 0; i
< 256; i
++)
556 for (c
= i
<< 24, j
= 8; j
> 0; --j
)
557 c
= c
& 0x80000000 ? (c
<< 1) ^ 0x04c11db7 : (c
<< 1);
564 crc
= (crc
<< 8) ^ crc32_table
[((crc
>> 24) ^ *buf
) & 255];
571 hex (unsigned char ch
)
573 if ((ch
>= 'a') && (ch
<= 'f')) return (ch
-'a'+10);
574 if ((ch
>= '0') && (ch
<= '9')) return (ch
-'0');
575 if ((ch
>= 'A') && (ch
<= 'F')) return (ch
-'A'+10);
579 /* scan for the sequence $<data>#<checksum> */
584 unsigned char *buffer
= &remcomInBuffer
[0];
585 unsigned char checksum
;
586 unsigned char xmitcsum
;
592 /* wait around for the start character, ignore all other characters */
593 while ((ch
= getDebugChar ()) != '$')
601 /* now, read until a # or end of buffer is found */
602 while (count
< BUFMAX
)
604 ch
= getDebugChar ();
609 checksum
= checksum
+ ch
;
617 ch
= getDebugChar ();
618 xmitcsum
= hex (ch
) << 4;
619 ch
= getDebugChar ();
620 xmitcsum
+= hex (ch
);
622 if (checksum
!= xmitcsum
)
626 unsigned char buf
[16];
628 mem2hex((unsigned char *) &checksum
, buf
, 4, 0);
629 gdb_error("Bad checksum: my count = %s, ", buf
);
630 mem2hex((unsigned char *) &xmitcsum
, buf
, 4, 0);
631 gdb_error("sent count = %s\n", buf
);
632 gdb_error(" -- Bad buffer: \"%s\"\n", buffer
);
634 putDebugChar ('-'); /* failed checksum */
638 putDebugChar ('+'); /* successful transfer */
640 /* if a sequence char is present, reply the sequence ID */
641 if (buffer
[2] == ':')
643 putDebugChar (buffer
[0]);
644 putDebugChar (buffer
[1]);
655 /* send the packet in buffer. */
658 putpacket (unsigned char *buffer
)
660 unsigned char checksum
;
664 /* $<packet info>#<checksum>. */
670 while (ch
=buffer
[count
]) {
676 putDebugChar(hexchars
[checksum
>> 4]);
677 putDebugChar(hexchars
[checksum
% 16]);
678 } while (getDebugChar() != '+');
681 /* Address of a routine to RTE to if we get a memory fault. */
683 static void (*volatile mem_fault_routine
)() = 0;
691 /* Check the address for safe access ranges. As currently defined,
692 this routine will reject the "expansion bus" address range(s).
693 To make those ranges useable, someone must implement code to detect
694 whether there's anything connected to the expansion bus. */
697 mem_safe (unsigned char *addr
)
699 #define BAD_RANGE_ONE_START ((unsigned char *) 0x600000)
700 #define BAD_RANGE_ONE_END ((unsigned char *) 0xa00000)
701 #define BAD_RANGE_TWO_START ((unsigned char *) 0xff680000)
702 #define BAD_RANGE_TWO_END ((unsigned char *) 0xff800000)
704 if (addr
< BAD_RANGE_ONE_START
) return 1; /* safe */
705 if (addr
< BAD_RANGE_ONE_END
) return 0; /* unsafe */
706 if (addr
< BAD_RANGE_TWO_START
) return 1; /* safe */
707 if (addr
< BAD_RANGE_TWO_END
) return 0; /* unsafe */
710 /* These are separate functions so that they are so short and sweet
711 that the compiler won't save any registers (if there is a fault
712 to mem_fault, they won't get restored, so there better not be any
715 get_char (unsigned char *addr
)
718 if (mem_fault_routine
&& !mem_safe(addr
))
720 mem_fault_routine ();
728 set_char (unsigned char *addr
, unsigned char val
)
731 if (mem_fault_routine
&& !mem_safe (addr
))
733 mem_fault_routine ();
740 /* Convert the memory pointed to by mem into hex, placing result in buf.
741 Return a pointer to the last char put in buf (null).
742 If MAY_FAULT is non-zero, then we should set mem_err in response to
743 a fault; if zero treat a fault like any other fault in the stub. */
745 static unsigned char *
746 mem2hex (unsigned char *mem
, unsigned char *buf
, int count
, int may_fault
)
752 mem_fault_routine
= set_mem_err
;
753 for (i
=0;i
<count
;i
++) {
754 ch
= get_char (mem
++);
755 if (may_fault
&& mem_err
)
757 *buf
++ = hexchars
[ch
>> 4];
758 *buf
++ = hexchars
[ch
% 16];
762 mem_fault_routine
= 0;
766 /* Convert the hex array pointed to by buf into binary to be placed in mem.
767 Return a pointer to the character AFTER the last byte written. */
769 static unsigned char*
770 hex2mem (unsigned char *buf
, unsigned char *mem
, int count
, int may_fault
)
776 mem_fault_routine
= set_mem_err
;
777 for (i
=0;i
<count
;i
++) {
778 ch
= hex(*buf
++) << 4;
779 ch
= ch
+ hex(*buf
++);
780 set_char (mem
++, ch
);
781 if (may_fault
&& mem_err
)
785 mem_fault_routine
= 0;
789 /* Convert the binary stream in BUF to memory.
791 Gdb will escape $, #, and the escape char (0x7d).
792 COUNT is the total number of bytes to write into
794 static unsigned char *
795 bin2mem (unsigned char *buf
, unsigned char *mem
, int count
, int may_fault
)
801 mem_fault_routine
= set_mem_err
;
802 for (i
= 0; i
< count
; i
++)
804 /* Check for any escaped characters. Be paranoid and
805 only unescape chars that should be escaped. */
812 case 0x5d: /* escape char */
822 set_char (mem
++, *buf
++);
824 if (may_fault
&& mem_err
)
829 mem_fault_routine
= 0;
833 /* this function takes the m32r exception vector and attempts to
834 translate this number into a unix compatible signal value */
837 computeSignal (int exceptionVector
)
840 switch (exceptionVector
) {
841 case 0 : sigval
= 23; break; /* I/O trap */
842 case 1 : sigval
= 5; break; /* breakpoint */
843 case 2 : sigval
= 5; break; /* breakpoint */
844 case 3 : sigval
= 5; break; /* breakpoint */
845 case 4 : sigval
= 5; break; /* breakpoint */
846 case 5 : sigval
= 5; break; /* breakpoint */
847 case 6 : sigval
= 5; break; /* breakpoint */
848 case 7 : sigval
= 5; break; /* breakpoint */
849 case 8 : sigval
= 5; break; /* breakpoint */
850 case 9 : sigval
= 5; break; /* breakpoint */
851 case 10 : sigval
= 5; break; /* breakpoint */
852 case 11 : sigval
= 5; break; /* breakpoint */
853 case 12 : sigval
= 5; break; /* breakpoint */
854 case 13 : sigval
= 5; break; /* breakpoint */
855 case 14 : sigval
= 5; break; /* breakpoint */
856 case 15 : sigval
= 5; break; /* breakpoint */
857 case 16 : sigval
= 10; break; /* BUS ERROR (alignment) */
858 case 17 : sigval
= 2; break; /* INTerrupt */
859 default : sigval
= 7; break; /* "software generated" */
864 /**********************************************/
865 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
866 /* RETURN NUMBER OF CHARS PROCESSED */
867 /**********************************************/
869 hexToInt (unsigned char **ptr
, int *intValue
)
877 hexValue
= hex(**ptr
);
880 *intValue
= (*intValue
<<4) | hexValue
;
891 Table of branch instructions:
893 10B6 RTE return from trap or exception
895 1ECr JL jump and link
897 FFxxxxxx BRA branch (long)
898 B09rxxxx BNEZ branch not-equal-zero
899 Br1rxxxx BNE branch not-equal
900 7Dxx BNC branch not-condition
901 FDxxxxxx BNC branch not-condition (long)
902 B0Arxxxx BLTZ branch less-than-zero
903 B0Crxxxx BLEZ branch less-equal-zero
904 7Exx BL branch and link
905 FExxxxxx BL branch and link (long)
906 B0Drxxxx BGTZ branch greater-than-zero
907 B0Brxxxx BGEZ branch greater-equal-zero
908 B08rxxxx BEQZ branch equal-zero
909 Br0rxxxx BEQ branch equal
910 7Cxx BC branch condition
911 FCxxxxxx BC branch condition (long)
915 isShortBranch (unsigned char *instr
)
917 unsigned char instr0
= instr
[0] & 0x7F; /* mask off high bit */
919 if (instr0
== 0x10 && instr
[1] == 0xB6) /* RTE */
920 return 1; /* return from trap or exception */
922 if (instr0
== 0x1E || instr0
== 0x1F) /* JL or JMP */
923 if ((instr
[1] & 0xF0) == 0xC0)
924 return 2; /* jump thru a register */
926 if (instr0
== 0x7C || instr0
== 0x7D || /* BC, BNC, BL, BRA */
927 instr0
== 0x7E || instr0
== 0x7F)
928 return 3; /* eight bit PC offset */
934 isLongBranch (unsigned char *instr
)
936 if (instr
[0] == 0xFC || instr
[0] == 0xFD || /* BRA, BNC, BL, BC */
937 instr
[0] == 0xFE || instr
[0] == 0xFF) /* 24 bit relative */
939 if ((instr
[0] & 0xF0) == 0xB0) /* 16 bit relative */
941 if ((instr
[1] & 0xF0) == 0x00 || /* BNE, BEQ */
942 (instr
[1] & 0xF0) == 0x10)
944 if (instr
[0] == 0xB0) /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
945 if ((instr
[1] & 0xF0) == 0x80 || (instr
[1] & 0xF0) == 0x90 ||
946 (instr
[1] & 0xF0) == 0xA0 || (instr
[1] & 0xF0) == 0xB0 ||
947 (instr
[1] & 0xF0) == 0xC0 || (instr
[1] & 0xF0) == 0xD0)
953 /* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
954 then it's a 2-byte instruction, else it's a 4-byte instruction. */
956 #define INSTRUCTION_SIZE(addr) \
957 ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
960 isBranch (unsigned char *instr
)
962 if (INSTRUCTION_SIZE(instr
) == 2)
963 return isShortBranch(instr
);
965 return isLongBranch(instr
);
969 willBranch (unsigned char *instr
, int branchCode
)
973 case 0: return 0; /* not a branch */
974 case 1: return 1; /* RTE */
975 case 2: return 1; /* JL or JMP */
976 case 3: /* BC, BNC, BL, BRA (short) */
977 case 4: /* BC, BNC, BL, BRA (long) */
978 switch (instr
[0] & 0x0F)
980 case 0xC: /* Branch if Condition Register */
981 return (registers
[CBR
] != 0);
982 case 0xD: /* Branch if NOT Condition Register */
983 return (registers
[CBR
] == 0);
984 case 0xE: /* Branch and Link */
985 case 0xF: /* Branch (unconditional) */
990 case 5: /* BNE, BEQ */
991 switch (instr
[1] & 0xF0)
993 case 0x00: /* Branch if r1 equal to r2 */
994 return (registers
[instr
[0] & 0x0F] == registers
[instr
[1] & 0x0F]);
995 case 0x10: /* Branch if r1 NOT equal to r2 */
996 return (registers
[instr
[0] & 0x0F] != registers
[instr
[1] & 0x0F]);
1000 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
1001 switch (instr
[1] & 0xF0)
1003 case 0x80: /* Branch if reg equal to zero */
1004 return (registers
[instr
[1] & 0x0F] == 0);
1005 case 0x90: /* Branch if reg NOT equal to zero */
1006 return (registers
[instr
[1] & 0x0F] != 0);
1007 case 0xA0: /* Branch if reg less than zero */
1008 return (registers
[instr
[1] & 0x0F] < 0);
1009 case 0xB0: /* Branch if reg greater or equal to zero */
1010 return (registers
[instr
[1] & 0x0F] >= 0);
1011 case 0xC0: /* Branch if reg less than or equal to zero */
1012 return (registers
[instr
[1] & 0x0F] <= 0);
1013 case 0xD0: /* Branch if reg greater than zero */
1014 return (registers
[instr
[1] & 0x0F] > 0);
1015 default: /* oops? */
1018 default: /* oops? */
1024 branchDestination (unsigned char *instr
, int branchCode
)
1026 switch (branchCode
) {
1028 case 0: /* not a branch */
1031 return registers
[BPC
] & ~3; /* pop BPC into PC */
1032 case 2: /* JL or JMP */
1033 return registers
[instr
[1] & 0x0F] & ~3; /* jump thru a register */
1034 case 3: /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
1035 return (((int) instr
) & ~3) + ((char) instr
[1] << 2);
1036 case 4: /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
1037 return ((int) instr
+
1038 ((((char) instr
[1] << 16) | (instr
[2] << 8) | (instr
[3])) << 2));
1039 case 5: /* BNE, BEQ (16-bit relative offset) */
1040 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
1041 return ((int) instr
+ ((((char) instr
[2] << 8) | (instr
[3])) << 2));
1044 /* An explanatory note: in the last three return expressions, I have
1045 cast the most-significant byte of the return offset to char.
1046 What this accomplishes is sign extension. If the other
1047 less-significant bytes were signed as well, they would get sign
1048 extended too and, if negative, their leading bits would clobber
1049 the bits of the more-significant bytes ahead of them. There are
1050 other ways I could have done this, but sign extension from
1051 odd-sized integers is always a pain. */
1055 branchSideEffects (unsigned char *instr
, int branchCode
)
1060 return; /* I <THINK> this is already handled... */
1061 case 2: /* JL (or JMP) */
1062 case 3: /* BL (or BC, BNC, BRA) */
1064 if ((instr
[0] & 0x0F) == 0x0E) /* branch/jump and link */
1065 registers
[R14
] = (registers
[PC
] & ~3) + 4;
1067 default: /* any other branch has no side effects */
1072 static struct STEPPING_CONTEXT
{
1073 int stepping
; /* true when we've started a single-step */
1074 unsigned long target_addr
; /* the instr we're trying to execute */
1075 unsigned long target_size
; /* the size of the target instr */
1076 unsigned long noop_addr
; /* where we've inserted a no-op, if any */
1077 unsigned long trap1_addr
; /* the trap following the target instr */
1078 unsigned long trap2_addr
; /* the trap at a branch destination, if any */
1079 unsigned short noop_save
; /* instruction overwritten by our no-op */
1080 unsigned short trap1_save
; /* instruction overwritten by trap1 */
1081 unsigned short trap2_save
; /* instruction overwritten by trap2 */
1082 unsigned short continue_p
; /* true if NOT returning to gdb after step */
1085 /* Function: prepare_to_step
1086 Called from handle_exception to prepare the user program to single-step.
1087 Places a trap instruction after the target instruction, with special
1088 extra handling for branch instructions and for instructions in the
1089 second half-word of a word.
1091 Returns: True if we should actually execute the instruction;
1092 False if we are going to emulate executing the instruction,
1093 in which case we simply report to GDB that the instruction
1094 has already been executed. */
1096 #define TRAP1 0x10f1; /* trap #1 instruction */
1097 #define NOOP 0x7000; /* noop instruction */
1099 static unsigned short trap1
= TRAP1
;
1100 static unsigned short noop
= NOOP
;
1103 prepare_to_step(continue_p
)
1104 int continue_p
; /* if this isn't REALLY a single-step (see below) */
1106 unsigned long pc
= registers
[PC
];
1107 int branchCode
= isBranch((unsigned char *) pc
);
1110 /* zero out the stepping context
1111 (paranoia -- it should already be zeroed) */
1112 for (p
= (unsigned char *) &stepping
;
1113 p
< ((unsigned char *) &stepping
) + sizeof(stepping
);
1117 if (branchCode
!= 0) /* next instruction is a branch */
1119 branchSideEffects((unsigned char *) pc
, branchCode
);
1120 if (willBranch((unsigned char *)pc
, branchCode
))
1121 registers
[PC
] = branchDestination((unsigned char *) pc
, branchCode
);
1123 registers
[PC
] = pc
+ INSTRUCTION_SIZE(pc
);
1124 return 0; /* branch "executed" -- just notify GDB */
1126 else if (((int) pc
& 2) != 0) /* "second-slot" instruction */
1128 /* insert no-op before pc */
1129 stepping
.noop_addr
= pc
- 2;
1130 stepping
.noop_save
= *(unsigned short *) stepping
.noop_addr
;
1131 *(unsigned short *) stepping
.noop_addr
= noop
;
1132 /* insert trap after pc */
1133 stepping
.trap1_addr
= pc
+ 2;
1134 stepping
.trap1_save
= *(unsigned short *) stepping
.trap1_addr
;
1135 *(unsigned short *) stepping
.trap1_addr
= trap1
;
1137 else /* "first-slot" instruction */
1139 /* insert trap after pc */
1140 stepping
.trap1_addr
= pc
+ INSTRUCTION_SIZE(pc
);
1141 stepping
.trap1_save
= *(unsigned short *) stepping
.trap1_addr
;
1142 *(unsigned short *) stepping
.trap1_addr
= trap1
;
1144 /* "continue_p" means that we are actually doing a continue, and not
1145 being requested to single-step by GDB. Sometimes we have to do
1146 one single-step before continuing, because the PC is on a half-word
1147 boundary. There's no way to simply resume at such an address. */
1148 stepping
.continue_p
= continue_p
;
1149 stepping
.stepping
= 1; /* starting a single-step */
1153 /* Function: finish_from_step
1154 Called from handle_exception to finish up when the user program
1155 returns from a single-step. Replaces the instructions that had
1156 been overwritten by traps or no-ops,
1158 Returns: True if we should notify GDB that the target stopped.
1159 False if we only single-stepped because we had to before we
1160 could continue (ie. we were trying to continue at a
1161 half-word boundary). In that case don't notify GDB:
1162 just "continue continuing". */
1165 finish_from_step (void)
1167 if (stepping
.stepping
) /* anything to do? */
1169 int continue_p
= stepping
.continue_p
;
1172 if (stepping
.noop_addr
) /* replace instr "under" our no-op */
1173 *(unsigned short *) stepping
.noop_addr
= stepping
.noop_save
;
1174 if (stepping
.trap1_addr
) /* replace instr "under" our trap */
1175 *(unsigned short *) stepping
.trap1_addr
= stepping
.trap1_save
;
1176 if (stepping
.trap2_addr
) /* ditto our other trap, if any */
1177 *(unsigned short *) stepping
.trap2_addr
= stepping
.trap2_save
;
1179 for (p
= (unsigned char *) &stepping
; /* zero out the stepping context */
1180 p
< ((unsigned char *) &stepping
) + sizeof(stepping
);
1184 return !(continue_p
);
1186 else /* we didn't single-step, therefore this must be a legitimate stop */
1190 struct PSWreg
{ /* separate out the bit flags in the PSW register */
1202 /* Upon entry the value for LR to save has been pushed.
1203 We unpush that so that the value for the stack pointer saved is correct.
1204 Upon entry, all other registers are assumed to have not been modified
1205 since the interrupt/trap occured. */
1211 seth r1, #shigh(registers)
1212 add3 r1, r1, #low(registers)
1217 addi r1, #4 ; only add 4 as subsequent saves are `pre inc'
1232 st sp, @+r1 ; sp contains right value at this point
1234 st r0, @+r1 ; cr0 == PSW
1236 st r0, @+r1 ; cr1 == CBR
1238 st r0, @+r1 ; cr2 == SPI
1240 st r0, @+r1 ; cr3 == SPU
1242 st r0, @+r1 ; cr6 == BPC
1243 st r0, @+r1 ; PC == BPC
1250 /* C routine to clean up what stash_registers did.
1251 It is called after calling stash_registers.
1252 This is separate from stash_registers as we want to do this in C
1253 but doing stash_registers in C isn't straightforward. */
1256 cleanup_stash (void)
1258 psw
= (struct PSWreg
*) ®isters
[PSW
]; /* fields of PSW register */
1259 psw
->sm
= psw
->bsm
; /* fix up pre-trap values of psw fields */
1262 registers
[CBR
] = psw
->bc
; /* fix up pre-trap "C" register */
1264 #if 0 /* FIXME: Was in previous version. Necessary?
1265 (Remember that we use the "rte" insn to return from the
1266 trap/interrupt so the values of bsm, bie, bc are important. */
1267 psw
->bsm
= psw
->bie
= psw
->bc
= 0; /* zero post-trap values */
1270 /* FIXME: Copied from previous version. This can probably be deleted
1271 since methinks stash_registers has already done this. */
1272 registers
[PC
] = registers
[BPC
]; /* pre-trap PC */
1274 /* FIXME: Copied from previous version. Necessary? */
1275 if (psw
->sm
) /* copy R15 into (psw->sm ? SPU : SPI) */
1276 registers
[SPU
] = registers
[R15
];
1278 registers
[SPI
] = registers
[R15
];
1283 seth r0, #shigh(registers+8)
1284 add3 r0, r0, #low(registers+8)
1285 ld r2, @r0+ ; restore r2
1286 ld r3, @r0+ ; restore r3
1287 ld r4, @r0+ ; restore r4
1288 ld r5, @r0+ ; restore r5
1289 ld r6, @r0+ ; restore r6
1290 ld r7, @r0+ ; restore r7
1291 ld r8, @r0+ ; restore r8
1292 ld r9, @r0+ ; restore r9
1293 ld r10, @r0+ ; restore r10
1294 ld r11, @r0+ ; restore r11
1295 ld r12, @r0+ ; restore r12
1296 ld r13, @r0+ ; restore r13
1297 ld r14, @r0+ ; restore r14
1298 ld r15, @r0+ ; restore r15
1299 addi r0, #4 ; don't restore PSW (rte will do it)
1300 ld r1, @r0+ ; restore cr1 == CBR (no-op, because it's read only)
1302 ld r1, @r0+ ; restore cr2 == SPI
1304 ld r1, @r0+ ; restore cr3 == SPU
1306 addi r0, #4 ; skip BPC
1307 ld r1, @r0+ ; restore cr6 (BPC) == PC
1309 ld r1, @r0+ ; restore ACCL
1311 ld r1, @r0+ ; restore ACCH
1313 seth r0, #shigh(registers)
1314 add3 r0, r0, #low(registers)
1315 ld r1, @(4,r0) ; restore r1
1316 ld r0, @r0 ; restore r0
1319 /* General trap handler, called after the registers have been stashed.
1320 NUM is the trap/exception number. */
1323 process_exception (int num
)
1327 seth r1, #shigh(stackPtr)
1328 add3 r1, r1, #low(stackPtr)
1329 ld r15, @r1 ; setup local stack (protect user stack)
1332 bl restore_and_return"
1333 : : "r" (num
) : "r0", "r1");
1336 void _catchException0 ();
1342 ; Note that at this point the pushed value of `lr' has been popped
1344 bl process_exception");
1346 void _catchException1 ();
1352 ; Note that at this point the pushed value of `lr' has been popped
1354 seth r1, #shigh(stackPtr)
1355 add3 r1, r1, #low(stackPtr)
1356 ld r15, @r1 ; setup local stack (protect user stack)
1357 seth r1, #shigh(registers + 21*4) ; PC
1358 add3 r1, r1, #low(registers + 21*4)
1360 addi r0, #-4 ; back up PC for breakpoint trap.
1361 st r0, @r1 ; FIXME: what about bp in right slot?
1364 bl restore_and_return");
1366 void _catchException2 ();
1372 ; Note that at this point the pushed value of `lr' has been popped
1374 bl process_exception");
1376 void _catchException3 ();
1382 ; Note that at this point the pushed value of `lr' has been popped
1384 bl process_exception");
1386 void _catchException4 ();
1392 ; Note that at this point the pushed value of `lr' has been popped
1394 bl process_exception");
1396 void _catchException5 ();
1402 ; Note that at this point the pushed value of `lr' has been popped
1404 bl process_exception");
1406 void _catchException6 ();
1412 ; Note that at this point the pushed value of `lr' has been popped
1414 bl process_exception");
1416 void _catchException7 ();
1422 ; Note that at this point the pushed value of `lr' has been popped
1424 bl process_exception");
1426 void _catchException8 ();
1432 ; Note that at this point the pushed value of `lr' has been popped
1434 bl process_exception");
1436 void _catchException9 ();
1442 ; Note that at this point the pushed value of `lr' has been popped
1444 bl process_exception");
1446 void _catchException10 ();
1452 ; Note that at this point the pushed value of `lr' has been popped
1454 bl process_exception");
1456 void _catchException11 ();
1462 ; Note that at this point the pushed value of `lr' has been popped
1464 bl process_exception");
1466 void _catchException12 ();
1472 ; Note that at this point the pushed value of `lr' has been popped
1474 bl process_exception");
1476 void _catchException13 ();
1482 ; Note that at this point the pushed value of `lr' has been popped
1484 bl process_exception");
1486 void _catchException14 ();
1492 ; Note that at this point the pushed value of `lr' has been popped
1494 bl process_exception");
1496 void _catchException15 ();
1502 ; Note that at this point the pushed value of `lr' has been popped
1504 bl process_exception");
1506 void _catchException16 ();
1512 ; Note that at this point the pushed value of `lr' has been popped
1514 bl process_exception");
1516 void _catchException17 ();
1522 ; Note that at this point the pushed value of `lr' has been popped
1524 bl process_exception");
1527 /* this function is used to set up exception handlers for tracing and
1530 set_debug_traps (void)
1532 /* extern void remcomHandler(); */
1535 for (i
= 0; i
< 18; i
++) /* keep a copy of old vectors */
1536 if (save_vectors
[i
] == 0) /* only copy them the first time */
1537 save_vectors
[i
] = getExceptionHandler (i
);
1539 stackPtr
= &remcomStack
[STACKSIZE
/sizeof(int) - 1];
1541 exceptionHandler (0, _catchException0
);
1542 exceptionHandler (1, _catchException1
);
1543 exceptionHandler (2, _catchException2
);
1544 exceptionHandler (3, _catchException3
);
1545 exceptionHandler (4, _catchException4
);
1546 exceptionHandler (5, _catchException5
);
1547 exceptionHandler (6, _catchException6
);
1548 exceptionHandler (7, _catchException7
);
1549 exceptionHandler (8, _catchException8
);
1550 exceptionHandler (9, _catchException9
);
1551 exceptionHandler (10, _catchException10
);
1552 exceptionHandler (11, _catchException11
);
1553 exceptionHandler (12, _catchException12
);
1554 exceptionHandler (13, _catchException13
);
1555 exceptionHandler (14, _catchException14
);
1556 exceptionHandler (15, _catchException15
);
1557 exceptionHandler (16, _catchException16
);
1558 /* exceptionHandler (17, _catchException17); */
1563 /* This function will generate a breakpoint exception. It is used at the
1564 beginning of a program to sync up with a debugger and can be used
1565 otherwise as a quick means to stop program execution and "break" into
1568 #define BREAKPOINT() asm volatile (" trap #2");
1578 Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
1579 Functions: gdb_putchar(char ch)
1581 gdb_write(char *str, int len)
1582 gdb_error(char *format, char *parm)
1585 /* Function: gdb_putchar(int)
1586 Make gdb write a char to stdout.
1587 Returns: the char */
1590 gdb_putchar (int ch
)
1595 buf
[1] = hexchars
[ch
>> 4];
1596 buf
[2] = hexchars
[ch
& 0x0F];
1602 /* Function: gdb_write(char *, int)
1603 Make gdb write n bytes to stdout (not assumed to be null-terminated).
1604 Returns: number of bytes written */
1607 gdb_write (char *data
, int len
)
1612 buf
= remcomOutBuffer
;
1618 i
< len
&& cpy
< buf
+ sizeof(remcomOutBuffer
) - 3;
1621 *cpy
++ = hexchars
[data
[i
] >> 4];
1622 *cpy
++ = hexchars
[data
[i
] & 0x0F];
1630 /* Function: gdb_puts(char *)
1631 Make gdb write a null-terminated string to stdout.
1632 Returns: the length of the string */
1635 gdb_puts (char *str
)
1637 return gdb_write(str
, strlen(str
));
1640 /* Function: gdb_error(char *, char *)
1641 Send an error message to gdb's stdout.
1642 First string may have 1 (one) optional "%s" in it, which
1643 will cause the optional second string to be inserted. */
1646 gdb_error (char *format
, char *parm
)
1648 char buf
[400], *cpy
;
1653 if (format
&& *format
)
1654 len
= strlen(format
);
1656 return; /* empty input */
1659 len
+= strlen(parm
);
1661 for (cpy
= buf
; *format
; )
1663 if (format
[0] == '%' && format
[1] == 's') /* include second string */
1665 format
+= 2; /* advance two chars instead of just one */
1666 while (parm
&& *parm
)
1677 static unsigned char *
1678 strcpy (unsigned char *dest
, const unsigned char *src
)
1680 unsigned char *ret
= dest
;
1692 strlen (const unsigned char *src
)
1696 for (ret
= 0; *src
; src
++)
1709 int atexit (void *p
)
This page took 0.067373 seconds and 4 git commands to generate.