1 /****************************************************************************
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
get_char(unsigned long addr)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
set_char(unsigned long addr,unsigned int val)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
get_word(unsigned long addr)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
set_word(unsigned long addr,unsigned int val)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
assign_regs(struct regs * dest,const struct regs * src)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 *
putreg(unsigned char * buf,int regnum,void * mem_p,int count)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
handle_exception(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, ®isters);
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, ®isters.pc, 4);
285 ptr = putreg (ptr, FP, ®isters.r[FP], 2);
286 ptr = putreg (ptr, SP, ®isters.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)®isters, 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, ®no)
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)®isters, 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 (®isters, &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
hex(int ch)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 *
getpacket(void)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
putPacket(unsigned char * buffer_p)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
putHex(char c,unsigned long mem_arg,int count)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
gdb_write(char * data,int len)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
gdb_read(char * buf,int nbytes)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
valid_addr_range(unsigned long mem,int count)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
hex2mem(unsigned char * buf,unsigned long mem,int count)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
hexToInt(unsigned char ** ptr,long * intValue)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
opcode_size(unsigned int opcode)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
prepare_to_step(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
finish_from_step(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
putDebugChar(unsigned ch)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
getDebugChar(void)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
uart_init(void)833 uart_init(void)
834 {
835 UART_CR(DBG_UART) |= (UART_CR_RUN | UART_CR_RXIEN);
836 }
837
838