OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [m68k-stub.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.