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 (buf
, len
, crc
)
543 if (! crc32_table
[1])
545 /* Initialize the CRC table and the decoding table. */
549 for (i
= 0; i
< 256; i
++)
551 for (c
= i
<< 24, j
= 8; j
> 0; --j
)
552 c
= c
& 0x80000000 ? (c
<< 1) ^ 0x04c11db7 : (c
<< 1);
559 crc
= (crc
<< 8) ^ crc32_table
[((crc
>> 24) ^ *buf
) & 255];
569 if ((ch
>= 'a') && (ch
<= 'f')) return (ch
-'a'+10);
570 if ((ch
>= '0') && (ch
<= '9')) return (ch
-'0');
571 if ((ch
>= 'A') && (ch
<= 'F')) return (ch
-'A'+10);
575 /* scan for the sequence $<data>#<checksum> */
580 unsigned char *buffer
= &remcomInBuffer
[0];
581 unsigned char checksum
;
582 unsigned char xmitcsum
;
588 /* wait around for the start character, ignore all other characters */
589 while ((ch
= getDebugChar ()) != '$')
597 /* now, read until a # or end of buffer is found */
598 while (count
< BUFMAX
)
600 ch
= getDebugChar ();
605 checksum
= checksum
+ ch
;
613 ch
= getDebugChar ();
614 xmitcsum
= hex (ch
) << 4;
615 ch
= getDebugChar ();
616 xmitcsum
+= hex (ch
);
618 if (checksum
!= xmitcsum
)
622 unsigned char buf
[16];
624 mem2hex((unsigned char *) &checksum
, buf
, 4, 0);
625 gdb_error("Bad checksum: my count = %s, ", buf
);
626 mem2hex((unsigned char *) &xmitcsum
, buf
, 4, 0);
627 gdb_error("sent count = %s\n", buf
);
628 gdb_error(" -- Bad buffer: \"%s\"\n", buffer
);
630 putDebugChar ('-'); /* failed checksum */
634 putDebugChar ('+'); /* successful transfer */
636 /* if a sequence char is present, reply the sequence ID */
637 if (buffer
[2] == ':')
639 putDebugChar (buffer
[0]);
640 putDebugChar (buffer
[1]);
651 /* send the packet in buffer. */
655 unsigned char *buffer
;
657 unsigned char checksum
;
661 /* $<packet info>#<checksum>. */
667 while (ch
=buffer
[count
]) {
673 putDebugChar(hexchars
[checksum
>> 4]);
674 putDebugChar(hexchars
[checksum
% 16]);
675 } while (getDebugChar() != '+');
678 /* Address of a routine to RTE to if we get a memory fault. */
680 static void (*volatile mem_fault_routine
)() = 0;
688 /* Check the address for safe access ranges. As currently defined,
689 this routine will reject the "expansion bus" address range(s).
690 To make those ranges useable, someone must implement code to detect
691 whether there's anything connected to the expansion bus. */
697 #define BAD_RANGE_ONE_START ((unsigned char *) 0x600000)
698 #define BAD_RANGE_ONE_END ((unsigned char *) 0xa00000)
699 #define BAD_RANGE_TWO_START ((unsigned char *) 0xff680000)
700 #define BAD_RANGE_TWO_END ((unsigned char *) 0xff800000)
702 if (addr
< BAD_RANGE_ONE_START
) return 1; /* safe */
703 if (addr
< BAD_RANGE_ONE_END
) return 0; /* unsafe */
704 if (addr
< BAD_RANGE_TWO_START
) return 1; /* safe */
705 if (addr
< BAD_RANGE_TWO_END
) return 0; /* unsafe */
708 /* These are separate functions so that they are so short and sweet
709 that the compiler won't save any registers (if there is a fault
710 to mem_fault, they won't get restored, so there better not be any
717 if (mem_fault_routine
&& !mem_safe(addr
))
719 mem_fault_routine ();
732 if (mem_fault_routine
&& !mem_safe (addr
))
734 mem_fault_routine ();
741 /* Convert the memory pointed to by mem into hex, placing result in buf.
742 Return a pointer to the last char put in buf (null).
743 If MAY_FAULT is non-zero, then we should set mem_err in response to
744 a fault; if zero treat a fault like any other fault in the stub. */
746 static unsigned char *
747 mem2hex(mem
, buf
, count
, may_fault
)
757 mem_fault_routine
= set_mem_err
;
758 for (i
=0;i
<count
;i
++) {
759 ch
= get_char (mem
++);
760 if (may_fault
&& mem_err
)
762 *buf
++ = hexchars
[ch
>> 4];
763 *buf
++ = hexchars
[ch
% 16];
767 mem_fault_routine
= 0;
771 /* Convert the hex array pointed to by buf into binary to be placed in mem.
772 Return a pointer to the character AFTER the last byte written. */
774 static unsigned char*
775 hex2mem(buf
, mem
, count
, may_fault
)
785 mem_fault_routine
= set_mem_err
;
786 for (i
=0;i
<count
;i
++) {
787 ch
= hex(*buf
++) << 4;
788 ch
= ch
+ hex(*buf
++);
789 set_char (mem
++, ch
);
790 if (may_fault
&& mem_err
)
794 mem_fault_routine
= 0;
798 /* Convert the binary stream in BUF to memory.
800 Gdb will escape $, #, and the escape char (0x7d).
801 COUNT is the total number of bytes to write into
803 static unsigned char *
804 bin2mem (buf
, mem
, count
, may_fault
)
814 mem_fault_routine
= set_mem_err
;
815 for (i
= 0; i
< count
; i
++)
817 /* Check for any escaped characters. Be paranoid and
818 only unescape chars that should be escaped. */
825 case 0x5d: /* escape char */
835 set_char (mem
++, *buf
++);
837 if (may_fault
&& mem_err
)
842 mem_fault_routine
= 0;
846 /* this function takes the m32r exception vector and attempts to
847 translate this number into a unix compatible signal value */
850 computeSignal(exceptionVector
)
854 switch (exceptionVector
) {
855 case 0 : sigval
= 23; break; /* I/O trap */
856 case 1 : sigval
= 5; break; /* breakpoint */
857 case 2 : sigval
= 5; break; /* breakpoint */
858 case 3 : sigval
= 5; break; /* breakpoint */
859 case 4 : sigval
= 5; break; /* breakpoint */
860 case 5 : sigval
= 5; break; /* breakpoint */
861 case 6 : sigval
= 5; break; /* breakpoint */
862 case 7 : sigval
= 5; break; /* breakpoint */
863 case 8 : sigval
= 5; break; /* breakpoint */
864 case 9 : sigval
= 5; break; /* breakpoint */
865 case 10 : sigval
= 5; break; /* breakpoint */
866 case 11 : sigval
= 5; break; /* breakpoint */
867 case 12 : sigval
= 5; break; /* breakpoint */
868 case 13 : sigval
= 5; break; /* breakpoint */
869 case 14 : sigval
= 5; break; /* breakpoint */
870 case 15 : sigval
= 5; break; /* breakpoint */
871 case 16 : sigval
= 10; break; /* BUS ERROR (alignment) */
872 case 17 : sigval
= 2; break; /* INTerrupt */
873 default : sigval
= 7; break; /* "software generated" */
878 /**********************************************/
879 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
880 /* RETURN NUMBER OF CHARS PROCESSED */
881 /**********************************************/
883 hexToInt(ptr
, intValue
)
893 hexValue
= hex(**ptr
);
896 *intValue
= (*intValue
<<4) | hexValue
;
907 Table of branch instructions:
909 10B6 RTE return from trap or exception
911 1ECr JL jump and link
913 FFxxxxxx BRA branch (long)
914 B09rxxxx BNEZ branch not-equal-zero
915 Br1rxxxx BNE branch not-equal
916 7Dxx BNC branch not-condition
917 FDxxxxxx BNC branch not-condition (long)
918 B0Arxxxx BLTZ branch less-than-zero
919 B0Crxxxx BLEZ branch less-equal-zero
920 7Exx BL branch and link
921 FExxxxxx BL branch and link (long)
922 B0Drxxxx BGTZ branch greater-than-zero
923 B0Brxxxx BGEZ branch greater-equal-zero
924 B08rxxxx BEQZ branch equal-zero
925 Br0rxxxx BEQ branch equal
926 7Cxx BC branch condition
927 FCxxxxxx BC branch condition (long)
932 unsigned char *instr
;
934 unsigned char instr0
= instr
[0] & 0x7F; /* mask off high bit */
936 if (instr0
== 0x10 && instr
[1] == 0xB6) /* RTE */
937 return 1; /* return from trap or exception */
939 if (instr0
== 0x1E || instr0
== 0x1F) /* JL or JMP */
940 if ((instr
[1] & 0xF0) == 0xC0)
941 return 2; /* jump thru a register */
943 if (instr0
== 0x7C || instr0
== 0x7D || /* BC, BNC, BL, BRA */
944 instr0
== 0x7E || instr0
== 0x7F)
945 return 3; /* eight bit PC offset */
952 unsigned char *instr
;
954 if (instr
[0] == 0xFC || instr
[0] == 0xFD || /* BRA, BNC, BL, BC */
955 instr
[0] == 0xFE || instr
[0] == 0xFF) /* 24 bit relative */
957 if ((instr
[0] & 0xF0) == 0xB0) /* 16 bit relative */
959 if ((instr
[1] & 0xF0) == 0x00 || /* BNE, BEQ */
960 (instr
[1] & 0xF0) == 0x10)
962 if (instr
[0] == 0xB0) /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
963 if ((instr
[1] & 0xF0) == 0x80 || (instr
[1] & 0xF0) == 0x90 ||
964 (instr
[1] & 0xF0) == 0xA0 || (instr
[1] & 0xF0) == 0xB0 ||
965 (instr
[1] & 0xF0) == 0xC0 || (instr
[1] & 0xF0) == 0xD0)
971 /* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
972 then it's a 2-byte instruction, else it's a 4-byte instruction. */
974 #define INSTRUCTION_SIZE(addr) \
975 ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
979 unsigned char *instr
;
981 if (INSTRUCTION_SIZE(instr
) == 2)
982 return isShortBranch(instr
);
984 return isLongBranch(instr
);
988 willBranch(instr
, branchCode
)
989 unsigned char *instr
;
993 case 0: return 0; /* not a branch */
994 case 1: return 1; /* RTE */
995 case 2: return 1; /* JL or JMP */
996 case 3: /* BC, BNC, BL, BRA (short) */
997 case 4: /* BC, BNC, BL, BRA (long) */
998 switch (instr
[0] & 0x0F)
1000 case 0xC: /* Branch if Condition Register */
1001 return (registers
[CBR
] != 0);
1002 case 0xD: /* Branch if NOT Condition Register */
1003 return (registers
[CBR
] == 0);
1004 case 0xE: /* Branch and Link */
1005 case 0xF: /* Branch (unconditional) */
1007 default: /* oops? */
1010 case 5: /* BNE, BEQ */
1011 switch (instr
[1] & 0xF0)
1013 case 0x00: /* Branch if r1 equal to r2 */
1014 return (registers
[instr
[0] & 0x0F] == registers
[instr
[1] & 0x0F]);
1015 case 0x10: /* Branch if r1 NOT equal to r2 */
1016 return (registers
[instr
[0] & 0x0F] != registers
[instr
[1] & 0x0F]);
1017 default: /* oops? */
1020 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
1021 switch (instr
[1] & 0xF0)
1023 case 0x80: /* Branch if reg equal to zero */
1024 return (registers
[instr
[1] & 0x0F] == 0);
1025 case 0x90: /* Branch if reg NOT equal to zero */
1026 return (registers
[instr
[1] & 0x0F] != 0);
1027 case 0xA0: /* Branch if reg less than zero */
1028 return (registers
[instr
[1] & 0x0F] < 0);
1029 case 0xB0: /* Branch if reg greater or equal to zero */
1030 return (registers
[instr
[1] & 0x0F] >= 0);
1031 case 0xC0: /* Branch if reg less than or equal to zero */
1032 return (registers
[instr
[1] & 0x0F] <= 0);
1033 case 0xD0: /* Branch if reg greater than zero */
1034 return (registers
[instr
[1] & 0x0F] > 0);
1035 default: /* oops? */
1038 default: /* oops? */
1044 branchDestination(instr
, branchCode
)
1045 unsigned char *instr
;
1047 switch (branchCode
) {
1049 case 0: /* not a branch */
1052 return registers
[BPC
] & ~3; /* pop BPC into PC */
1053 case 2: /* JL or JMP */
1054 return registers
[instr
[1] & 0x0F] & ~3; /* jump thru a register */
1055 case 3: /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
1056 return (((int) instr
) & ~3) + ((char) instr
[1] << 2);
1057 case 4: /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
1058 return ((int) instr
+
1059 ((((char) instr
[1] << 16) | (instr
[2] << 8) | (instr
[3])) << 2));
1060 case 5: /* BNE, BEQ (16-bit relative offset) */
1061 case 6: /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
1062 return ((int) instr
+ ((((char) instr
[2] << 8) | (instr
[3])) << 2));
1065 /* An explanatory note: in the last three return expressions, I have
1066 cast the most-significant byte of the return offset to char.
1067 What this accomplishes is sign extension. If the other
1068 less-significant bytes were signed as well, they would get sign
1069 extended too and, if negative, their leading bits would clobber
1070 the bits of the more-significant bytes ahead of them. There are
1071 other ways I could have done this, but sign extension from
1072 odd-sized integers is always a pain. */
1076 branchSideEffects(instr
, branchCode
)
1077 unsigned char *instr
;
1083 return; /* I <THINK> this is already handled... */
1084 case 2: /* JL (or JMP) */
1085 case 3: /* BL (or BC, BNC, BRA) */
1087 if ((instr
[0] & 0x0F) == 0x0E) /* branch/jump and link */
1088 registers
[R14
] = (registers
[PC
] & ~3) + 4;
1090 default: /* any other branch has no side effects */
1095 static struct STEPPING_CONTEXT
{
1096 int stepping
; /* true when we've started a single-step */
1097 unsigned long target_addr
; /* the instr we're trying to execute */
1098 unsigned long target_size
; /* the size of the target instr */
1099 unsigned long noop_addr
; /* where we've inserted a no-op, if any */
1100 unsigned long trap1_addr
; /* the trap following the target instr */
1101 unsigned long trap2_addr
; /* the trap at a branch destination, if any */
1102 unsigned short noop_save
; /* instruction overwritten by our no-op */
1103 unsigned short trap1_save
; /* instruction overwritten by trap1 */
1104 unsigned short trap2_save
; /* instruction overwritten by trap2 */
1105 unsigned short continue_p
; /* true if NOT returning to gdb after step */
1108 /* Function: prepare_to_step
1109 Called from handle_exception to prepare the user program to single-step.
1110 Places a trap instruction after the target instruction, with special
1111 extra handling for branch instructions and for instructions in the
1112 second half-word of a word.
1114 Returns: True if we should actually execute the instruction;
1115 False if we are going to emulate executing the instruction,
1116 in which case we simply report to GDB that the instruction
1117 has already been executed. */
1119 #define TRAP1 0x10f1; /* trap #1 instruction */
1120 #define NOOP 0x7000; /* noop instruction */
1122 static unsigned short trap1
= TRAP1
;
1123 static unsigned short noop
= NOOP
;
1126 prepare_to_step(continue_p
)
1127 int continue_p
; /* if this isn't REALLY a single-step (see below) */
1129 unsigned long pc
= registers
[PC
];
1130 int branchCode
= isBranch((unsigned char *) pc
);
1133 /* zero out the stepping context
1134 (paranoia -- it should already be zeroed) */
1135 for (p
= (unsigned char *) &stepping
;
1136 p
< ((unsigned char *) &stepping
) + sizeof(stepping
);
1140 if (branchCode
!= 0) /* next instruction is a branch */
1142 branchSideEffects((unsigned char *) pc
, branchCode
);
1143 if (willBranch((unsigned char *)pc
, branchCode
))
1144 registers
[PC
] = branchDestination((unsigned char *) pc
, branchCode
);
1146 registers
[PC
] = pc
+ INSTRUCTION_SIZE(pc
);
1147 return 0; /* branch "executed" -- just notify GDB */
1149 else if (((int) pc
& 2) != 0) /* "second-slot" instruction */
1151 /* insert no-op before pc */
1152 stepping
.noop_addr
= pc
- 2;
1153 stepping
.noop_save
= *(unsigned short *) stepping
.noop_addr
;
1154 *(unsigned short *) stepping
.noop_addr
= noop
;
1155 /* insert trap after pc */
1156 stepping
.trap1_addr
= pc
+ 2;
1157 stepping
.trap1_save
= *(unsigned short *) stepping
.trap1_addr
;
1158 *(unsigned short *) stepping
.trap1_addr
= trap1
;
1160 else /* "first-slot" instruction */
1162 /* insert trap after pc */
1163 stepping
.trap1_addr
= pc
+ INSTRUCTION_SIZE(pc
);
1164 stepping
.trap1_save
= *(unsigned short *) stepping
.trap1_addr
;
1165 *(unsigned short *) stepping
.trap1_addr
= trap1
;
1167 /* "continue_p" means that we are actually doing a continue, and not
1168 being requested to single-step by GDB. Sometimes we have to do
1169 one single-step before continuing, because the PC is on a half-word
1170 boundary. There's no way to simply resume at such an address. */
1171 stepping
.continue_p
= continue_p
;
1172 stepping
.stepping
= 1; /* starting a single-step */
1176 /* Function: finish_from_step
1177 Called from handle_exception to finish up when the user program
1178 returns from a single-step. Replaces the instructions that had
1179 been overwritten by traps or no-ops,
1181 Returns: True if we should notify GDB that the target stopped.
1182 False if we only single-stepped because we had to before we
1183 could continue (ie. we were trying to continue at a
1184 half-word boundary). In that case don't notify GDB:
1185 just "continue continuing". */
1190 if (stepping
.stepping
) /* anything to do? */
1192 int continue_p
= stepping
.continue_p
;
1195 if (stepping
.noop_addr
) /* replace instr "under" our no-op */
1196 *(unsigned short *) stepping
.noop_addr
= stepping
.noop_save
;
1197 if (stepping
.trap1_addr
) /* replace instr "under" our trap */
1198 *(unsigned short *) stepping
.trap1_addr
= stepping
.trap1_save
;
1199 if (stepping
.trap2_addr
) /* ditto our other trap, if any */
1200 *(unsigned short *) stepping
.trap2_addr
= stepping
.trap2_save
;
1202 for (p
= (unsigned char *) &stepping
; /* zero out the stepping context */
1203 p
< ((unsigned char *) &stepping
) + sizeof(stepping
);
1207 return !(continue_p
);
1209 else /* we didn't single-step, therefore this must be a legitimate stop */
1213 struct PSWreg
{ /* separate out the bit flags in the PSW register */
1225 /* Upon entry the value for LR to save has been pushed.
1226 We unpush that so that the value for the stack pointer saved is correct.
1227 Upon entry, all other registers are assumed to have not been modified
1228 since the interrupt/trap occured. */
1234 seth r1, #shigh(registers)
1235 add3 r1, r1, #low(registers)
1240 addi r1, #4 ; only add 4 as subsequent saves are `pre inc'
1255 st sp, @+r1 ; sp contains right value at this point
1257 st r0, @+r1 ; cr0 == PSW
1259 st r0, @+r1 ; cr1 == CBR
1261 st r0, @+r1 ; cr2 == SPI
1263 st r0, @+r1 ; cr3 == SPU
1265 st r0, @+r1 ; cr6 == BPC
1266 st r0, @+r1 ; PC == BPC
1273 /* C routine to clean up what stash_registers did.
1274 It is called after calling stash_registers.
1275 This is separate from stash_registers as we want to do this in C
1276 but doing stash_registers in C isn't straightforward. */
1281 psw
= (struct PSWreg
*) ®isters
[PSW
]; /* fields of PSW register */
1282 psw
->sm
= psw
->bsm
; /* fix up pre-trap values of psw fields */
1285 registers
[CBR
] = psw
->bc
; /* fix up pre-trap "C" register */
1287 #if 0 /* FIXME: Was in previous version. Necessary?
1288 (Remember that we use the "rte" insn to return from the
1289 trap/interrupt so the values of bsm, bie, bc are important. */
1290 psw
->bsm
= psw
->bie
= psw
->bc
= 0; /* zero post-trap values */
1293 /* FIXME: Copied from previous version. This can probably be deleted
1294 since methinks stash_registers has already done this. */
1295 registers
[PC
] = registers
[BPC
]; /* pre-trap PC */
1297 /* FIXME: Copied from previous version. Necessary? */
1298 if (psw
->sm
) /* copy R15 into (psw->sm ? SPU : SPI) */
1299 registers
[SPU
] = registers
[R15
];
1301 registers
[SPI
] = registers
[R15
];
1306 seth r0, #shigh(registers+8)
1307 add3 r0, r0, #low(registers+8)
1308 ld r2, @r0+ ; restore r2
1309 ld r3, @r0+ ; restore r3
1310 ld r4, @r0+ ; restore r4
1311 ld r5, @r0+ ; restore r5
1312 ld r6, @r0+ ; restore r6
1313 ld r7, @r0+ ; restore r7
1314 ld r8, @r0+ ; restore r8
1315 ld r9, @r0+ ; restore r9
1316 ld r10, @r0+ ; restore r10
1317 ld r11, @r0+ ; restore r11
1318 ld r12, @r0+ ; restore r12
1319 ld r13, @r0+ ; restore r13
1320 ld r14, @r0+ ; restore r14
1321 ld r15, @r0+ ; restore r15
1322 ld r1, @r0+ ; restore cr0 == PSW
1324 ld r1, @r0+ ; restore cr1 == CBR (no-op, because it's read only)
1326 ld r1, @r0+ ; restore cr2 == SPI
1328 ld r1, @r0+ ; restore cr3 == SPU
1330 addi r0, #4 ; skip BPC
1331 ld r1, @r0+ ; restore cr6 (BPC) == PC
1333 ld r1, @r0+ ; restore ACCL
1335 ld r1, @r0+ ; restore ACCH
1337 seth r0, #shigh(registers)
1338 add3 r0, r0, #low(registers)
1339 ld r1, @(4,r0) ; restore r1
1340 ld r0, @r0 ; restore r0
1343 /* General trap handler, called after the registers have been stashed.
1344 NUM is the trap/exception number. */
1347 process_exception (num
)
1352 seth r1, #shigh(stackPtr)
1353 add3 r1, r1, #low(stackPtr)
1354 ld r15, @r1 ; setup local stack (protect user stack)
1357 bl restore_and_return"
1358 : : "r" (num
) : "r0", "r1");
1361 void _catchException0 ();
1367 ; Note that at this point the pushed value of `lr' has been popped
1369 bl process_exception");
1371 void _catchException1 ();
1377 ; Note that at this point the pushed value of `lr' has been popped
1379 seth r1, #shigh(stackPtr)
1380 add3 r1, r1, #low(stackPtr)
1381 ld r15, @r1 ; setup local stack (protect user stack)
1382 seth r1, #shigh(registers + 21*4) ; PC
1383 add3 r1, r1, #low(registers + 21*4)
1385 addi r0, #-4 ; back up PC for breakpoint trap.
1386 st r0, @r1 ; FIXME: what about bp in right slot?
1389 bl restore_and_return");
1391 void _catchException2 ();
1397 ; Note that at this point the pushed value of `lr' has been popped
1399 bl process_exception");
1401 void _catchException3 ();
1407 ; Note that at this point the pushed value of `lr' has been popped
1409 bl process_exception");
1411 void _catchException4 ();
1417 ; Note that at this point the pushed value of `lr' has been popped
1419 bl process_exception");
1421 void _catchException5 ();
1427 ; Note that at this point the pushed value of `lr' has been popped
1429 bl process_exception");
1431 void _catchException6 ();
1437 ; Note that at this point the pushed value of `lr' has been popped
1439 bl process_exception");
1441 void _catchException7 ();
1447 ; Note that at this point the pushed value of `lr' has been popped
1449 bl process_exception");
1451 void _catchException8 ();
1457 ; Note that at this point the pushed value of `lr' has been popped
1459 bl process_exception");
1461 void _catchException9 ();
1467 ; Note that at this point the pushed value of `lr' has been popped
1469 bl process_exception");
1471 void _catchException10 ();
1477 ; Note that at this point the pushed value of `lr' has been popped
1479 bl process_exception");
1481 void _catchException11 ();
1487 ; Note that at this point the pushed value of `lr' has been popped
1489 bl process_exception");
1491 void _catchException12 ();
1497 ; Note that at this point the pushed value of `lr' has been popped
1499 bl process_exception");
1501 void _catchException13 ();
1507 ; Note that at this point the pushed value of `lr' has been popped
1509 bl process_exception");
1511 void _catchException14 ();
1517 ; Note that at this point the pushed value of `lr' has been popped
1519 bl process_exception");
1521 void _catchException15 ();
1527 ; Note that at this point the pushed value of `lr' has been popped
1529 bl process_exception");
1531 void _catchException16 ();
1537 ; Note that at this point the pushed value of `lr' has been popped
1539 bl process_exception");
1541 void _catchException17 ();
1547 ; Note that at this point the pushed value of `lr' has been popped
1549 bl process_exception");
1552 /* this function is used to set up exception handlers for tracing and
1557 /* extern void remcomHandler(); */
1560 for (i
= 0; i
< 18; i
++) /* keep a copy of old vectors */
1561 if (save_vectors
[i
] == 0) /* only copy them the first time */
1562 save_vectors
[i
] = getExceptionHandler (i
);
1564 stackPtr
= &remcomStack
[STACKSIZE
/sizeof(int) - 1];
1566 exceptionHandler (0, _catchException0
);
1567 exceptionHandler (1, _catchException1
);
1568 exceptionHandler (2, _catchException2
);
1569 exceptionHandler (3, _catchException3
);
1570 exceptionHandler (4, _catchException4
);
1571 exceptionHandler (5, _catchException5
);
1572 exceptionHandler (6, _catchException6
);
1573 exceptionHandler (7, _catchException7
);
1574 exceptionHandler (8, _catchException8
);
1575 exceptionHandler (9, _catchException9
);
1576 exceptionHandler (10, _catchException10
);
1577 exceptionHandler (11, _catchException11
);
1578 exceptionHandler (12, _catchException12
);
1579 exceptionHandler (13, _catchException13
);
1580 exceptionHandler (14, _catchException14
);
1581 exceptionHandler (15, _catchException15
);
1582 exceptionHandler (16, _catchException16
);
1583 /* exceptionHandler (17, _catchException17); */
1588 /* This function will generate a breakpoint exception. It is used at the
1589 beginning of a program to sync up with a debugger and can be used
1590 otherwise as a quick means to stop program execution and "break" into
1593 #define BREAKPOINT() asm volatile (" trap #2");
1603 Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
1604 Functions: gdb_putchar(char ch)
1606 gdb_write(char *str, int len)
1607 gdb_error(char *format, char *parm)
1610 /* Function: gdb_putchar(int)
1611 Make gdb write a char to stdout.
1612 Returns: the char */
1621 buf
[1] = hexchars
[ch
>> 4];
1622 buf
[2] = hexchars
[ch
& 0x0F];
1628 /* Function: gdb_write(char *, int)
1629 Make gdb write n bytes to stdout (not assumed to be null-terminated).
1630 Returns: number of bytes written */
1633 gdb_write(data
, len
)
1640 buf
= remcomOutBuffer
;
1646 i
< len
&& cpy
< buf
+ sizeof(remcomOutBuffer
) - 3;
1649 *cpy
++ = hexchars
[data
[i
] >> 4];
1650 *cpy
++ = hexchars
[data
[i
] & 0x0F];
1658 /* Function: gdb_puts(char *)
1659 Make gdb write a null-terminated string to stdout.
1660 Returns: the length of the string */
1666 return gdb_write(str
, strlen(str
));
1669 /* Function: gdb_error(char *, char *)
1670 Send an error message to gdb's stdout.
1671 First string may have 1 (one) optional "%s" in it, which
1672 will cause the optional second string to be inserted. */
1675 gdb_error(format
, parm
)
1679 char buf
[400], *cpy
;
1684 if (format
&& *format
)
1685 len
= strlen(format
);
1687 return; /* empty input */
1690 len
+= strlen(parm
);
1692 for (cpy
= buf
; *format
; )
1694 if (format
[0] == '%' && format
[1] == 's') /* include second string */
1696 format
+= 2; /* advance two chars instead of just one */
1697 while (parm
&& *parm
)
1708 static unsigned char *
1709 strcpy (unsigned char *dest
, const unsigned char *src
)
1711 unsigned char *ret
= dest
;
1723 strlen (const unsigned char *src
)
1727 for (ret
= 0; *src
; src
++)
1740 int atexit (void *p
)
This page took 0.064855 seconds and 4 git commands to generate.