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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [i386-stub.c] - Blame information for rev 1765

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
 *  Modified for 386 by Jim Kingdon, Cygnus Support.
33
 *
34
 *  To enable debugger support, two things need to happen.  One, a
35
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
36
 *  or error conditions to be properly intercepted and reported to gdb.
37
 *  Two, a breakpoint needs to be generated to begin communication.  This
38
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
39
 *  simulates a breakpoint by executing a trap #1.
40
 *
41
 *  The external function exceptionHandler() is
42
 *  used to attach a specific handler to a specific 386 vector number.
43
 *  It should use the same privilege level it runs at.  It should
44
 *  install it as an interrupt gate so that interrupts are masked
45
 *  while the handler runs.
46
 *
47
 *  Because gdb will sometimes write to the stack area to execute function
48
 *  calls, this program cannot rely on using the supervisor stack so it
49
 *  uses it's own stack area reserved in the int array remcomStack.
50
 *
51
 *************
52
 *
53
 *    The following gdb commands are supported:
54
 *
55
 * command          function                               Return value
56
 *
57
 *    g             return the value of the CPU registers  hex data or ENN
58
 *    G             set the value of the CPU registers     OK or ENN
59
 *
60
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
61
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
62
 *
63
 *    c             Resume at current address              SNN   ( signal NN)
64
 *    cAA..AA       Continue at address AA..AA             SNN
65
 *
66
 *    s             Step one instruction                   SNN
67
 *    sAA..AA       Step one instruction from AA..AA       SNN
68
 *
69
 *    k             kill
70
 *
71
 *    ?             What was the last sigval ?             SNN   (signal NN)
72
 *
73
 * All commands and responses are sent with a packet which includes a
74
 * checksum.  A packet consists of
75
 *
76
 * $<packet info>#<checksum>.
77
 *
78
 * where
79
 * <packet info> :: <characters representing the command or response>
80
 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
81
 *
82
 * When a packet is received, it is first acknowledged with either '+' or '-'.
83
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
84
 *
85
 * Example:
86
 *
87
 * Host:                  Reply:
88
 * $m0,10#2a               +$00010203040506070809101112131415#42
89
 *
90
 ****************************************************************************/
91
 
92
#include <stdio.h>
93
#include <string.h>
94
 
95
/************************************************************************
96
 *
97
 * external low-level support routines
98
 */
99
 
100
extern void putDebugChar();     /* write a single character      */
101
extern int getDebugChar();      /* read and return a single char */
102
extern void exceptionHandler(); /* assign an exception handler   */
103
 
104
/************************************************************************/
105
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
106
/* at least NUMREGBYTES*2 are needed for register packets */
107
#define BUFMAX 400
108
 
109
static char initialized;  /* boolean flag. != 0 means we've been initialized */
110
 
111
int     remote_debug;
112
/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
113
 
114
static const char hexchars[]="0123456789abcdef";
115
 
116
/* Number of registers.  */
117
#define NUMREGS 16
118
 
119
/* Number of bytes of registers.  */
120
#define NUMREGBYTES (NUMREGS * 4)
121
 
122
enum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
123
               PC /* also known as eip */,
124
               PS /* also known as eflags */,
125
               CS, SS, DS, ES, FS, GS};
126
 
127
/*
128
 * these should not be static cuz they can be used outside this module
129
 */
130
int registers[NUMREGS];
131
 
132
#define STACKSIZE 10000
133
int remcomStack[STACKSIZE/sizeof(int)];
134
static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
135
 
136
/***************************  ASSEMBLY CODE MACROS *************************/
137
/*                                                                         */
138
 
139
extern void
140
return_to_prog ();
141
 
142
/* Restore the program's registers (including the stack pointer, which
143
   means we get the right stack and don't have to worry about popping our
144
   return address and any stack frames and so on) and return.  */
145
asm(".text");
146
asm(".globl _return_to_prog");
147
asm("_return_to_prog:");
148
asm("        movw _registers+44, %ss");
149
asm("        movl _registers+16, %esp");
150
asm("        movl _registers+4, %ecx");
151
asm("        movl _registers+8, %edx");
152
asm("        movl _registers+12, %ebx");
153
asm("        movl _registers+20, %ebp");
154
asm("        movl _registers+24, %esi");
155
asm("        movl _registers+28, %edi");
156
asm("        movw _registers+48, %ds");
157
asm("        movw _registers+52, %es");
158
asm("        movw _registers+56, %fs");
159
asm("        movw _registers+60, %gs");
160
asm("        movl _registers+36, %eax");
161
asm("        pushl %eax");  /* saved eflags */
162
asm("        movl _registers+40, %eax");
163
asm("        pushl %eax");  /* saved cs */
164
asm("        movl _registers+32, %eax");
165
asm("        pushl %eax");  /* saved eip */
166
asm("        movl _registers, %eax");
167
/* use iret to restore pc and flags together so
168
   that trace flag works right.  */
169
asm("        iret");
170
 
171
#define BREAKPOINT() asm("   int $3");
172
 
173
/* Put the error code here just in case the user cares.  */
174
int gdb_i386errcode;
175
/* Likewise, the vector number here (since GDB only gets the signal
176
   number through the usual means, and that's not very specific).  */
177
int gdb_i386vector = -1;
178
 
179
/* GDB stores segment registers in 32-bit words (that's just the way
180
   m-i386v.h is written).  So zero the appropriate areas in registers.  */
181
#define SAVE_REGISTERS1() \
182
  asm ("movl %eax, _registers");                                          \
183
  asm ("movl %ecx, _registers+4");                                           \
184
  asm ("movl %edx, _registers+8");                                           \
185
  asm ("movl %ebx, _registers+12");                                          \
186
  asm ("movl %ebp, _registers+20");                                          \
187
  asm ("movl %esi, _registers+24");                                          \
188
  asm ("movl %edi, _registers+28");                                          \
189
  asm ("movw $0, %ax");                                                      \
190
  asm ("movw %ds, _registers+48");                                           \
191
  asm ("movw %ax, _registers+50");                                           \
192
  asm ("movw %es, _registers+52");                                           \
193
  asm ("movw %ax, _registers+54");                                           \
194
  asm ("movw %fs, _registers+56");                                           \
195
  asm ("movw %ax, _registers+58");                                           \
196
  asm ("movw %gs, _registers+60");                                           \
197
  asm ("movw %ax, _registers+62");
198
#define SAVE_ERRCODE() \
199
  asm ("popl %ebx");                                  \
200
  asm ("movl %ebx, _gdb_i386errcode");
201
#define SAVE_REGISTERS2() \
202
  asm ("popl %ebx"); /* old eip */                                           \
203
  asm ("movl %ebx, _registers+32");                                          \
204
  asm ("popl %ebx");     /* old cs */                                        \
205
  asm ("movl %ebx, _registers+40");                                          \
206
  asm ("movw %ax, _registers+42");                                           \
207
  asm ("popl %ebx");     /* old eflags */                                    \
208
  asm ("movl %ebx, _registers+36");                                          \
209
  /* Now that we've done the pops, we can save the stack pointer.");  */   \
210
  asm ("movw %ss, _registers+44");                                           \
211
  asm ("movw %ax, _registers+46");                                           \
212
  asm ("movl %esp, _registers+16");
213
 
214
/* See if mem_fault_routine is set, if so just IRET to that address.  */
215
#define CHECK_FAULT() \
216
  asm ("cmpl $0, _mem_fault_routine");                                     \
217
  asm ("jne mem_fault");
218
 
219
asm (".text");
220
asm ("mem_fault:");
221
/* OK to clobber temp registers; we're just going to end up in set_mem_err.  */
222
/* Pop error code from the stack and save it.  */
223
asm ("     popl %eax");
224
asm ("     movl %eax, _gdb_i386errcode");
225
 
226
asm ("     popl %eax"); /* eip */
227
/* We don't want to return there, we want to return to the function
228
   pointed to by mem_fault_routine instead.  */
229
asm ("     movl _mem_fault_routine, %eax");
230
asm ("     popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits).  */
231
asm ("     popl %edx"); /* eflags */
232
 
233
/* Remove this stack frame; when we do the iret, we will be going to
234
   the start of a function, so we want the stack to look just like it
235
   would after a "call" instruction.  */
236
asm ("     leave");
237
 
238
/* Push the stuff that iret wants.  */
239
asm ("     pushl %edx"); /* eflags */
240
asm ("     pushl %ecx"); /* cs */
241
asm ("     pushl %eax"); /* eip */
242
 
243
/* Zero mem_fault_routine.  */
244
asm ("     movl $0, %eax");
245
asm ("     movl %eax, _mem_fault_routine");
246
 
247
asm ("iret");
248
 
249
#define CALL_HOOK() asm("call _remcomHandler");
250
 
251
/* This function is called when a i386 exception occurs.  It saves
252
 * all the cpu regs in the _registers array, munges the stack a bit,
253
 * and invokes an exception handler (remcom_handler).
254
 *
255
 * stack on entry:                       stack on exit:
256
 *   old eflags                          vector number
257
 *   old cs (zero-filled to 32 bits)
258
 *   old eip
259
 *
260
 */
261
extern void _catchException3();
262
asm(".text");
263
asm(".globl __catchException3");
264
asm("__catchException3:");
265
SAVE_REGISTERS1();
266
SAVE_REGISTERS2();
267
asm ("pushl $3");
268
CALL_HOOK();
269
 
270
/* Same thing for exception 1.  */
271
extern void _catchException1();
272
asm(".text");
273
asm(".globl __catchException1");
274
asm("__catchException1:");
275
SAVE_REGISTERS1();
276
SAVE_REGISTERS2();
277
asm ("pushl $1");
278
CALL_HOOK();
279
 
280
/* Same thing for exception 0.  */
281
extern void _catchException0();
282
asm(".text");
283
asm(".globl __catchException0");
284
asm("__catchException0:");
285
SAVE_REGISTERS1();
286
SAVE_REGISTERS2();
287
asm ("pushl $0");
288
CALL_HOOK();
289
 
290
/* Same thing for exception 4.  */
291
extern void _catchException4();
292
asm(".text");
293
asm(".globl __catchException4");
294
asm("__catchException4:");
295
SAVE_REGISTERS1();
296
SAVE_REGISTERS2();
297
asm ("pushl $4");
298
CALL_HOOK();
299
 
300
/* Same thing for exception 5.  */
301
extern void _catchException5();
302
asm(".text");
303
asm(".globl __catchException5");
304
asm("__catchException5:");
305
SAVE_REGISTERS1();
306
SAVE_REGISTERS2();
307
asm ("pushl $5");
308
CALL_HOOK();
309
 
310
/* Same thing for exception 6.  */
311
extern void _catchException6();
312
asm(".text");
313
asm(".globl __catchException6");
314
asm("__catchException6:");
315
SAVE_REGISTERS1();
316
SAVE_REGISTERS2();
317
asm ("pushl $6");
318
CALL_HOOK();
319
 
320
/* Same thing for exception 7.  */
321
extern void _catchException7();
322
asm(".text");
323
asm(".globl __catchException7");
324
asm("__catchException7:");
325
SAVE_REGISTERS1();
326
SAVE_REGISTERS2();
327
asm ("pushl $7");
328
CALL_HOOK();
329
 
330
/* Same thing for exception 8.  */
331
extern void _catchException8();
332
asm(".text");
333
asm(".globl __catchException8");
334
asm("__catchException8:");
335
SAVE_REGISTERS1();
336
SAVE_ERRCODE();
337
SAVE_REGISTERS2();
338
asm ("pushl $8");
339
CALL_HOOK();
340
 
341
/* Same thing for exception 9.  */
342
extern void _catchException9();
343
asm(".text");
344
asm(".globl __catchException9");
345
asm("__catchException9:");
346
SAVE_REGISTERS1();
347
SAVE_REGISTERS2();
348
asm ("pushl $9");
349
CALL_HOOK();
350
 
351
/* Same thing for exception 10.  */
352
extern void _catchException10();
353
asm(".text");
354
asm(".globl __catchException10");
355
asm("__catchException10:");
356
SAVE_REGISTERS1();
357
SAVE_ERRCODE();
358
SAVE_REGISTERS2();
359
asm ("pushl $10");
360
CALL_HOOK();
361
 
362
/* Same thing for exception 12.  */
363
extern void _catchException12();
364
asm(".text");
365
asm(".globl __catchException12");
366
asm("__catchException12:");
367
SAVE_REGISTERS1();
368
SAVE_ERRCODE();
369
SAVE_REGISTERS2();
370
asm ("pushl $12");
371
CALL_HOOK();
372
 
373
/* Same thing for exception 16.  */
374
extern void _catchException16();
375
asm(".text");
376
asm(".globl __catchException16");
377
asm("__catchException16:");
378
SAVE_REGISTERS1();
379
SAVE_REGISTERS2();
380
asm ("pushl $16");
381
CALL_HOOK();
382
 
383
/* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff.  */
384
 
385
/* Same thing for exception 13.  */
386
extern void _catchException13 ();
387
asm (".text");
388
asm (".globl __catchException13");
389
asm ("__catchException13:");
390
CHECK_FAULT();
391
SAVE_REGISTERS1();
392
SAVE_ERRCODE();
393
SAVE_REGISTERS2();
394
asm ("pushl $13");
395
CALL_HOOK();
396
 
397
/* Same thing for exception 11.  */
398
extern void _catchException11 ();
399
asm (".text");
400
asm (".globl __catchException11");
401
asm ("__catchException11:");
402
CHECK_FAULT();
403
SAVE_REGISTERS1();
404
SAVE_ERRCODE();
405
SAVE_REGISTERS2();
406
asm ("pushl $11");
407
CALL_HOOK();
408
 
409
/* Same thing for exception 14.  */
410
extern void _catchException14 ();
411
asm (".text");
412
asm (".globl __catchException14");
413
asm ("__catchException14:");
414
CHECK_FAULT();
415
SAVE_REGISTERS1();
416
SAVE_ERRCODE();
417
SAVE_REGISTERS2();
418
asm ("pushl $14");
419
CALL_HOOK();
420
 
421
/*
422
 * remcomHandler is a front end for handle_exception.  It moves the
423
 * stack pointer into an area reserved for debugger use.
424
 */
425
asm("_remcomHandler:");
426
asm("           popl %eax");        /* pop off return address     */
427
asm("           popl %eax");      /* get the exception number   */
428
asm("           movl _stackPtr, %esp"); /* move to remcom stack area  */
429
asm("           pushl %eax");   /* push exception onto stack  */
430
asm("           call  _handle_exception");    /* this never returns */
431
 
432
void _returnFromException()
433
{
434
  return_to_prog ();
435
}
436
 
437
int hex(ch)
438
char ch;
439
{
440
  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
441
  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
442
  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
443
  return (-1);
444
}
445
 
446
static char remcomInBuffer[BUFMAX];
447
static char remcomOutBuffer[BUFMAX];
448
 
449
/* scan for the sequence $<data>#<checksum>     */
450
 
451
unsigned char *
452
getpacket ()
453
{
454
  unsigned char *buffer = &remcomInBuffer[0];
455
  unsigned char checksum;
456
  unsigned char xmitcsum;
457
  int count;
458
  char ch;
459
 
460
  while (1)
461
    {
462
      /* wait around for the start character, ignore all other characters */
463
      while ((ch = getDebugChar ()) != '$')
464
        ;
465
 
466
retry:
467
      checksum = 0;
468
      xmitcsum = -1;
469
      count = 0;
470
 
471
      /* now, read until a # or end of buffer is found */
472
      while (count < BUFMAX)
473
        {
474
          ch = getDebugChar ();
475
          if (ch == '$')
476
            goto retry;
477
          if (ch == '#')
478
            break;
479
          checksum = checksum + ch;
480
          buffer[count] = ch;
481
          count = count + 1;
482
        }
483
      buffer[count] = 0;
484
 
485
      if (ch == '#')
486
        {
487
          ch = getDebugChar ();
488
          xmitcsum = hex (ch) << 4;
489
          ch = getDebugChar ();
490
          xmitcsum += hex (ch);
491
 
492
          if (checksum != xmitcsum)
493
            {
494
              if (remote_debug)
495
                {
496
                  fprintf (stderr,
497
                      "bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
498
                           checksum, xmitcsum, buffer);
499
                }
500
              putDebugChar ('-');       /* failed checksum */
501
            }
502
          else
503
            {
504
              putDebugChar ('+');       /* successful transfer */
505
 
506
              /* if a sequence char is present, reply the sequence ID */
507
              if (buffer[2] == ':')
508
                {
509
                  putDebugChar (buffer[0]);
510
                  putDebugChar (buffer[1]);
511
 
512
                  return &buffer[3];
513
                }
514
 
515
              return &buffer[0];
516
            }
517
        }
518
    }
519
}
520
 
521
/* send the packet in buffer.  */
522
 
523
void putpacket(buffer)
524
    unsigned char *buffer;
525
{
526
  unsigned char checksum;
527
  int  count;
528
  char ch;
529
 
530
  /*  $<packet info>#<checksum>. */
531
  do {
532
  putDebugChar('$');
533
  checksum = 0;
534
  count    = 0;
535
 
536
  while (ch=buffer[count]) {
537
    putDebugChar(ch);
538
    checksum += ch;
539
    count += 1;
540
  }
541
 
542
  putDebugChar('#');
543
  putDebugChar(hexchars[checksum >> 4]);
544
  putDebugChar(hexchars[checksum % 16]);
545
 
546
  } while (getDebugChar() != '+');
547
 
548
}
549
 
550
void debug_error(format, parm)
551
char * format;
552
char * parm;
553
{
554
  if (remote_debug) fprintf (stderr,format,parm);
555
}
556
 
557
/* Address of a routine to RTE to if we get a memory fault.  */
558
static void (*volatile mem_fault_routine)() = NULL;
559
 
560
/* Indicate to caller of mem2hex or hex2mem that there has been an
561
   error.  */
562
static volatile int mem_err = 0;
563
 
564
void
565
set_mem_err ()
566
{
567
  mem_err = 1;
568
}
569
 
570
/* These are separate functions so that they are so short and sweet
571
   that the compiler won't save any registers (if there is a fault
572
   to mem_fault, they won't get restored, so there better not be any
573
   saved).  */
574
int
575
get_char (addr)
576
     char *addr;
577
{
578
  return *addr;
579
}
580
 
581
void
582
set_char (addr, val)
583
     char *addr;
584
     int val;
585
{
586
  *addr = val;
587
}
588
 
589
/* convert the memory pointed to by mem into hex, placing result in buf */
590
/* return a pointer to the last char put in buf (null) */
591
/* If MAY_FAULT is non-zero, then we should set mem_err in response to
592
   a fault; if zero treat a fault like any other fault in the stub.  */
593
char* mem2hex(mem, buf, count, may_fault)
594
char* mem;
595
char* buf;
596
int   count;
597
int may_fault;
598
{
599
      int i;
600
      unsigned char ch;
601
 
602
      if (may_fault)
603
          mem_fault_routine = set_mem_err;
604
      for (i=0;i<count;i++) {
605
          ch = get_char (mem++);
606
          if (may_fault && mem_err)
607
            return (buf);
608
          *buf++ = hexchars[ch >> 4];
609
          *buf++ = hexchars[ch % 16];
610
      }
611
      *buf = 0;
612
      if (may_fault)
613
          mem_fault_routine = NULL;
614
      return(buf);
615
}
616
 
617
/* convert the hex array pointed to by buf into binary to be placed in mem */
618
/* return a pointer to the character AFTER the last byte written */
619
char* hex2mem(buf, mem, count, may_fault)
620
char* buf;
621
char* mem;
622
int   count;
623
int may_fault;
624
{
625
      int i;
626
      unsigned char ch;
627
 
628
      if (may_fault)
629
          mem_fault_routine = set_mem_err;
630
      for (i=0;i<count;i++) {
631
          ch = hex(*buf++) << 4;
632
          ch = ch + hex(*buf++);
633
          set_char (mem++, ch);
634
          if (may_fault && mem_err)
635
            return (mem);
636
      }
637
      if (may_fault)
638
          mem_fault_routine = NULL;
639
      return(mem);
640
}
641
 
642
/* this function takes the 386 exception vector and attempts to
643
   translate this number into a unix compatible signal value */
644
int computeSignal( exceptionVector )
645
int exceptionVector;
646
{
647
  int sigval;
648
  switch (exceptionVector) {
649
    case 0 : sigval = 8; break; /* divide by zero */
650
    case 1 : sigval = 5; break; /* debug exception */
651
    case 3 : sigval = 5; break; /* breakpoint */
652
    case 4 : sigval = 16; break; /* into instruction (overflow) */
653
    case 5 : sigval = 16; break; /* bound instruction */
654
    case 6 : sigval = 4; break; /* Invalid opcode */
655
    case 7 : sigval = 8; break; /* coprocessor not available */
656
    case 8 : sigval = 7; break; /* double fault */
657
    case 9 : sigval = 11; break; /* coprocessor segment overrun */
658
    case 10 : sigval = 11; break; /* Invalid TSS */
659
    case 11 : sigval = 11; break; /* Segment not present */
660
    case 12 : sigval = 11; break; /* stack exception */
661
    case 13 : sigval = 11; break; /* general protection */
662
    case 14 : sigval = 11; break; /* page fault */
663
    case 16 : sigval = 7; break; /* coprocessor error */
664
    default:
665
      sigval = 7;         /* "software generated"*/
666
  }
667
  return (sigval);
668
}
669
 
670
/**********************************************/
671
/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
672
/* RETURN NUMBER OF CHARS PROCESSED           */
673
/**********************************************/
674
int hexToInt(char **ptr, int *intValue)
675
{
676
    int numChars = 0;
677
    int hexValue;
678
 
679
    *intValue = 0;
680
 
681
    while (**ptr)
682
    {
683
        hexValue = hex(**ptr);
684
        if (hexValue >=0)
685
        {
686
            *intValue = (*intValue <<4) | hexValue;
687
            numChars ++;
688
        }
689
        else
690
            break;
691
 
692
        (*ptr)++;
693
    }
694
 
695
    return (numChars);
696
}
697
 
698
/*
699
 * This function does all command procesing for interfacing to gdb.
700
 */
701
void handle_exception(int exceptionVector)
702
{
703
  int    sigval, stepping;
704
  int    addr, length;
705
  char * ptr;
706
  int    newPC;
707
 
708
  gdb_i386vector = exceptionVector;
709
 
710
  if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n",
711
                            exceptionVector,
712
                            registers[ PS ],
713
                            registers[ PC ]);
714
 
715
  /* reply to host that an exception has occurred */
716
  sigval = computeSignal( exceptionVector );
717
  remcomOutBuffer[0] = 'S';
718
  remcomOutBuffer[1] =  hexchars[sigval >> 4];
719
  remcomOutBuffer[2] =  hexchars[sigval % 16];
720
  remcomOutBuffer[3] = 0;
721
 
722
  putpacket(remcomOutBuffer);
723
 
724
  stepping = 0;
725
 
726
  while (1==1) {
727
    remcomOutBuffer[0] = 0;
728
    ptr = getpacket();
729
 
730
    switch (*ptr++) {
731
      case '?' :   remcomOutBuffer[0] = 'S';
732
                   remcomOutBuffer[1] =  hexchars[sigval >> 4];
733
                   remcomOutBuffer[2] =  hexchars[sigval % 16];
734
                   remcomOutBuffer[3] = 0;
735
                 break;
736
      case 'd' : remote_debug = !(remote_debug);  /* toggle debug flag */
737
                 break;
738
      case 'g' : /* return the value of the CPU registers */
739
                mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
740
                break;
741
      case 'G' : /* set the value of the CPU registers - return OK */
742
                hex2mem(ptr, (char*) registers, NUMREGBYTES, 0);
743
                strcpy(remcomOutBuffer,"OK");
744
                break;
745
      case 'P' : /* set the value of a single CPU register - return OK */
746
                {
747
                  int regno;
748
 
749
                  if (hexToInt (&ptr, &regno) && *ptr++ == '=')
750
                  if (regno >= 0 && regno < NUMREGS)
751
                    {
752
                      hex2mem (ptr, (char *)&registers[regno], 4, 0);
753
                      strcpy(remcomOutBuffer,"OK");
754
                      break;
755
                    }
756
 
757
                  strcpy (remcomOutBuffer, "E01");
758
                  break;
759
                }
760
 
761
      /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
762
      case 'm' :
763
                    /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
764
                    if (hexToInt(&ptr,&addr))
765
                        if (*(ptr++) == ',')
766
                            if (hexToInt(&ptr,&length))
767
                            {
768
                                ptr = 0;
769
                                mem_err = 0;
770
                                mem2hex((char*) addr, remcomOutBuffer, length, 1);
771
                                if (mem_err) {
772
                                    strcpy (remcomOutBuffer, "E03");
773
                                    debug_error ("memory fault");
774
                                }
775
                            }
776
 
777
                    if (ptr)
778
                    {
779
                      strcpy(remcomOutBuffer,"E01");
780
                    }
781
                  break;
782
 
783
      /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
784
      case 'M' :
785
                    /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
786
                    if (hexToInt(&ptr,&addr))
787
                        if (*(ptr++) == ',')
788
                            if (hexToInt(&ptr,&length))
789
                                if (*(ptr++) == ':')
790
                                {
791
                                    mem_err = 0;
792
                                    hex2mem(ptr, (char*) addr, length, 1);
793
 
794
                                    if (mem_err) {
795
                                        strcpy (remcomOutBuffer, "E03");
796
                                        debug_error ("memory fault");
797
                                    } else {
798
                                        strcpy(remcomOutBuffer,"OK");
799
                                    }
800
 
801
                                    ptr = 0;
802
                                }
803
                    if (ptr)
804
                    {
805
                      strcpy(remcomOutBuffer,"E02");
806
                    }
807
                break;
808
 
809
     /* cAA..AA    Continue at address AA..AA(optional) */
810
     /* sAA..AA   Step one instruction from AA..AA(optional) */
811
     case 's' :
812
         stepping = 1;
813
     case 'c' :
814
          /* try to read optional parameter, pc unchanged if no parm */
815
         if (hexToInt(&ptr,&addr))
816
             registers[ PC ] = addr;
817
 
818
          newPC = registers[ PC];
819
 
820
          /* clear the trace bit */
821
          registers[ PS ] &= 0xfffffeff;
822
 
823
          /* set the trace bit if we're stepping */
824
          if (stepping) registers[ PS ] |= 0x100;
825
 
826
          _returnFromException(); /* this is a jump */
827
          break;
828
 
829
      /* kill the program */
830
      case 'k' :  /* do nothing */
831
#if 0
832
        /* Huh? This doesn't look like "nothing".
833
           m68k-stub.c and sparc-stub.c don't have it.  */
834
                BREAKPOINT();
835
#endif
836
                break;
837
      } /* switch */
838
 
839
    /* reply to the request */
840
    putpacket(remcomOutBuffer);
841
    }
842
}
843
 
844
/* this function is used to set up exception handlers for tracing and
845
   breakpoints */
846
void set_debug_traps()
847
{
848
extern void remcomHandler();
849
int exception;
850
 
851
  stackPtr  = &remcomStack[STACKSIZE/sizeof(int) - 1];
852
 
853
  exceptionHandler (0, _catchException0);
854
  exceptionHandler (1, _catchException1);
855
  exceptionHandler (3, _catchException3);
856
  exceptionHandler (4, _catchException4);
857
  exceptionHandler (5, _catchException5);
858
  exceptionHandler (6, _catchException6);
859
  exceptionHandler (7, _catchException7);
860
  exceptionHandler (8, _catchException8);
861
  exceptionHandler (9, _catchException9);
862
  exceptionHandler (10, _catchException10);
863
  exceptionHandler (11, _catchException11);
864
  exceptionHandler (12, _catchException12);
865
  exceptionHandler (13, _catchException13);
866
  exceptionHandler (14, _catchException14);
867
  exceptionHandler (16, _catchException16);
868
 
869
  initialized = 1;
870
}
871
 
872
/* This function will generate a breakpoint exception.  It is used at the
873
   beginning of a program to sync up with a debugger and can be used
874
   otherwise as a quick means to stop program execution and "break" into
875
   the debugger. */
876
 
877
void breakpoint()
878
{
879
  if (initialized)
880
    BREAKPOINT();
881
}

powered by: WebSVN 2.1.0

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