* bfd.c (union tdata): Add nlm_obj_data;
[deliverable/binutils-gdb.git] / gdb / m68k-stub.c
1 /****************************************************************************
2
3 THIS SOFTWARE IS NOT COPYRIGHTED
4
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.
8
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.
12
13 ****************************************************************************/
14
15 /****************************************************************************
16 * $Header$
17 *
18 * $Module name: remcom.c $
19 * $Revision$
20 * $Date$
21 * $Contributor: Lake Stevens Instrument Division$
22 *
23 * $Description: low level support for gdb debugger. $
24 *
25 * $Considerations: only works on target hardware $
26 *
27 * $Written by: Glenn Engel $
28 * $ModuleState: Experimental $
29 *
30 * $NOTES: See Below $
31 *
32 * To enable debugger support, two things need to happen. One, a
33 * call to set_debug_traps() is necessary in order to allow any breakpoints
34 * or error conditions to be properly intercepted and reported to gdb.
35 * Two, a breakpoint needs to be generated to begin communication. This
36 * is most easily accomplished by a call to breakpoint(). Breakpoint()
37 * simulates a breakpoint by executing a trap #1.
38 *
39 * Some explanation is probably necessary to explain how exceptions are
40 * handled. When an exception is encountered the 68000 pushes the current
41 * program counter and status register onto the supervisor stack and then
42 * transfers execution to a location specified in it's vector table.
43 * The handlers for the exception vectors are hardwired to jmp to an address
44 * given by the relation: (exception - 256) * 6. These are decending
45 * addresses starting from -6, -12, -18, ... By allowing 6 bytes for
46 * each entry, a jsr, jmp, bsr, ... can be used to enter the exception
47 * handler. Using a jsr to handle an exception has an added benefit of
48 * allowing a single handler to service several exceptions and use the
49 * return address as the key differentiation. The vector number can be
50 * computed from the return address by [ exception = (addr + 1530) / 6 ].
51 * The sole purpose of the routine _catchException is to compute the
52 * exception number and push it on the stack in place of the return address.
53 * The external function exceptionHandler() is
54 * used to attach a specific handler to a specific 68k exception.
55 * For 68020 machines, the ability to have a return address around just
56 * so the vector can be determined is not necessary because the '020 pushes an
57 * extra word onto the stack containing the vector offset
58 *
59 * Because gdb will sometimes write to the stack area to execute function
60 * calls, this program cannot rely on using the supervisor stack so it
61 * uses it's own stack area reserved in the int array remcomStack.
62 *
63 *************
64 *
65 * The following gdb commands are supported:
66 *
67 * command function Return value
68 *
69 * g return the value of the CPU registers hex data or ENN
70 * G set the value of the CPU registers OK or ENN
71 *
72 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
73 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
74 *
75 * c Resume at current address SNN ( signal NN)
76 * cAA..AA Continue at address AA..AA SNN
77 *
78 * s Step one instruction SNN
79 * sAA..AA Step one instruction from AA..AA SNN
80 *
81 * k kill
82 *
83 * ? What was the last sigval ? SNN (signal NN)
84 *
85 * All commands and responses are sent with a packet which includes a
86 * checksum. A packet consists of
87 *
88 * $<packet info>#<checksum>.
89 *
90 * where
91 * <packet info> :: <characters representing the command or response>
92 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
93 *
94 * When a packet is received, it is first acknowledged with either '+' or '-'.
95 * '+' indicates a successful transfer. '-' indicates a failed transfer.
96 *
97 * Example:
98 *
99 * Host: Reply:
100 * $m0,10#2a +$00010203040506070809101112131415#42
101 *
102 ****************************************************************************/
103
104 #include <stdio.h>
105 #include <string.h>
106 #include <setjmp.h>
107
108 /************************************************************************
109 *
110 * external low-level support routines
111 */
112 typedef void (*ExceptionHook)(int); /* pointer to function with int parm */
113 typedef void (*Function)(); /* pointer to a function */
114
115 extern putDebugChar(); /* write a single character */
116 extern getDebugChar(); /* read and return a single char */
117
118 extern Function exceptionHandler(); /* assign an exception handler */
119 extern ExceptionHook exceptionHook; /* hook variable for errors/exceptions */
120
121 /************************/
122 /* FORWARD DECLARATIONS */
123 /************************/
124 void initializeRemcomErrorFrame(void);
125
126 /************************************************************************/
127 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
128 /* at least NUMREGBYTES*2 are needed for register packets */
129 #define BUFMAX 400
130
131 static char initialized; /* boolean flag. != 0 means we've been initialized */
132
133 int remote_debug;
134 /* debug > 0 prints ill-formed commands in valid packets & checksum errors */
135
136 static const char hexchars[]="0123456789abcdef";
137
138 /* there are 180 bytes of registers on a 68020 w/68881 */
139 /* many of the fpa registers are 12 byte (96 bit) registers */
140 #define NUMREGBYTES 180
141 enum regnames {D0,D1,D2,D3,D4,D5,D6,D7,
142 A0,A1,A2,A3,A4,A5,A6,A7,
143 PS,PC,
144 FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7,
145 FPCONTROL,FPSTATUS,FPIADDR
146 };
147
148 typedef struct FrameStruct
149 {
150 struct FrameStruct *previous;
151 int exceptionPC; /* pc value when this frame created */
152 int exceptionVector; /* cpu vector causing exception */
153 short frameSize; /* size of cpu frame in words */
154 short sr; /* for 68000, this not always sr */
155 int pc;
156 short format;
157 int fsaveHeader;
158 int morejunk[0]; /* exception frame, fp save... */
159 } Frame;
160
161 #define FRAMESIZE 500
162 int gdbFrameStack[FRAMESIZE];
163 static Frame *lastFrame;
164
165 /*
166 * these should not be static cuz they can be used outside this module
167 */
168 int registers[NUMREGBYTES/4];
169 int superStack;
170
171 #define STACKSIZE 10000
172 int remcomStack[STACKSIZE/sizeof(int)];
173 static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
174
175 /*
176 * In many cases, the system will want to continue exception processing
177 * when a continue command is given.
178 * oldExceptionHook is a function to invoke in this case.
179 */
180
181 static ExceptionHook oldExceptionHook;
182
183 /* the size of the exception stack on the 68020 varies with the type of
184 * exception. The following table is the number of WORDS used
185 * for each exception format.
186 */
187 const short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,12,4,4,4 };
188
189 /************* jump buffer used for setjmp/longjmp **************************/
190 jmp_buf remcomEnv;
191
192 /*************************** ASSEMBLY CODE MACROS *************************/
193 /* */
194
195 #ifdef __HAVE_68881__
196 /* do an fsave, then remember the address to begin a restore from */
197 #define SAVE_FP_REGS() asm(" fsave a0@-"); \
198 asm(" fmovemx fp0-fp7,_registers+72"); \
199 asm(" fmoveml fpcr/fpsr/fpi,_registers+168");
200 #define RESTORE_FP_REGS() \
201 asm(" \n\
202 fmoveml _registers+168,fpcr/fpsr/fpi \n\
203 fmovemx _registers+72,fp0-fp7 \n\
204 cmpl #-1,a0@ | skip frestore flag set ? \n\
205 beq skip_frestore \n\
206 frestore a0@+ \n\
207 skip_frestore: \n\
208 ");
209
210 #else
211 #define SAVE_FP_REGS()
212 #define RESTORE_FP_REGS()
213 #endif /* __HAVE_68881__ */
214
215 void return_to_super(void);
216 void return_to_user(void);
217
218 asm("
219 .text
220 .globl _return_to_super
221 _return_to_super:
222 movel _registers+60,sp /* get new stack pointer */
223 movel _lastFrame,a0 /* get last frame info */
224 bra return_to_any
225
226 .globl _return_to_user
227 _return_to_user:
228 movel _registers+60,a0 /* get usp */
229 movel a0,usp /* set usp */
230 movel _superStack,sp /* get original stack pointer */
231
232 return_to_any:
233 movel _lastFrame,a0 /* get last frame info */
234 movel a0@+,_lastFrame /* link in previous frame */
235 addql #8,a0 /* skip over pc, vector#*/
236 movew a0@+,d0 /* get # of words in cpu frame */
237 addw d0,a0 /* point to end of data */
238 addw d0,a0 /* point to end of data */
239 movel a0,a1
240 #
241 # copy the stack frame
242 subql #1,d0
243 copyUserLoop:
244 movew a1@-,sp@-
245 dbf d0,copyUserLoop
246 ");
247 RESTORE_FP_REGS()
248 asm(" moveml _registers,d0-d7/a0-a6");
249 asm(" rte"); /* pop and go! */
250
251 #define DISABLE_INTERRUPTS() asm(" oriw #0x0700,sr");
252 #define BREAKPOINT() asm(" trap #1");
253
254 /* this function is called immediately when a level 7 interrupt occurs */
255 /* if the previous interrupt level was 7 then we're already servicing */
256 /* this interrupt and an rte is in order to return to the debugger. */
257 /* For the 68000, the offset for sr is 6 due to the jsr return address */
258 asm("
259 .text
260 .globl __debug_level7
261 __debug_level7:
262 movew d0,sp@-");
263 #ifdef mc68020
264 asm(" movew sp@(2),d0");
265 #else
266 asm(" movew sp@(6),d0");
267 #endif
268 asm(" andiw #0x700,d0
269 cmpiw #0x700,d0
270 beq _already7
271 movew sp@+,d0
272 bra __catchException
273 _already7:
274 movew sp@+,d0");
275 #ifndef mc68020
276 asm(" lea sp@(4),sp"); /* pull off 68000 return address */
277 #endif
278 asm(" rte");
279
280 extern void _catchException();
281
282 #ifdef mc68020
283 /* This function is called when a 68020 exception occurs. It saves
284 * all the cpu and fpcp regs in the _registers array, creates a frame on a
285 * linked list of frames which has the cpu and fpcp stack frames needed
286 * to properly restore the context of these processors, and invokes
287 * an exception handler (remcom_handler).
288 *
289 * stack on entry: stack on exit:
290 * N bytes of junk exception # MSWord
291 * Exception Format Word exception # MSWord
292 * Program counter LSWord
293 * Program counter MSWord
294 * Status Register
295 *
296 *
297 */
298 asm("
299 .text
300 .globl __catchException
301 __catchException:");
302 DISABLE_INTERRUPTS();
303 asm("
304 moveml d0-d7/a0-a6,_registers /* save registers */
305 movel _lastFrame,a0 /* last frame pointer */
306 ");
307 SAVE_FP_REGS();
308 asm("
309 lea _registers,a5 /* get address of registers */
310 movew sp@,d1 /* get status register */
311 movew d1,a5@(66) /* save sr */
312 movel sp@(2),a4 /* save pc in a4 for later use */
313 movel a4,a5@(68) /* save pc in _regisers[] */
314
315 #
316 # figure out how many bytes in the stack frame
317 movew sp@(6),d0 /* get '020 exception format */
318 movew d0,d2 /* make a copy of format word */
319 andiw #0xf000,d0 /* mask off format type */
320 rolw #5,d0 /* rotate into the low byte *2 */
321 lea _exceptionSize,a1
322 addw d0,a1 /* index into the table */
323 movew a1@,d0 /* get number of words in frame */
324 movew d0,d3 /* save it */
325 subw d0,a0 /* adjust save pointer */
326 subw d0,a0 /* adjust save pointer(bytes) */
327 movel a0,a1 /* copy save pointer */
328 subql #1,d0 /* predecrement loop counter */
329 #
330 # copy the frame
331 saveFrameLoop:
332 movew sp@+,a1@+
333 dbf d0,saveFrameLoop
334 #
335 # now that the stack has been clenaed,
336 # save the a7 in use at time of exception
337 movel sp,_superStack /* save supervisor sp */
338 andiw #0x2000,d1 /* were we in supervisor mode ? */
339 beq userMode
340 movel a7,a5@(60) /* save a7 */
341 bra a7saveDone
342 userMode:
343 movel usp,a1
344 movel a1,a5@(60) /* save user stack pointer */
345 a7saveDone:
346
347 #
348 # save size of frame
349 movew d3,a0@-
350
351 #
352 # compute exception number
353 andl #0xfff,d2 /* mask off vector offset */
354 lsrw #2,d2 /* divide by 4 to get vect num */
355 movel d2,a0@- /* save it */
356 #
357 # save pc causing exception
358 movel a4,a0@-
359 #
360 # save old frame link and set the new value
361 movel _lastFrame,a1 /* last frame pointer */
362 movel a1,a0@- /* save pointer to prev frame */
363 movel a0,_lastFrame
364
365 movel d2,sp@- /* push exception num */
366 movel _exceptionHook,a0 /* get address of handler */
367 jbsr a0@ /* and call it */
368 clrl sp@ /* replace exception num parm with frame ptr */
369 jbsr __returnFromException /* jbsr, but never returns */
370 ");
371 #else /* mc68000 */
372 /* This function is called when an exception occurs. It translates the
373 * return address found on the stack into an exception vector # which
374 * is then handled by either handle_exception or a system handler.
375 * _catchException provides a front end for both.
376 *
377 * stack on entry: stack on exit:
378 * Program counter MSWord exception # MSWord
379 * Program counter LSWord exception # MSWord
380 * Status Register
381 * Return Address MSWord
382 * Return Address LSWord
383 */
384 asm("
385 .text
386 .globl __catchException
387 __catchException:");
388 DISABLE_INTERRUPTS();
389 asm("
390 moveml d0-d7/a0-a6,_registers /* save registers */
391 movel _lastFrame,a0 /* last frame pointer */
392 ");
393 SAVE_FP_REGS();
394 asm("
395 lea _registers,a5 /* get address of registers */
396 movel sp@+,d2 /* pop return address */
397 addl #1530,d2 /* convert return addr to */
398 divs #6,d2 /* exception number */
399 extl d2
400
401 moveql #3,d3 /* assume a three word frame */
402
403 cmpiw #3,d2 /* bus error or address error ? */
404 bgt normal /* if >3 then normal error */
405 movel sp@+,a0@- /* copy error info to frame buff*/
406 movel sp@+,a0@- /* these are never used */
407 moveql #7,d3 /* this is a 7 word frame */
408
409 normal:
410 movew sp@+,d1 /* pop status register */
411 movel sp@+,a4 /* pop program counter */
412 movew d1,a5@(66) /* save sr */
413 movel a4,a5@(68) /* save pc in _regisers[] */
414 movel a4,a0@- /* copy pc to frame buffer */
415 movew d1,a0@- /* copy sr to frame buffer */
416
417 movel sp,_superStack /* save supervisor sp */
418
419 andiw #0x2000,d1 /* were we in supervisor mode ? */
420 beq userMode
421 movel a7,a5@(60) /* save a7 */
422 bra saveDone
423 userMode:
424 movel usp,a1 /* save user stack pointer */
425 movel a1,a5@(60) /* save user stack pointer */
426 saveDone:
427
428 movew d3,a0@- /* push frame size in words */
429 movel d2,a0@- /* push vector number */
430 movel a4,a0@- /* push exception pc */
431
432 #
433 # save old frame link and set the new value
434 movel _lastFrame,a1 /* last frame pointer */
435 movel a1,a0@- /* save pointer to prev frame */
436 movel a0,_lastFrame
437
438 movel d2,sp@- /* push exception num */
439 movel _exceptionHook,a0 /* get address of handler */
440 jbsr a0@ /* and call it */
441 clrl sp@ /* replace exception num parm with frame ptr */
442 jbsr __returnFromException /* jbsr, but never returns */
443 ");
444 #endif
445
446
447 /*
448 * remcomHandler is a front end for handle_exception. It moves the
449 * stack pointer into an area reserved for debugger use in case the
450 * breakpoint happened in supervisor mode.
451 */
452 asm("_remcomHandler:");
453 asm(" addl #4,sp"); /* pop off return address */
454 asm(" movel sp@+,d0"); /* get the exception number */
455 asm(" movel _stackPtr,sp"); /* move to remcom stack area */
456 asm(" movel d0,sp@-"); /* push exception onto stack */
457 asm(" jbsr _handle_exception"); /* this never returns */
458 asm(" rts"); /* return */
459
460 void _returnFromException( Frame *frame )
461 {
462 /* if no passed in frame, use the last one */
463 if (! frame)
464 {
465 frame = lastFrame;
466 frame->frameSize = 4;
467 frame->format = 0;
468 frame->fsaveHeader = -1; /* restore regs, but we dont have fsave info*/
469 }
470
471 #ifndef mc68020
472 /* a 68000 cannot use the internal info pushed onto a bus error
473 * or address error frame when doing an RTE so don't put this info
474 * onto the stack or the stack will creep every time this happens.
475 */
476 frame->frameSize=3;
477 #endif
478
479 /* throw away any frames in the list after this frame */
480 lastFrame = frame;
481
482 frame->sr = registers[(int) PS];
483 frame->pc = registers[(int) PC];
484
485 if (registers[(int) PS] & 0x2000)
486 {
487 /* return to supervisor mode... */
488 return_to_super();
489 }
490 else
491 { /* return to user mode */
492 return_to_user();
493 }
494 }
495
496 int hex(ch)
497 char ch;
498 {
499 if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
500 if ((ch >= '0') && (ch <= '9')) return (ch-'0');
501 if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
502 return (-1);
503 }
504
505
506 /* scan for the sequence $<data>#<checksum> */
507 void getpacket(buffer)
508 char * buffer;
509 {
510 unsigned char checksum;
511 unsigned char xmitcsum;
512 int i;
513 int count;
514 char ch;
515
516 do {
517 /* wait around for the start character, ignore all other characters */
518 while ((ch = getDebugChar()) != '$');
519 checksum = 0;
520 xmitcsum = -1;
521
522 count = 0;
523
524 /* now, read until a # or end of buffer is found */
525 while (count < BUFMAX) {
526 ch = getDebugChar();
527 if (ch == '#') break;
528 checksum = checksum + ch;
529 buffer[count] = ch;
530 count = count + 1;
531 }
532 buffer[count] = 0;
533
534 if (ch == '#') {
535 xmitcsum = hex(getDebugChar()) << 4;
536 xmitcsum += hex(getDebugChar());
537 if ((remote_debug ) && (checksum != xmitcsum)) {
538 fprintf(stderr,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
539 checksum,xmitcsum,buffer);
540 }
541
542 if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */
543 else {
544 putDebugChar('+'); /* successful transfer */
545 /* if a sequence char is present, reply the sequence ID */
546 if (buffer[2] == ':') {
547 putDebugChar( buffer[0] );
548 putDebugChar( buffer[1] );
549 /* remove sequence chars from buffer */
550 count = strlen(buffer);
551 for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
552 }
553 }
554 }
555 } while (checksum != xmitcsum);
556
557 }
558
559 /* send the packet in buffer. The host get's one chance to read it.
560 This routine does not wait for a positive acknowledge. */
561
562
563 void putpacket(buffer)
564 char * buffer;
565 {
566 unsigned char checksum;
567 int count;
568 char ch;
569
570 /* $<packet info>#<checksum>. */
571 do {
572 putDebugChar('$');
573 checksum = 0;
574 count = 0;
575
576 while (ch=buffer[count]) {
577 if (! putDebugChar(ch)) return;
578 checksum += ch;
579 count += 1;
580 }
581
582 putDebugChar('#');
583 putDebugChar(hexchars[checksum >> 4]);
584 putDebugChar(hexchars[checksum % 16]);
585
586 } while (1 == 0); /* (getDebugChar() != '+'); */
587
588 }
589
590 char remcomInBuffer[BUFMAX];
591 char remcomOutBuffer[BUFMAX];
592 static short error;
593
594
595 void debug_error(format, parm)
596 char * format;
597 char * parm;
598 {
599 if (remote_debug) fprintf(stderr,format,parm);
600 }
601
602 /* convert the memory pointed to by mem into hex, placing result in buf */
603 /* return a pointer to the last char put in buf (null) */
604 char* mem2hex(mem, buf, count)
605 char* mem;
606 char* buf;
607 int count;
608 {
609 int i;
610 unsigned char ch;
611 for (i=0;i<count;i++) {
612 ch = *mem++;
613 *buf++ = hexchars[ch >> 4];
614 *buf++ = hexchars[ch % 16];
615 }
616 *buf = 0;
617 return(buf);
618 }
619
620 /* convert the hex array pointed to by buf into binary to be placed in mem */
621 /* return a pointer to the character AFTER the last byte written */
622 char* hex2mem(buf, mem, count)
623 char* buf;
624 char* mem;
625 int count;
626 {
627 int i;
628 unsigned char ch;
629 for (i=0;i<count;i++) {
630 ch = hex(*buf++) << 4;
631 ch = ch + hex(*buf++);
632 *mem++ = ch;
633 }
634 return(mem);
635 }
636
637 /* a bus error has occurred, perform a longjmp
638 to return execution and allow handling of the error */
639
640 void handle_buserror()
641 {
642 longjmp(remcomEnv,1);
643 }
644
645 /* this function takes the 68000 exception number and attempts to
646 translate this number into a unix compatible signal value */
647 int computeSignal( exceptionVector )
648 int exceptionVector;
649 {
650 int sigval;
651 switch (exceptionVector) {
652 case 2 : sigval = 10; break; /* bus error */
653 case 3 : sigval = 10; break; /* address error */
654 case 4 : sigval = 4; break; /* illegal instruction */
655 case 5 : sigval = 8; break; /* zero divide */
656 case 6 : sigval = 16; break; /* chk instruction */
657 case 7 : sigval = 16; break; /* trapv instruction */
658 case 8 : sigval = 11; break; /* privilege violation */
659 case 9 : sigval = 5; break; /* trace trap */
660 case 10: sigval = 4; break; /* line 1010 emulator */
661 case 11: sigval = 4; break; /* line 1111 emulator */
662 case 13: sigval = 8; break; /* floating point err */
663 case 31: sigval = 2; break; /* interrupt */
664 case 33: sigval = 5; break; /* breakpoint */
665 case 40: sigval = 8; break; /* floating point err */
666 case 48: sigval = 8; break; /* floating point err */
667 case 49: sigval = 8; break; /* floating point err */
668 case 50: sigval = 8; break; /* zero divide */
669 case 51: sigval = 8; break; /* underflow */
670 case 52: sigval = 8; break; /* operand error */
671 case 53: sigval = 8; break; /* overflow */
672 case 54: sigval = 8; break; /* NAN */
673 default:
674 sigval = 7; /* "software generated"*/
675 }
676 return (sigval);
677 }
678
679 /**********************************************/
680 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
681 /* RETURN NUMBER OF CHARS PROCESSED */
682 /**********************************************/
683 int hexToInt(char **ptr, int *intValue)
684 {
685 int numChars = 0;
686 int hexValue;
687
688 *intValue = 0;
689
690 while (**ptr)
691 {
692 hexValue = hex(**ptr);
693 if (hexValue >=0)
694 {
695 *intValue = (*intValue <<4) | hexValue;
696 numChars ++;
697 }
698 else
699 break;
700
701 (*ptr)++;
702 }
703
704 return (numChars);
705 }
706
707 /*
708 * This function does all command procesing for interfacing to gdb.
709 */
710 void handle_exception(int exceptionVector)
711 {
712 int sigval;
713 int addr, length;
714 char * ptr;
715 int newPC;
716 Frame *frame;
717
718 if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n",
719 exceptionVector,
720 registers[ PS ],
721 registers[ PC ]);
722
723 /* reply to host that an exception has occurred */
724 sigval = computeSignal( exceptionVector );
725 remcomOutBuffer[0] = 'S';
726 remcomOutBuffer[1] = hexchars[sigval >> 4];
727 remcomOutBuffer[2] = hexchars[sigval % 16];
728 remcomOutBuffer[3] = 0;
729
730 putpacket(remcomOutBuffer);
731
732 while (1==1) {
733 error = 0;
734 remcomOutBuffer[0] = 0;
735 getpacket(remcomInBuffer);
736 switch (remcomInBuffer[0]) {
737 case '?' : remcomOutBuffer[0] = 'S';
738 remcomOutBuffer[1] = hexchars[sigval >> 4];
739 remcomOutBuffer[2] = hexchars[sigval % 16];
740 remcomOutBuffer[3] = 0;
741 break;
742 case 'd' : remote_debug = !(remote_debug); /* toggle debug flag */
743 break;
744 case 'g' : /* return the value of the CPU registers */
745 mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES);
746 break;
747 case 'G' : /* set the value of the CPU registers - return OK */
748 hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES);
749 strcpy(remcomOutBuffer,"OK");
750 break;
751
752 /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
753 case 'm' :
754 if (setjmp(remcomEnv) == 0)
755 {
756 exceptionHandler(2,handle_buserror);
757
758 /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
759 ptr = &remcomInBuffer[1];
760 if (hexToInt(&ptr,&addr))
761 if (*(ptr++) == ',')
762 if (hexToInt(&ptr,&length))
763 {
764 ptr = 0;
765 mem2hex((char*) addr, remcomOutBuffer, length);
766 }
767
768 if (ptr)
769 {
770 strcpy(remcomOutBuffer,"E01");
771 debug_error("malformed read memory command: %s",remcomInBuffer);
772 }
773 }
774 else {
775 exceptionHandler(2,_catchException);
776 strcpy(remcomOutBuffer,"E03");
777 debug_error("bus error");
778 }
779
780 /* restore handler for bus error */
781 exceptionHandler(2,_catchException);
782 break;
783
784 /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
785 case 'M' :
786 if (setjmp(remcomEnv) == 0) {
787 exceptionHandler(2,handle_buserror);
788
789 /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
790 ptr = &remcomInBuffer[1];
791 if (hexToInt(&ptr,&addr))
792 if (*(ptr++) == ',')
793 if (hexToInt(&ptr,&length))
794 if (*(ptr++) == ':')
795 {
796 hex2mem(ptr, (char*) addr, length);
797 ptr = 0;
798 strcpy(remcomOutBuffer,"OK");
799 }
800 if (ptr)
801 {
802 strcpy(remcomOutBuffer,"E02");
803 debug_error("malformed write memory command: %s",remcomInBuffer);
804 }
805 }
806 else {
807 exceptionHandler(2,_catchException);
808 strcpy(remcomOutBuffer,"E03");
809 debug_error("bus error");
810 }
811
812 /* restore handler for bus error */
813 exceptionHandler(2,_catchException);
814 break;
815
816 /* cAA..AA Continue at address AA..AA(optional) */
817 /* sAA..AA Step one instruction from AA..AA(optional) */
818 case 'c' :
819 case 's' :
820 /* try to read optional parameter, pc unchanged if no parm */
821 ptr = &remcomInBuffer[1];
822 if (hexToInt(&ptr,&addr))
823 registers[ PC ] = addr;
824
825 newPC = registers[ PC];
826
827 /* clear the trace bit */
828 registers[ PS ] &= 0x7fff;
829
830 /* set the trace bit if we're stepping */
831 if (remcomInBuffer[0] == 's') registers[ PS ] |= 0x8000;
832
833 /*
834 * look for newPC in the linked list of exception frames.
835 * if it is found, use the old frame it. otherwise,
836 * fake up a dummy frame in returnFromException().
837 */
838 if (remote_debug) printf("new pc = 0x%x\n",newPC);
839 frame = lastFrame;
840 while (frame)
841 {
842 if (remote_debug)
843 printf("frame at 0x%x has pc=0x%x, except#=%d\n",
844 frame,frame->exceptionPC,
845 frame->exceptionVector);
846 if (frame->exceptionPC == newPC) break; /* bingo! a match */
847 /*
848 * for a breakpoint instruction, the saved pc may
849 * be off by two due to re-executing the instruction
850 * replaced by the trap instruction. Check for this.
851 */
852 if ((frame->exceptionVector == 33) &&
853 (frame->exceptionPC == (newPC+2))) break;
854 if (frame == frame->previous)
855 {
856 frame = 0; /* no match found */
857 break;
858 }
859 frame = frame->previous;
860 }
861
862 /*
863 * If we found a match for the PC AND we are not returning
864 * as a result of a breakpoint (33),
865 * trace exception (9), nmi (31), jmp to
866 * the old exception handler as if this code never ran.
867 */
868 if (frame)
869 {
870 if ((frame->exceptionVector != 9) &&
871 (frame->exceptionVector != 31) &&
872 (frame->exceptionVector != 33))
873 {
874 /*
875 * invoke the previous handler.
876 */
877 if (oldExceptionHook)
878 (*oldExceptionHook) (frame->exceptionVector);
879 newPC = registers[ PC ]; /* pc may have changed */
880 if (newPC != frame->exceptionPC)
881 {
882 if (remote_debug)
883 printf("frame at 0x%x has pc=0x%x, except#=%d\n",
884 frame,frame->exceptionPC,
885 frame->exceptionVector);
886 /* re-use the last frame, we're skipping it (longjump?)*/
887 frame = (Frame *) 0;
888 _returnFromException( frame ); /* this is a jump */
889 }
890 }
891 }
892
893 /* if we couldn't find a frame, create one */
894 if (frame == 0)
895 {
896 frame = lastFrame -1 ;
897
898 /* by using a bunch of print commands with breakpoints,
899 it's possible for the frame stack to creep down. If it creeps
900 too far, give up and reset it to the top. Normal use should
901 not see this happen.
902 */
903 if ((unsigned int) (frame-2) < (unsigned int) &gdbFrameStack)
904 {
905 initializeRemcomErrorFrame();
906 frame = lastFrame;
907 }
908 frame->previous = lastFrame;
909 lastFrame = frame;
910 frame = 0; /* null so _return... will properly initialize it */
911 }
912
913 _returnFromException( frame ); /* this is a jump */
914
915 break;
916
917 /* kill the program */
918 case 'k' : /* do nothing */
919 break;
920 } /* switch */
921
922 /* reply to the request */
923 putpacket(remcomOutBuffer);
924 }
925 }
926
927
928 void initializeRemcomErrorFrame(void)
929 {
930 lastFrame = ((Frame *) &gdbFrameStack[FRAMESIZE-1]) - 1;
931 lastFrame->previous = lastFrame;
932 }
933
934 /* this function is used to set up exception handlers for tracing and
935 breakpoints */
936 void set_debug_traps()
937 {
938 extern void _debug_level7();
939 extern void remcomHandler();
940 int exception;
941
942 initializeRemcomErrorFrame();
943 stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
944
945 for (exception = 2; exception <= 23; exception++)
946 exceptionHandler(exception,_catchException);
947
948 /* level 7 interrupt */
949 exceptionHandler(31,_debug_level7);
950
951 /* breakpoint exception (trap #1) */
952 exceptionHandler(33,_catchException);
953
954 /* floating point error (trap #8) */
955 exceptionHandler(40,_catchException);
956
957 /* 48 to 54 are floating point coprocessor errors */
958 for (exception = 48; exception <= 54; exception++)
959 exceptionHandler(exception,_catchException);
960
961 if (oldExceptionHook != remcomHandler)
962 {
963 oldExceptionHook = exceptionHook;
964 exceptionHook = remcomHandler;
965 }
966
967 initialized = 1;
968
969 }
970
971 /* This function will generate a breakpoint exception. It is used at the
972 beginning of a program to sync up with a debugger and can be used
973 otherwise as a quick means to stop program execution and "break" into
974 the debugger. */
975
976 void breakpoint()
977 {
978 if (initialized) BREAKPOINT();
979 }
980
This page took 0.050573 seconds and 4 git commands to generate.