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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [libgloss/] [xstormy16/] [xstormy16_stub.c] - Blame information for rev 308

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

Line No. Rev Author Line
1 148 jeremybenn
/****************************************************************************
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
 *  Heavily modified for XStormy16 by Mark Salter, Red Hat.
33
 *  Optimisations and 'X' support by Geoff Keating, Red Hat.
34
 *
35
 *  To enable debugger support, two things need to happen.  One, a
36
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
37
 *  or error conditions to be properly intercepted and reported to gdb.
38
 *  Two, a breakpoint needs to be generated to begin communication.  This
39
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
40
 *  simulates a breakpoint by executing a trap #1.
41
 *
42
 *  Because gdb will sometimes write to the stack area to execute function
43
 *  calls, this program cannot rely on using the inferior stack so it uses
44
 *  it's own stack area.
45
 *
46
 *************
47
 *
48
 *    The following gdb commands are supported:
49
 *
50
 * command          function                               Return value
51
 *
52
 *    g             return the value of the CPU registers  hex data or ENN
53
 *    G             set the value of the CPU registers     OK or ENN
54
 *
55
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
56
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
57
 *    XAA..AA,LLLL: Write LLLL binary bytes at address     OK or ENN
58
 *                  AA..AA
59
 *
60
 *    c             Resume at current address              SNN   ( signal NN)
61
 *    cAA..AA       Continue at address AA..AA             SNN
62
 *
63
 *    s             Step one instruction                   SNN
64
 *    sAA..AA       Step one instruction from AA..AA       SNN
65
 *
66
 *    k             kill
67
 *
68
 *    ?             What was the last sigval ?             SNN   (signal NN)
69
 *
70
 * All commands and responses are sent with a packet which includes a
71
 * checksum.  A packet consists of
72
 *
73
 * $<packet info>#<checksum>.
74
 *
75
 * where
76
 * <packet info> :: <characters representing the command or response>
77
 * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
78
 *
79
 * When a packet is received, it is first acknowledged with either '+' or '-'.
80
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
81
 *
82
 * Example:
83
 *
84
 * Host:                  Reply:
85
 * $m0,10#2a               +$00010203040506070809101112131415#42
86
 *
87
 ****************************************************************************/
88
 
89
/* Local functions:
90
 */
91
static void putDebugChar(unsigned ch);
92
static unsigned char getDebugChar(void);
93
static void putPacket(unsigned char *);
94
static void putHex (char c, unsigned long mem_arg, int count);
95
static unsigned char *getpacket(void);
96
static void hex2mem(unsigned char *, unsigned long, int);
97
static int valid_addr_range (unsigned long mem, int count);
98
static int  hexToInt(unsigned char **, long *);
99
static void prepare_to_step(void);
100
static void finish_from_step(void);
101
 
102
/* breakpoint opcode */
103
#define BREAKPOINT_OPCODE 0x0006
104
 
105
/* Error Detection Register */
106
#define ERR_DETECT_REG  (*(volatile unsigned *)0x7f08)
107
#define UNDEF_INSN_ENA   0x01
108
#define UNDEF_INSN_FLAG  0x02
109
#define ODD_ADDR_ENA     0x04
110
#define ODD_ADDR_FLAG    0x08
111
#define BAD_ADDR_ENA     0x10
112
#define BAD_ADDR_FLAG    0x20
113
#define SER0_IRQ_ENA     0x1000
114
#define SER0_IRQ_FLAG    0x2000
115
 
116
/*****************************************************************************
117
 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
118
 * at least NUMREGBYTES*2 are needed for register packets
119
 */
120
#define BUFMAX 80
121
 
122
static const unsigned char hexchars[]="0123456789abcdef";
123
 
124
#define NUMREGS 17
125
 
126
/* Number of bytes of registers (extra 2 bytes is for 4 byte PC).  */
127
#define NUMREGBYTES ((NUMREGS * 2) + 2)
128
enum regnames { R0,  R1,  R2,  R3,  R4,  R5,  R6,   R7,
129
                R8,  R9,  R10, R11, R12, R13, R14,  R15,
130
                PC };
131
 
132
#define FP  R13
133
#define PSW R14
134
#define SP  R15
135
 
136
struct regs {
137
    int  r[16];
138
    long pc;
139
} registers;
140
 
141
static struct regs orig_registers;
142
 
143
static unsigned char remcomBuffer[BUFMAX];
144
 
145
/* Indicate whether inferior is running. Used to decide whether or not to
146
   send T packet when stub is entered. */
147
static char is_running;
148
 
149
static inline unsigned char
150
get_char(unsigned long addr)
151
{
152
  unsigned int msw, lsw;
153
  unsigned char ret;
154
 
155
  msw = addr >> 16;
156
  lsw = addr & 0xffff;
157
 
158
  asm("movf.b %0,(%2)\n"
159
      : "=e"(ret) : "d"(msw), "r"(lsw) : "memory");
160
 
161
  return ret;
162
}
163
 
164
static inline void
165
set_char(unsigned long addr, unsigned int val)
166
{
167
  unsigned int msw, lsw;
168
 
169
  msw = addr >> 16;
170
  lsw = addr & 0xffff;
171
 
172
  asm("movf.b (%1),%2\n"
173
      : /* none */ : "d"(msw), "r"(lsw), "e"(val) : "memory" );
174
}
175
 
176
static inline unsigned int
177
get_word(unsigned long addr)
178
{
179
  unsigned int ret, msw, lsw;
180
 
181
  msw = addr >> 16;
182
  lsw = addr & 0xffff;
183
 
184
  asm("movf.w %0,(%2)\n"
185
      : "=e"(ret) : "d"(msw), "r"(lsw) : "memory" );
186
 
187
  return ret;
188
}
189
 
190
static inline void
191
set_word(unsigned long addr, unsigned int val)
192
{
193
  unsigned int msw, lsw;
194
 
195
  msw = addr >> 16;
196
  lsw = addr & 0xffff;
197
 
198
  asm("movf.w (%1),%2\n"
199
      : /* none */ : "d"(msw), "r"(lsw), "e"(val) : "memory" );
200
}
201
 
202
static void
203
assign_regs (struct regs *dest, const struct regs *src)
204
{
205
  int i;
206
  char *d = (char *)dest, *s = (char *)src;
207
  for (i = 0; i < sizeof (struct regs); i++)
208
    *d++ = *s++;
209
}
210
 
211
/* Write out a register for a 'T' packet.  */
212
 
213
static unsigned char *
214
putreg (unsigned char *buf, int regnum, void *mem_p, int count)
215
{
216
  int i;
217
  unsigned char ch;
218
  char *mem = (char *)mem_p;
219
 
220
  *buf++ = hexchars[regnum >> 4];
221
  *buf++ = hexchars[regnum % 16];
222
  *buf++ = ':';
223
 
224
  for (i=0;i<count;i++)
225
    {
226
      ch = *mem++;
227
      *buf++ = hexchars[ch >> 4];
228
      *buf++ = hexchars[ch % 16];
229
    }
230
  *buf++ = ';';
231
  return(buf);
232
}
233
 
234
/*
235
 * This function does all command procesing for interfacing to gdb.
236
 */
237
void
238
handle_exception(void)
239
{
240
  char sigval;
241
  unsigned char *ptr;
242
  long addr, length;
243
 
244
  /* reply to host that an exception has occurred */
245
  sigval = 5; /* SIGTRAP is default */
246
  if (ERR_DETECT_REG & UNDEF_INSN_FLAG)
247
    {
248
      ERR_DETECT_REG &= ~UNDEF_INSN_FLAG;
249
      registers.pc -= 2;
250
      if (get_word(registers.pc) != BREAKPOINT_OPCODE)
251
        sigval = 4; /* SIGILL */
252
    }
253
  if (ERR_DETECT_REG & BAD_ADDR_FLAG)
254
    {
255
      ERR_DETECT_REG &= ~BAD_ADDR_FLAG;
256
      sigval = 11; /* SIGSEGV */
257
    }
258
  if (ERR_DETECT_REG & SER0_IRQ_FLAG)
259
    {
260
      unsigned char ch;
261
 
262
      ch = getDebugChar();
263
      ERR_DETECT_REG &= ~SER0_IRQ_FLAG;
264
      if (ch != 0x03)
265
        return;
266
      sigval = 2; /* SIGINT */
267
    }
268
 
269
  finish_from_step();
270
 
271
  /* save original context so it can be restored as a result of
272
     a kill packet. */
273
  if (orig_registers.pc == 0L)
274
    assign_regs (&orig_registers, &registers);
275
 
276
  if (is_running)
277
    {
278
      ptr = remcomBuffer;
279
 
280
      *ptr++ = 'T';         /* notify gdb with signo, PC, FP and SP */
281
      *ptr++ = hexchars[sigval >> 4];
282
      *ptr++ = hexchars[sigval & 0xf];
283
 
284
      ptr = putreg (ptr, PC, &registers.pc, 4);
285
      ptr = putreg (ptr, FP, &registers.r[FP], 2);
286
      ptr = putreg (ptr, SP, &registers.r[SP], 2);
287
 
288
      *ptr++ = 0;
289
 
290
      putPacket(remcomBuffer);
291
    }
292
 
293
  while (1) {
294
    char kind;
295
 
296
    ptr = getpacket();
297
    kind = *ptr++;
298
    if (kind == 'M' || kind == 'X')
299
      {
300
        /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
301
        /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
302
        if (hexToInt(&ptr,&addr)
303
            && *(ptr++) == ','
304
            && hexToInt(&ptr,&length)
305
            && *(ptr++) == ':')
306
          {
307
            if (valid_addr_range (addr, length))
308
              {
309
                if (kind == 'M')
310
                  hex2mem(ptr, addr, length);
311
                else
312
                  {
313
                    int i;
314
                    for (i = 0; i < length; i++)
315
                      if (*ptr++ == 0x7d)
316
                        set_char (addr++, *ptr++ ^ 0x20);
317
                      else
318
                        set_char (addr++, ptr[-1]);
319
 
320
                  }
321
                putPacket ("OK");
322
              }
323
            else
324
              putPacket ("E03");
325
          }
326
        else
327
          putPacket ("E02");
328
      }
329
    else if (kind == 'm')
330
      {
331
        /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
332
        /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
333
        if (hexToInt(&ptr,&addr)
334
            && *(ptr++) == ','
335
            && hexToInt (&ptr,&length))
336
          {
337
            if (valid_addr_range (addr, length))
338
              putHex (0, addr, length);
339
            else
340
              putPacket ("E03");
341
          }
342
        else
343
          putPacket ("E02");
344
      }
345
    else if (kind == 'R')
346
      {
347
        if (hexToInt (&ptr, &addr))
348
          registers.pc = addr;
349
        putPacket ("OK");
350
      }
351
    else if (kind == '!')
352
      putPacket ("OK");
353
    else if (kind == '?')
354
      putHex ('S', (unsigned long)(unsigned int)&sigval, 1);
355
    else if (kind == 'g')
356
      putHex (0, (unsigned long)(unsigned int)&registers, NUMREGBYTES);
357
    else if (kind == 'P')
358
      {
359
        /* set the value of a single CPU register - return OK */
360
        unsigned long regno;
361
 
362
        if (hexToInt (&ptr, &regno)
363
            && *ptr++ == '='
364
            && regno < NUMREGS)
365
          {
366
            hex2mem (ptr, (unsigned long)(unsigned int)(registers.r + regno),
367
                     regno == PC ? 4 : 2);
368
            putPacket ("OK");
369
          }
370
        else
371
          putPacket ("E01");
372
      }
373
    else if (kind == 'G')
374
      {
375
        /* set the value of the CPU registers - return OK */
376
        hex2mem(ptr, (unsigned long)(unsigned int)&registers, NUMREGBYTES);
377
        putPacket ("OK");
378
      }
379
    else if (kind == 's' || kind == 'c')
380
      {
381
        /* sAA..AA      Step one instruction from AA..AA(optional) */
382
        /* cAA..AA      Continue from address AA..AA(optional) */
383
        /* try to read optional parameter, pc unchanged if no parm */
384
 
385
        is_running = 1;
386
 
387
        if (hexToInt(&ptr,&addr))
388
          registers.pc = addr;
389
 
390
        if (kind == 's')        /* single-stepping */
391
          prepare_to_step();
392
        return;
393
      }
394
    else if (kind == 'k')
395
      {
396
        /* kill the program */
397
        assign_regs (&registers, &orig_registers);
398
        is_running = 0;
399
        putPacket ("");
400
      }
401
    else
402
      /* Unknown code.  Return an empty reply message. */
403
      putPacket ("");
404
  }
405
}
406
 
407
static int
408
hex (int ch)
409
{
410
  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
411
  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
412
  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
413
  return (-1);
414
}
415
 
416
/* scan for the sequence $<data>#<checksum>     */
417
 
418
static unsigned char *
419
getpacket (void)
420
{
421
  unsigned char *buffer = &remcomBuffer[0];
422
  unsigned checksum;
423
  int count;
424
  char ch;
425
 
426
  while (1)
427
    {
428
      /* wait around for the start character, ignore all other characters */
429
      while (getDebugChar () != '$')
430
        ;
431
 
432
      checksum = 0;
433
      count = 0;
434
      while ((ch = getDebugChar ()) == '$')
435
        ;
436
 
437
      /* now, read until a # or end of buffer is found */
438
      while (ch != '#' && count < BUFMAX - 1)
439
        {
440
          checksum = checksum + ch;
441
          buffer[count] = ch;
442
          count = count + 1;
443
          ch = getDebugChar ();
444
        }
445
      buffer[count] = 0;
446
 
447
      if (ch == '#')
448
        {
449
          unsigned xmitcsum;
450
          ch = getDebugChar ();
451
          xmitcsum = hex (ch) << 4;
452
          ch = getDebugChar ();
453
          xmitcsum += hex (ch);
454
 
455
          /* If one of the above 'hex' calls returns -1, xmitcsum will
456
             have high bits set, and so the test below will fail.  */
457
 
458
          if ((checksum & 0xFF) != xmitcsum)
459
            putDebugChar ('-'); /* failed checksum */
460
          else
461
            {
462
              putDebugChar ('+');       /* successful transfer */
463
              return &buffer[0];
464
            }
465
        }
466
    }
467
}
468
 
469
/* send the packet in buffer.  */
470
 
471
static void
472
putPacket (unsigned char *buffer_p)
473
{
474
  /*  $<packet info>#<checksum>. */
475
  do {
476
    unsigned checksum;
477
    unsigned char *buffer = buffer_p;
478
 
479
    putDebugChar('$');
480
    checksum = 0;
481
 
482
    while (*buffer) {
483
      putDebugChar(*buffer);
484
      checksum += *buffer;
485
      buffer++;
486
    }
487
    putDebugChar('#');
488
    putDebugChar(hexchars[(checksum >> 4) % 16]);
489
    putDebugChar(hexchars[checksum % 16]);
490
  } while (getDebugChar() != '+');
491
}
492
 
493
/* Convert the memory pointed to by mem into hex, and return it as a packet. */
494
 
495
static void
496
putHex (char c, unsigned long mem_arg, int count)
497
{
498
  do {
499
    unsigned long mem = mem_arg;
500
    int i;
501
    unsigned checksum;
502
 
503
    putDebugChar('$');
504
    checksum = 0;
505
 
506
    if (c)
507
      {
508
        checksum = c;
509
        putDebugChar(c);
510
      }
511
 
512
    for (i = 0; i < count; i++)
513
      {
514
        unsigned char c = get_char (mem);
515
        char ch = hexchars[c >> 4];
516
        putDebugChar(ch);
517
        checksum += ch;
518
        ch = hexchars[c % 16];
519
        putDebugChar(ch);
520
        checksum += ch;
521
        mem++;
522
      }
523
    putDebugChar('#');
524
    putDebugChar(hexchars[(checksum >> 4) % 16]);
525
    putDebugChar(hexchars[checksum % 16]);
526
  } while (getDebugChar() != '+');
527
}
528
 
529
/* Function: gdb_write(char *, int)
530
   Make gdb write n bytes to stdout (not assumed to be null-terminated). */
531
 
532
void
533
gdb_write (char *data, int len)
534
{
535
  ERR_DETECT_REG &= ~SER0_IRQ_ENA;
536
  putHex ('O', (unsigned long)(unsigned int)data, len);
537
  ERR_DETECT_REG |= SER0_IRQ_ENA;
538
}
539
 
540
int
541
gdb_read (char *buf, int nbytes)
542
{
543
  int i = 0;
544
 
545
  ERR_DETECT_REG &= ~SER0_IRQ_ENA;
546
  for (i = 0; i < nbytes; i++)
547
    {
548
      *(buf + i) = getDebugChar();
549
      if ((*(buf + i) == '\n') || (*(buf + i) == '\r'))
550
        {
551
          (*(buf + i + 1)) = 0;
552
          break;
553
        }
554
    }
555
  ERR_DETECT_REG |= SER0_IRQ_ENA;
556
  return (i);
557
}
558
 
559
static int
560
valid_addr_range (unsigned long mem, int count)
561
{
562
  unsigned long last = mem + count - 1;
563
 
564
  if (last < 0x800L)
565
    return 1;
566
 
567
  if (mem < 0x7f00L)
568
    return 0;
569
 
570
  if (last > 0x7ffffL)
571
    return 0;
572
 
573
  return 1;
574
}
575
 
576
/* Convert the hex array pointed to by buf into binary to be placed in mem.
577
   Return a pointer to the character AFTER the last byte written. */
578
 
579
static void
580
hex2mem (unsigned char *buf, unsigned long mem, int count)
581
{
582
  int i;
583
  unsigned char ch;
584
 
585
  for (i=0;i<count;i++)
586
    {
587
      ch = hex(*buf++) << 4;
588
      ch = ch + hex(*buf++);
589
      set_char (mem++, ch);
590
    }
591
}
592
 
593
/**********************************************/
594
/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
595
/* RETURN NUMBER OF CHARS PROCESSED           */
596
/**********************************************/
597
static int
598
hexToInt (unsigned char **ptr, long *intValue)
599
{
600
  int numChars = 0;
601
  int hexValue;
602
 
603
  *intValue = 0;
604
  while (**ptr)
605
    {
606
      hexValue = hex(**ptr);
607
      if (hexValue >=0)
608
        {
609
          *intValue = (*intValue <<4) | (unsigned) hexValue;
610
          numChars ++;
611
        }
612
      else
613
        break;
614
      (*ptr)++;
615
    }
616
  return (numChars);
617
}
618
 
619
 
620
/* Function: opcode_size
621
   Determine number of bytes in full opcode by examining first word.
622
*/
623
static int
624
opcode_size(unsigned int opcode)
625
{
626
  if ((opcode & 0xff00) == 0)
627
    return 2;
628
 
629
  if ((opcode & 0xf800) == 0)
630
    return 4;
631
 
632
  if ((opcode & 0xf800) == 0x7800)
633
    return 4;
634
 
635
  if ((opcode & 0xf000) == 0xc000)
636
    return 4;
637
 
638
  if ((opcode & 0xf100) == 0x2000)
639
    return 4;
640
 
641
  if ((opcode & 0xfff0) == 0x30e0)
642
    return 4;
643
 
644
  if ((opcode & 0xf008) == 0x6008)
645
    return 4;
646
 
647
  if ((opcode & 0xf808) == 0x7008)
648
    return 4;
649
 
650
  opcode >>= 8;
651
  if (opcode == 0x0c || opcode == 0x0d || opcode == 0x31)
652
    return 4;
653
 
654
  return 2;
655
}
656
 
657
static struct {
658
  unsigned long  addr;
659
  unsigned long  addr2;
660
  unsigned int   opcode;
661
  unsigned int   opcode2;
662
} stepinfo;
663
 
664
/* Function: prepare_to_step
665
   Called from handle_exception to prepare the user program to single-step.
666
   Places a trap instruction after the target instruction, with special
667
   extra handling for branch instructions.
668
*/
669
 
670
static void
671
prepare_to_step(void)
672
{
673
  unsigned long pc = registers.pc;
674
  unsigned long next_pc, next_pc2;
675
  unsigned int  op, op2, sp;
676
  unsigned char op_msb, op_lsb;
677
  int  r12;
678
  char r8;
679
 
680
  op = get_word(pc);
681
  op_msb = (op >> 8) & 0xff;
682
  op_lsb = op & 0xff;
683
  op2 = get_word(pc + 2);
684
  next_pc = pc + opcode_size(op);
685
  next_pc2 = 0;
686
 
687
  if (op_msb == 0)
688
    {
689
      if (op_lsb == 2)
690
        {
691
          /* IRET */
692
          sp = registers.r[SP];
693
          next_pc = *(unsigned *)(sp - 4);
694
          next_pc = (next_pc << 16) | *(unsigned *)(sp - 6);
695
        }
696
      else if (op_lsb == 3)
697
        {
698
          /* RET */
699
          sp = registers.r[SP];
700
          next_pc = *(unsigned *)(sp - 2);
701
          next_pc = (next_pc << 16) | *(unsigned *)(sp - 4);
702
        }
703
      else
704
        {
705
          op2 = op_lsb & 0xf0;
706
          if (op2 && op2 < 0x40)
707
            {
708
              /* {CALLR,BR,ICALLR} Rs */
709
              next_pc = (pc + 2) + (int)registers.r[op_lsb & 0xf];
710
            }
711
          else if (op2 < 0x80 || op2 == 0xa0 || op2 == 0xb0)
712
            {
713
              /* {JMP,ICALL,CALL} Rb,Rs */
714
              next_pc = registers.r[(op_lsb & 0x10) ? 9 : 8];
715
              next_pc = (next_pc << 16) | (unsigned int)registers.r[op_lsb & 0xf];
716
            }
717
        }
718
    }
719
  else if (op_msb < 4)
720
    {
721
      /* {CALLF,JMPF,ICALLF} a24 */
722
      next_pc = ((unsigned long)op2) << 8;
723
      next_pc |= op_lsb;
724
    }
725
  else if (op_msb < 8)
726
    {
727
      if ((op2 & 0xf000) == 0)
728
        {
729
            /* Bx Rd,#imm4,r12 */
730
            /* Bx Rd,Rs,r12    */
731
            r12 = op2 << 4;
732
            r12 >>= 4;
733
            next_pc2 = (pc + 4) + r12;
734
        }
735
    }
736
  else if (op_msb == 0x0c || op_msb == 0x0d || (op_msb & 0xf1) == 0x20 ||
737
           ((op_msb >= 0x7c && op_msb <= 0x7f) && (op2 & 0x8000) == 0))
738
    {
739
      /* Bxx Rd,Rs,r12    */
740
      /* Bxx Rd,#imm8,r12 */
741
      /* Bx  m8,#imm3,r12 */
742
      /* Bx s8,#imm3,r12  */
743
      r12 = op2 << 4;
744
      r12 >>= 4;
745
      next_pc2 = (pc + 4) + r12;
746
    }
747
  else if ((op_msb & 0xf0) == 0x10)
748
    {
749
      /* {BR,CALLR} r12 */
750
      r12 = (op & 0xffe) << 4;
751
      r12 >>= 4;
752
      next_pc = (pc + 2) + r12;
753
    }
754
  else if ((op_msb & 0xe0) == 0xc0)
755
    {
756
      /* Bxx Rx,#imm16,r8 */
757
      /* TBxx r8 */
758
      r8 = op_lsb;
759
      next_pc2 = next_pc + r8;
760
    }
761
 
762
  stepinfo.addr = next_pc;
763
  stepinfo.opcode = get_word(next_pc);
764
  set_word(next_pc, BREAKPOINT_OPCODE);
765
 
766
  if (next_pc2)
767
    {
768
      stepinfo.addr2 = next_pc2;
769
      stepinfo.opcode2 = get_word(next_pc2);
770
      set_word(next_pc2, BREAKPOINT_OPCODE);
771
    }
772
}
773
 
774
/* Function: finish_from_step
775
   Called from handle_exception to finish up when the user program
776
   returns from a single-step.  Replaces the instructions that had
777
   been overwritten by breakpoint. */
778
 
779
static void
780
finish_from_step (void)
781
{
782
  if (stepinfo.addr)    /* anything to do? */
783
    {
784
      set_word(stepinfo.addr, stepinfo.opcode);
785
      stepinfo.addr = 0;
786
      if (stepinfo.addr2)
787
        {
788
          set_word(stepinfo.addr2, stepinfo.opcode2);
789
          stepinfo.addr2 = 0;
790
        }
791
    }
792
}
793
 
794
 
795
/*
796
 * UART support
797
 */
798
#define UART0_BASE 0x7f38
799
#define UART1_BASE 0x7f48
800
 
801
#define UART_CR(base)  (*(volatile unsigned char *)(base))
802
#define UART_RXD(base) (*(volatile unsigned int *)((base) + 2))
803
#define UART_TXD(base) (*(volatile unsigned int *)((base) + 4))
804
 
805
#define UART_CR_RUN       0x80
806
#define UART_CR_ERR       0x40
807
#define UART_CR_BAUD_115k 0x20
808
#define UART_CR_PARITY    0x10
809
#define UART_CR_TXEMPTY   0x08
810
#define UART_CR_TXIEN     0x04
811
#define UART_CR_RXRDY     0x02
812
#define UART_CR_RXIEN     0x01
813
 
814
#define DBG_UART UART0_BASE
815
 
816
static void
817
putDebugChar(unsigned ch)
818
{
819
  while ((UART_CR(DBG_UART) & UART_CR_TXEMPTY) == 0) ;
820
 
821
  UART_TXD(DBG_UART) = ch;
822
}
823
 
824
static unsigned char
825
getDebugChar(void)
826
{
827
  while ((UART_CR(DBG_UART) & UART_CR_RXRDY) == 0) ;
828
 
829
  return UART_RXD(DBG_UART);
830
}
831
 
832
void
833
uart_init(void)
834
{
835
  UART_CR(DBG_UART) |= (UART_CR_RUN | UART_CR_RXIEN);
836
}
837
 

powered by: WebSVN 2.1.0

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