source: rtems/c/src/lib/libbsp/m68k/ods68302/startup/m68k-stub.c @ 3ec7bfc

4.104.114.84.95
Last change on this file since 3ec7bfc was 3ec7bfc, checked in by Joel Sherrill <joel.sherrill@…>, on 03/24/98 at 16:24:39

Rename hppa1_1 to hppa1.1 and switched to using XXX macros for
the CPU family name constants.

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