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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [i386/] [shared/] [comm/] [i386-stub.c] - Blame information for rev 30

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

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

powered by: WebSVN 2.1.0

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