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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [i386-stub.c] - Blame information for rev 1768

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

Line No. Rev Author Line
1 578 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
433
_returnFromException ()
434
{
435
  return_to_prog ();
436
}
437
 
438
int
439
hex (ch)
440
     char ch;
441
{
442
  if ((ch >= 'a') && (ch <= 'f'))
443
    return (ch - 'a' + 10);
444
  if ((ch >= '0') && (ch <= '9'))
445
    return (ch - '0');
446
  if ((ch >= 'A') && (ch <= 'F'))
447
    return (ch - 'A' + 10);
448
  return (-1);
449
}
450
 
451
static char remcomInBuffer[BUFMAX];
452
static char remcomOutBuffer[BUFMAX];
453
 
454
/* scan for the sequence $<data>#<checksum>     */
455
 
456
unsigned char *
457
getpacket (void)
458
{
459
  unsigned char *buffer = &remcomInBuffer[0];
460
  unsigned char checksum;
461
  unsigned char xmitcsum;
462
  int count;
463
  char ch;
464
 
465
  while (1)
466
    {
467
      /* wait around for the start character, ignore all other characters */
468
      while ((ch = getDebugChar ()) != '$')
469
        ;
470
 
471
    retry:
472
      checksum = 0;
473
      xmitcsum = -1;
474
      count = 0;
475
 
476
      /* now, read until a # or end of buffer is found */
477
      while (count < BUFMAX)
478
        {
479
          ch = getDebugChar ();
480
          if (ch == '$')
481
            goto retry;
482
          if (ch == '#')
483
            break;
484
          checksum = checksum + ch;
485
          buffer[count] = ch;
486
          count = count + 1;
487
        }
488
      buffer[count] = 0;
489
 
490
      if (ch == '#')
491
        {
492
          ch = getDebugChar ();
493
          xmitcsum = hex (ch) << 4;
494
          ch = getDebugChar ();
495
          xmitcsum += hex (ch);
496
 
497
          if (checksum != xmitcsum)
498
            {
499
              if (remote_debug)
500
                {
501
                  fprintf (stderr,
502
                           "bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
503
                           checksum, xmitcsum, buffer);
504
                }
505
              putDebugChar ('-');       /* failed checksum */
506
            }
507
          else
508
            {
509
              putDebugChar ('+');       /* successful transfer */
510
 
511
              /* if a sequence char is present, reply the sequence ID */
512
              if (buffer[2] == ':')
513
                {
514
                  putDebugChar (buffer[0]);
515
                  putDebugChar (buffer[1]);
516
 
517
                  return &buffer[3];
518
                }
519
 
520
              return &buffer[0];
521
            }
522
        }
523
    }
524
}
525
 
526
/* send the packet in buffer.  */
527
 
528
void
529
putpacket (unsigned char *buffer)
530
{
531
  unsigned char checksum;
532
  int count;
533
  char ch;
534
 
535
  /*  $<packet info>#<checksum>. */
536
  do
537
    {
538
      putDebugChar ('$');
539
      checksum = 0;
540
      count = 0;
541
 
542
      while (ch = buffer[count])
543
        {
544
          putDebugChar (ch);
545
          checksum += ch;
546
          count += 1;
547
        }
548
 
549
      putDebugChar ('#');
550
      putDebugChar (hexchars[checksum >> 4]);
551
      putDebugChar (hexchars[checksum % 16]);
552
 
553
    }
554
  while (getDebugChar () != '+');
555
}
556
 
557
void
558
debug_error (format, parm)
559
     char *format;
560
     char *parm;
561
{
562
  if (remote_debug)
563
    fprintf (stderr, format, parm);
564
}
565
 
566
/* Address of a routine to RTE to if we get a memory fault.  */
567
static void (*volatile mem_fault_routine) () = NULL;
568
 
569
/* Indicate to caller of mem2hex or hex2mem that there has been an
570
   error.  */
571
static volatile int mem_err = 0;
572
 
573
void
574
set_mem_err (void)
575
{
576
  mem_err = 1;
577
}
578
 
579
/* These are separate functions so that they are so short and sweet
580
   that the compiler won't save any registers (if there is a fault
581
   to mem_fault, they won't get restored, so there better not be any
582
   saved).  */
583
int
584
get_char (char *addr)
585
{
586
  return *addr;
587
}
588
 
589
void
590
set_char (char *addr, int val)
591
{
592
  *addr = val;
593
}
594
 
595
/* convert the memory pointed to by mem into hex, placing result in buf */
596
/* return a pointer to the last char put in buf (null) */
597
/* If MAY_FAULT is non-zero, then we should set mem_err in response to
598
   a fault; if zero treat a fault like any other fault in the stub.  */
599
char *
600
mem2hex (mem, buf, count, may_fault)
601
     char *mem;
602
     char *buf;
603
     int count;
604
     int may_fault;
605
{
606
  int i;
607
  unsigned char ch;
608
 
609
  if (may_fault)
610
    mem_fault_routine = set_mem_err;
611
  for (i = 0; i < count; i++)
612
    {
613
      ch = get_char (mem++);
614
      if (may_fault && mem_err)
615
        return (buf);
616
      *buf++ = hexchars[ch >> 4];
617
      *buf++ = hexchars[ch % 16];
618
    }
619
  *buf = 0;
620
  if (may_fault)
621
    mem_fault_routine = NULL;
622
  return (buf);
623
}
624
 
625
/* convert the hex array pointed to by buf into binary to be placed in mem */
626
/* return a pointer to the character AFTER the last byte written */
627
char *
628
hex2mem (buf, mem, count, may_fault)
629
     char *buf;
630
     char *mem;
631
     int count;
632
     int may_fault;
633
{
634
  int i;
635
  unsigned char ch;
636
 
637
  if (may_fault)
638
    mem_fault_routine = set_mem_err;
639
  for (i = 0; i < count; i++)
640
    {
641
      ch = hex (*buf++) << 4;
642
      ch = ch + hex (*buf++);
643
      set_char (mem++, ch);
644
      if (may_fault && mem_err)
645
        return (mem);
646
    }
647
  if (may_fault)
648
    mem_fault_routine = NULL;
649
  return (mem);
650
}
651
 
652
/* this function takes the 386 exception vector and attempts to
653
   translate this number into a unix compatible signal value */
654
int
655
computeSignal (int exceptionVector)
656
{
657
  int sigval;
658
  switch (exceptionVector)
659
    {
660
    case 0:
661
      sigval = 8;
662
      break;                    /* divide by zero */
663
    case 1:
664
      sigval = 5;
665
      break;                    /* debug exception */
666
    case 3:
667
      sigval = 5;
668
      break;                    /* breakpoint */
669
    case 4:
670
      sigval = 16;
671
      break;                    /* into instruction (overflow) */
672
    case 5:
673
      sigval = 16;
674
      break;                    /* bound instruction */
675
    case 6:
676
      sigval = 4;
677
      break;                    /* Invalid opcode */
678
    case 7:
679
      sigval = 8;
680
      break;                    /* coprocessor not available */
681
    case 8:
682
      sigval = 7;
683
      break;                    /* double fault */
684
    case 9:
685
      sigval = 11;
686
      break;                    /* coprocessor segment overrun */
687
    case 10:
688
      sigval = 11;
689
      break;                    /* Invalid TSS */
690
    case 11:
691
      sigval = 11;
692
      break;                    /* Segment not present */
693
    case 12:
694
      sigval = 11;
695
      break;                    /* stack exception */
696
    case 13:
697
      sigval = 11;
698
      break;                    /* general protection */
699
    case 14:
700
      sigval = 11;
701
      break;                    /* page fault */
702
    case 16:
703
      sigval = 7;
704
      break;                    /* coprocessor error */
705
    default:
706
      sigval = 7;               /* "software generated" */
707
    }
708
  return (sigval);
709
}
710
 
711
/**********************************************/
712
/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
713
/* RETURN NUMBER OF CHARS PROCESSED           */
714
/**********************************************/
715
int
716
hexToInt (char **ptr, int *intValue)
717
{
718
  int numChars = 0;
719
  int hexValue;
720
 
721
  *intValue = 0;
722
 
723
  while (**ptr)
724
    {
725
      hexValue = hex (**ptr);
726
      if (hexValue >= 0)
727
        {
728
          *intValue = (*intValue << 4) | hexValue;
729
          numChars++;
730
        }
731
      else
732
        break;
733
 
734
      (*ptr)++;
735
    }
736
 
737
  return (numChars);
738
}
739
 
740
/*
741
 * This function does all command procesing for interfacing to gdb.
742
 */
743
void
744
handle_exception (int exceptionVector)
745
{
746
  int sigval, stepping;
747
  int addr, length;
748
  char *ptr;
749
  int newPC;
750
 
751
  gdb_i386vector = exceptionVector;
752
 
753
  if (remote_debug)
754
    {
755
      printf ("vector=%d, sr=0x%x, pc=0x%x\n",
756
              exceptionVector, registers[PS], registers[PC]);
757
    }
758
 
759
  /* reply to host that an exception has occurred */
760
  sigval = computeSignal (exceptionVector);
761
 
762
  ptr = remcomOutBuffer;
763
 
764
  *ptr++ = 'T';                 /* notify gdb with signo, PC, FP and SP */
765
  *ptr++ = hexchars[sigval >> 4];
766
  *ptr++ = hexchars[sigval & 0xf];
767
 
768
  *ptr++ = hexchars[ESP];
769
  *ptr++ = ':';
770
  ptr = mem2hex((char *)&registers[ESP], ptr, 4, 0);     /* SP */
771
  *ptr++ = ';';
772
 
773
  *ptr++ = hexchars[EBP];
774
  *ptr++ = ':';
775
  ptr = mem2hex((char *)&registers[EBP], ptr, 4, 0);     /* FP */
776
  *ptr++ = ';';
777
 
778
  *ptr++ = hexchars[PC];
779
  *ptr++ = ':';
780
  ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);      /* PC */
781
  *ptr++ = ';';
782
 
783
  *ptr = '\0'
784
 
785
  putpacket (remcomOutBuffer);
786
 
787
  stepping = 0;
788
 
789
  while (1 == 1)
790
    {
791
      remcomOutBuffer[0] = 0;
792
      ptr = getpacket ();
793
 
794
      switch (*ptr++)
795
        {
796
        case '?':
797
          remcomOutBuffer[0] = 'S';
798
          remcomOutBuffer[1] = hexchars[sigval >> 4];
799
          remcomOutBuffer[2] = hexchars[sigval % 16];
800
          remcomOutBuffer[3] = 0;
801
          break;
802
        case 'd':
803
          remote_debug = !(remote_debug);       /* toggle debug flag */
804
          break;
805
        case 'g':               /* return the value of the CPU registers */
806
          mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);
807
          break;
808
        case 'G':               /* set the value of the CPU registers - return OK */
809
          hex2mem (ptr, (char *) registers, NUMREGBYTES, 0);
810
          strcpy (remcomOutBuffer, "OK");
811
          break;
812
        case 'P':               /* set the value of a single CPU register - return OK */
813
          {
814
            int regno;
815
 
816
            if (hexToInt (&ptr, &regno) && *ptr++ == '=')
817
              if (regno >= 0 && regno < NUMREGS)
818
                {
819
                  hex2mem (ptr, (char *) &registers[regno], 4, 0);
820
                  strcpy (remcomOutBuffer, "OK");
821
                  break;
822
                }
823
 
824
            strcpy (remcomOutBuffer, "E01");
825
            break;
826
          }
827
 
828
          /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
829
        case 'm':
830
          /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
831
          if (hexToInt (&ptr, &addr))
832
            if (*(ptr++) == ',')
833
              if (hexToInt (&ptr, &length))
834
                {
835
                  ptr = 0;
836
                  mem_err = 0;
837
                  mem2hex ((char *) addr, remcomOutBuffer, length, 1);
838
                  if (mem_err)
839
                    {
840
                      strcpy (remcomOutBuffer, "E03");
841
                      debug_error ("memory fault");
842
                    }
843
                }
844
 
845
          if (ptr)
846
            {
847
              strcpy (remcomOutBuffer, "E01");
848
            }
849
          break;
850
 
851
          /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
852
        case 'M':
853
          /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
854
          if (hexToInt (&ptr, &addr))
855
            if (*(ptr++) == ',')
856
              if (hexToInt (&ptr, &length))
857
                if (*(ptr++) == ':')
858
                  {
859
                    mem_err = 0;
860
                    hex2mem (ptr, (char *) addr, length, 1);
861
 
862
                    if (mem_err)
863
                      {
864
                        strcpy (remcomOutBuffer, "E03");
865
                        debug_error ("memory fault");
866
                      }
867
                    else
868
                      {
869
                        strcpy (remcomOutBuffer, "OK");
870
                      }
871
 
872
                    ptr = 0;
873
                  }
874
          if (ptr)
875
            {
876
              strcpy (remcomOutBuffer, "E02");
877
            }
878
          break;
879
 
880
          /* cAA..AA    Continue at address AA..AA(optional) */
881
          /* sAA..AA   Step one instruction from AA..AA(optional) */
882
        case 's':
883
          stepping = 1;
884
        case 'c':
885
          /* try to read optional parameter, pc unchanged if no parm */
886
          if (hexToInt (&ptr, &addr))
887
            registers[PC] = addr;
888
 
889
          newPC = registers[PC];
890
 
891
          /* clear the trace bit */
892
          registers[PS] &= 0xfffffeff;
893
 
894
          /* set the trace bit if we're stepping */
895
          if (stepping)
896
            registers[PS] |= 0x100;
897
 
898
          _returnFromException ();      /* this is a jump */
899
          break;
900
 
901
          /* kill the program */
902
        case 'k':               /* do nothing */
903
#if 0
904
          /* Huh? This doesn't look like "nothing".
905
             m68k-stub.c and sparc-stub.c don't have it.  */
906
          BREAKPOINT ();
907
#endif
908
          break;
909
        }                       /* switch */
910
 
911
      /* reply to the request */
912
      putpacket (remcomOutBuffer);
913
    }
914
}
915
 
916
/* this function is used to set up exception handlers for tracing and
917
   breakpoints */
918
void
919
set_debug_traps (void)
920
{
921
  stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
922
 
923
  exceptionHandler (0, _catchException0);
924
  exceptionHandler (1, _catchException1);
925
  exceptionHandler (3, _catchException3);
926
  exceptionHandler (4, _catchException4);
927
  exceptionHandler (5, _catchException5);
928
  exceptionHandler (6, _catchException6);
929
  exceptionHandler (7, _catchException7);
930
  exceptionHandler (8, _catchException8);
931
  exceptionHandler (9, _catchException9);
932
  exceptionHandler (10, _catchException10);
933
  exceptionHandler (11, _catchException11);
934
  exceptionHandler (12, _catchException12);
935
  exceptionHandler (13, _catchException13);
936
  exceptionHandler (14, _catchException14);
937
  exceptionHandler (16, _catchException16);
938
 
939
  initialized = 1;
940
}
941
 
942
/* This function will generate a breakpoint exception.  It is used at the
943
   beginning of a program to sync up with a debugger and can be used
944
   otherwise as a quick means to stop program execution and "break" into
945
   the debugger. */
946
 
947
void
948
breakpoint (void)
949
{
950
  if (initialized)
951
    BREAKPOINT ();
952
}

powered by: WebSVN 2.1.0

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