xref: /dragonfly/contrib/gdb-7/gdb/stubs/sh-stub.c (revision d4ef6694)
1 /* sh-stub.c -- debugging stub for the Renesas-SH.
2 
3  NOTE!! This code has to be compiled with optimization, otherwise the
4  function inlining which generates the exception handlers won't work.
5 
6 */
7 
8 /*   This is originally based on an m68k software stub written by Glenn
9      Engel at HP, but has changed quite a bit.
10 
11      Modifications for the SH by Ben Lee and Steve Chamberlain
12 
13 */
14 
15 /****************************************************************************
16 
17 		THIS SOFTWARE IS NOT COPYRIGHTED
18 
19    HP offers the following for use in the public domain.  HP makes no
20    warranty with regard to the software or it's performance and the
21    user accepts the software "AS IS" with all faults.
22 
23    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
24    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
25    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26 
27 ****************************************************************************/
28 
29 
30 /* Remote communication protocol.
31 
32    A debug packet whose contents are <data>
33    is encapsulated for transmission in the form:
34 
35 	$ <data> # CSUM1 CSUM2
36 
37 	<data> must be ASCII alphanumeric and cannot include characters
38 	'$' or '#'.  If <data> starts with two characters followed by
39 	':', then the existing stubs interpret this as a sequence number.
40 
41 	CSUM1 and CSUM2 are ascii hex representation of an 8-bit
42 	checksum of <data>, the most significant nibble is sent first.
43 	the hex digits 0-9,a-f are used.
44 
45    Receiver responds with:
46 
47 	+	- if CSUM is correct and ready for next packet
48 	-	- if CSUM is incorrect
49 
50    <data> is as follows:
51    All values are encoded in ascii hex digits.
52 
53 	Request		Packet
54 
55 	read registers  g
56 	reply		XX....X		Each byte of register data
57 					is described by two hex digits.
58 					Registers are in the internal order
59 					for GDB, and the bytes in a register
60 					are in the same order the machine uses.
61 			or ENN		for an error.
62 
63 	write regs	GXX..XX		Each byte of register data
64 					is described by two hex digits.
65 	reply		OK		for success
66 			ENN		for an error
67 
68         write reg	Pn...=r...	Write register n... with value r...,
69 					which contains two hex digits for each
70 					byte in the register (target byte
71 					order).
72 	reply		OK		for success
73 			ENN		for an error
74 	(not supported by all stubs).
75 
76 	read mem	mAA..AA,LLLL	AA..AA is address, LLLL is length.
77 	reply		XX..XX		XX..XX is mem contents
78 					Can be fewer bytes than requested
79 					if able to read only part of the data.
80 			or ENN		NN is errno
81 
82 	write mem	MAA..AA,LLLL:XX..XX
83 					AA..AA is address,
84 					LLLL is number of bytes,
85 					XX..XX is data
86 	reply		OK		for success
87 			ENN		for an error (this includes the case
88 					where only part of the data was
89 					written).
90 
91 	cont		cAA..AA		AA..AA is address to resume
92 					If AA..AA is omitted,
93 					resume at same address.
94 
95 	step		sAA..AA		AA..AA is address to resume
96 					If AA..AA is omitted,
97 					resume at same address.
98 
99 	last signal     ?               Reply the current reason for stopping.
100                                         This is the same reply as is generated
101 					for step or cont : SAA where AA is the
102 					signal number.
103 
104 	There is no immediate reply to step or cont.
105 	The reply comes when the machine stops.
106 	It is		SAA		AA is the "signal number"
107 
108 	or...		TAAn...:r...;n:r...;n...:r...;
109 					AA = signal number
110 					n... = register number
111 					r... = register contents
112 	or...		WAA		The process exited, and AA is
113 					the exit status.  This is only
114 					applicable for certains sorts of
115 					targets.
116 	kill request	k
117 
118 	toggle debug	d		toggle debug flag (see 386 & 68k stubs)
119 	reset		r		reset -- see sparc stub.
120 	reserved	<other>		On other requests, the stub should
121 					ignore the request and send an empty
122 					response ($#<checksum>).  This way
123 					we can extend the protocol and GDB
124 					can tell whether the stub it is
125 					talking to uses the old or the new.
126 	search		tAA:PP,MM	Search backwards starting at address
127 					AA for a match with pattern PP and
128 					mask MM.  PP and MM are 4 bytes.
129 					Not supported by all stubs.
130 
131 	general query	qXXXX		Request info about XXXX.
132 	general set	QXXXX=yyyy	Set value of XXXX to yyyy.
133 	query sect offs	qOffsets	Get section offsets.  Reply is
134 					Text=xxx;Data=yyy;Bss=zzz
135 	console output	Otext		Send text to stdout.  Only comes from
136 					remote target.
137 
138 	Responses can be run-length encoded to save space.  A '*' means that
139 	the next character is an ASCII encoding giving a repeat count which
140 	stands for that many repititions of the character preceding the '*'.
141 	The encoding is n+29, yielding a printable character where n >=3
142 	(which is where rle starts to win).  Don't use an n > 126.
143 
144 	So
145 	"0* " means the same as "0000".  */
146 
147 #include <string.h>
148 #include <setjmp.h>
149 
150 /* Renesas SH architecture instruction encoding masks */
151 
152 #define COND_BR_MASK   0xff00
153 #define UCOND_DBR_MASK 0xe000
154 #define UCOND_RBR_MASK 0xf0df
155 #define TRAPA_MASK     0xff00
156 
157 #define COND_DISP      0x00ff
158 #define UCOND_DISP     0x0fff
159 #define UCOND_REG      0x0f00
160 
161 /* Renesas SH instruction opcodes */
162 
163 #define BF_INSTR       0x8b00
164 #define BT_INSTR       0x8900
165 #define BRA_INSTR      0xa000
166 #define BSR_INSTR      0xb000
167 #define JMP_INSTR      0x402b
168 #define JSR_INSTR      0x400b
169 #define RTS_INSTR      0x000b
170 #define RTE_INSTR      0x002b
171 #define TRAPA_INSTR    0xc300
172 #define SSTEP_INSTR    0xc3ff
173 
174 /* Renesas SH processor register masks */
175 
176 #define T_BIT_MASK     0x0001
177 
178 /*
179  * BUFMAX defines the maximum number of characters in inbound/outbound
180  * buffers. At least NUMREGBYTES*2 are needed for register packets.
181  */
182 #define BUFMAX 1024
183 
184 /*
185  * Number of bytes for registers
186  */
187 #define NUMREGBYTES 112		/* 92 */
188 
189 /*
190  * typedef
191  */
192 typedef void (*Function) ();
193 
194 /*
195  * Forward declarations
196  */
197 
198 static int hex (char);
199 static char *mem2hex (char *, char *, int);
200 static char *hex2mem (char *, char *, int);
201 static int hexToInt (char **, int *);
202 static unsigned char *getpacket (void);
203 static void putpacket (char *);
204 static void handle_buserror (void);
205 static int computeSignal (int exceptionVector);
206 static void handle_exception (int exceptionVector);
207 void init_serial();
208 
209 void putDebugChar (char);
210 char getDebugChar (void);
211 
212 /* These are in the file but in asm statements so the compiler can't see them */
213 void catch_exception_4 (void);
214 void catch_exception_6 (void);
215 void catch_exception_9 (void);
216 void catch_exception_10 (void);
217 void catch_exception_11 (void);
218 void catch_exception_32 (void);
219 void catch_exception_33 (void);
220 void catch_exception_255 (void);
221 
222 
223 
224 #define catch_exception_random catch_exception_255 /* Treat all odd ones like 255 */
225 
226 void breakpoint (void);
227 
228 
229 #define init_stack_size 8*1024  /* if you change this you should also modify BINIT */
230 #define stub_stack_size 8*1024
231 
232 int init_stack[init_stack_size] __attribute__ ((section ("stack"))) = {0};
233 int stub_stack[stub_stack_size] __attribute__ ((section ("stack"))) = {0};
234 
235 
236 void INIT ();
237 void BINIT ();
238 
239 #define CPU_BUS_ERROR_VEC  9
240 #define DMA_BUS_ERROR_VEC 10
241 #define NMI_VEC           11
242 #define INVALID_INSN_VEC   4
243 #define INVALID_SLOT_VEC   6
244 #define TRAP_VEC          32
245 #define IO_VEC            33
246 #define USER_VEC         255
247 
248 
249 
250 char in_nmi;   /* Set when handling an NMI, so we don't reenter */
251 int dofault;  /* Non zero, bus errors will raise exception */
252 
253 int *stub_sp;
254 
255 /* debug > 0 prints ill-formed commands in valid packets & checksum errors */
256 int remote_debug;
257 
258 /* jump buffer used for setjmp/longjmp */
259 jmp_buf remcomEnv;
260 
261 enum regnames
262   {
263     R0, R1, R2, R3, R4, R5, R6, R7,
264     R8, R9, R10, R11, R12, R13, R14,
265     R15, PC, PR, GBR, VBR, MACH, MACL, SR,
266     TICKS, STALLS, CYCLES, INSTS, PLR
267   };
268 
269 typedef struct
270   {
271     short *memAddr;
272     short oldInstr;
273   }
274 stepData;
275 
276 int registers[NUMREGBYTES / 4];
277 stepData instrBuffer;
278 char stepped;
279 static const char hexchars[] = "0123456789abcdef";
280 static char remcomInBuffer[BUFMAX];
281 static char remcomOutBuffer[BUFMAX];
282 
283 char highhex(int  x)
284 {
285   return hexchars[(x >> 4) & 0xf];
286 }
287 
288 char lowhex(int  x)
289 {
290   return hexchars[x & 0xf];
291 }
292 
293 /*
294  * Assembly macros
295  */
296 
297 #define BREAKPOINT()   asm("trapa	#0x20"::);
298 
299 
300 /*
301  * Routines to handle hex data
302  */
303 
304 static int
305 hex (char ch)
306 {
307   if ((ch >= 'a') && (ch <= 'f'))
308     return (ch - 'a' + 10);
309   if ((ch >= '0') && (ch <= '9'))
310     return (ch - '0');
311   if ((ch >= 'A') && (ch <= 'F'))
312     return (ch - 'A' + 10);
313   return (-1);
314 }
315 
316 /* convert the memory, pointed to by mem into hex, placing result in buf */
317 /* return a pointer to the last char put in buf (null) */
318 static char *
319 mem2hex (char *mem, char *buf, int count)
320 {
321   int i;
322   int ch;
323   for (i = 0; i < count; i++)
324     {
325       ch = *mem++;
326       *buf++ = highhex (ch);
327       *buf++ = lowhex (ch);
328     }
329   *buf = 0;
330   return (buf);
331 }
332 
333 /* convert the hex array pointed to by buf into binary, to be placed in mem */
334 /* return a pointer to the character after the last byte written */
335 
336 static char *
337 hex2mem (char *buf, char *mem, int count)
338 {
339   int i;
340   unsigned char ch;
341   for (i = 0; i < count; i++)
342     {
343       ch = hex (*buf++) << 4;
344       ch = ch + hex (*buf++);
345       *mem++ = ch;
346     }
347   return (mem);
348 }
349 
350 /**********************************************/
351 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
352 /* RETURN NUMBER OF CHARS PROCESSED           */
353 /**********************************************/
354 static int
355 hexToInt (char **ptr, int *intValue)
356 {
357   int numChars = 0;
358   int hexValue;
359 
360   *intValue = 0;
361 
362   while (**ptr)
363     {
364       hexValue = hex (**ptr);
365       if (hexValue >= 0)
366 	{
367 	  *intValue = (*intValue << 4) | hexValue;
368 	  numChars++;
369 	}
370       else
371 	break;
372 
373       (*ptr)++;
374     }
375 
376   return (numChars);
377 }
378 
379 /*
380  * Routines to get and put packets
381  */
382 
383 /* scan for the sequence $<data>#<checksum>     */
384 
385 char *
386 getpacket (void)
387 {
388   unsigned char *buffer = &remcomInBuffer[0];
389   unsigned char checksum;
390   unsigned char xmitcsum;
391   int count;
392   char ch;
393 
394   while (1)
395     {
396       /* wait around for the start character, ignore all other characters */
397       while ((ch = getDebugChar ()) != '$')
398 	;
399 
400 retry:
401       checksum = 0;
402       xmitcsum = -1;
403       count = 0;
404 
405       /* now, read until a # or end of buffer is found */
406       while (count < BUFMAX - 1)
407 	{
408 	  ch = getDebugChar ();
409           if (ch == '$')
410             goto retry;
411 	  if (ch == '#')
412 	    break;
413 	  checksum = checksum + ch;
414 	  buffer[count] = ch;
415 	  count = count + 1;
416 	}
417       buffer[count] = 0;
418 
419       if (ch == '#')
420 	{
421  	  ch = getDebugChar ();
422  	  xmitcsum = hex (ch) << 4;
423  	  ch = getDebugChar ();
424  	  xmitcsum += hex (ch);
425 
426 	  if (checksum != xmitcsum)
427 	    {
428 	      putDebugChar ('-');	/* failed checksum */
429 	    }
430 	  else
431 	    {
432 	      putDebugChar ('+');	/* successful transfer */
433 
434 	      /* if a sequence char is present, reply the sequence ID */
435 	      if (buffer[2] == ':')
436 		{
437 		  putDebugChar (buffer[0]);
438 		  putDebugChar (buffer[1]);
439 
440  		  return &buffer[3];
441 		}
442 
443 	      return &buffer[0];
444 	    }
445 	}
446     }
447 }
448 
449 
450 /* send the packet in buffer. */
451 
452 static void
453 putpacket (char *buffer)
454 {
455   int checksum;
456   int count;
457 
458   /*  $<packet info>#<checksum>. */
459   do
460     {
461       char *src = buffer;
462       putDebugChar ('$');
463       checksum = 0;
464 
465       while (*src)
466 	{
467 	  int runlen;
468 
469 	  /* Do run length encoding */
470 	  for (runlen = 0; runlen < 100; runlen ++)
471 	    {
472 	      if (src[0] != src[runlen])
473 		{
474 		  if (runlen > 3)
475 		    {
476 		      int encode;
477 		      /* Got a useful amount */
478 		      putDebugChar (*src);
479 		      checksum += *src;
480 		      putDebugChar ('*');
481 		      checksum += '*';
482 		      checksum += (encode = runlen + ' ' - 4);
483 		      putDebugChar (encode);
484 		      src += runlen;
485 		    }
486 		  else
487 		    {
488 		      putDebugChar (*src);
489 		      checksum += *src;
490 		      src++;
491 		    }
492 		  break;
493 		}
494 	    }
495 	}
496 
497 
498       putDebugChar ('#');
499       putDebugChar (highhex(checksum));
500       putDebugChar (lowhex(checksum));
501     }
502   while  (getDebugChar() != '+');
503 }
504 
505 
506 /* a bus error has occurred, perform a longjmp
507    to return execution and allow handling of the error */
508 
509 void
510 handle_buserror (void)
511 {
512   longjmp (remcomEnv, 1);
513 }
514 
515 /*
516  * this function takes the SH-1 exception number and attempts to
517  * translate this number into a unix compatible signal value
518  */
519 static int
520 computeSignal (int exceptionVector)
521 {
522   int sigval;
523   switch (exceptionVector)
524     {
525     case INVALID_INSN_VEC:
526       sigval = 4;
527       break;
528     case INVALID_SLOT_VEC:
529       sigval = 4;
530       break;
531     case CPU_BUS_ERROR_VEC:
532       sigval = 10;
533       break;
534     case DMA_BUS_ERROR_VEC:
535       sigval = 10;
536       break;
537     case NMI_VEC:
538       sigval = 2;
539       break;
540 
541     case TRAP_VEC:
542     case USER_VEC:
543       sigval = 5;
544       break;
545 
546     default:
547       sigval = 7;		/* "software generated"*/
548       break;
549     }
550   return (sigval);
551 }
552 
553 void
554 doSStep (void)
555 {
556   short *instrMem;
557   int displacement;
558   int reg;
559   unsigned short opcode;
560 
561   instrMem = (short *) registers[PC];
562 
563   opcode = *instrMem;
564   stepped = 1;
565 
566   if ((opcode & COND_BR_MASK) == BT_INSTR)
567     {
568       if (registers[SR] & T_BIT_MASK)
569 	{
570 	  displacement = (opcode & COND_DISP) << 1;
571 	  if (displacement & 0x80)
572 	    displacement |= 0xffffff00;
573 	  /*
574 		   * Remember PC points to second instr.
575 		   * after PC of branch ... so add 4
576 		   */
577 	  instrMem = (short *) (registers[PC] + displacement + 4);
578 	}
579       else
580 	instrMem += 1;
581     }
582   else if ((opcode & COND_BR_MASK) == BF_INSTR)
583     {
584       if (registers[SR] & T_BIT_MASK)
585 	instrMem += 1;
586       else
587 	{
588 	  displacement = (opcode & COND_DISP) << 1;
589 	  if (displacement & 0x80)
590 	    displacement |= 0xffffff00;
591 	  /*
592 		   * Remember PC points to second instr.
593 		   * after PC of branch ... so add 4
594 		   */
595 	  instrMem = (short *) (registers[PC] + displacement + 4);
596 	}
597     }
598   else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR)
599     {
600       displacement = (opcode & UCOND_DISP) << 1;
601       if (displacement & 0x0800)
602 	displacement |= 0xfffff000;
603 
604       /*
605 	   * Remember PC points to second instr.
606 	   * after PC of branch ... so add 4
607 	   */
608       instrMem = (short *) (registers[PC] + displacement + 4);
609     }
610   else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR)
611     {
612       reg = (char) ((opcode & UCOND_REG) >> 8);
613 
614       instrMem = (short *) registers[reg];
615     }
616   else if (opcode == RTS_INSTR)
617     instrMem = (short *) registers[PR];
618   else if (opcode == RTE_INSTR)
619     instrMem = (short *) registers[15];
620   else if ((opcode & TRAPA_MASK) == TRAPA_INSTR)
621     instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2);
622   else
623     instrMem += 1;
624 
625   instrBuffer.memAddr = instrMem;
626   instrBuffer.oldInstr = *instrMem;
627   *instrMem = SSTEP_INSTR;
628 }
629 
630 
631 /* Undo the effect of a previous doSStep.  If we single stepped,
632    restore the old instruction. */
633 
634 void
635 undoSStep (void)
636 {
637   if (stepped)
638     {  short *instrMem;
639       instrMem = instrBuffer.memAddr;
640       *instrMem = instrBuffer.oldInstr;
641     }
642   stepped = 0;
643 }
644 
645 /*
646 This function does all exception handling.  It only does two things -
647 it figures out why it was called and tells gdb, and then it reacts
648 to gdb's requests.
649 
650 When in the monitor mode we talk a human on the serial line rather than gdb.
651 
652 */
653 
654 
655 void
656 gdb_handle_exception (int exceptionVector)
657 {
658   int sigval, stepping;
659   int addr, length;
660   char *ptr;
661 
662   /* reply to host that an exception has occurred */
663   sigval = computeSignal (exceptionVector);
664   remcomOutBuffer[0] = 'S';
665   remcomOutBuffer[1] = highhex(sigval);
666   remcomOutBuffer[2] = lowhex (sigval);
667   remcomOutBuffer[3] = 0;
668 
669   putpacket (remcomOutBuffer);
670 
671   /*
672    * exception 255 indicates a software trap
673    * inserted in place of code ... so back up
674    * PC by one instruction, since this instruction
675    * will later be replaced by its original one!
676    */
677   if (exceptionVector == 0xff
678       || exceptionVector == 0x20)
679     registers[PC] -= 2;
680 
681   /*
682    * Do the thangs needed to undo
683    * any stepping we may have done!
684    */
685   undoSStep ();
686 
687   stepping = 0;
688 
689   while (1)
690     {
691       remcomOutBuffer[0] = 0;
692       ptr = getpacket ();
693 
694       switch (*ptr++)
695 	{
696 	case '?':
697 	  remcomOutBuffer[0] = 'S';
698 	  remcomOutBuffer[1] = highhex (sigval);
699 	  remcomOutBuffer[2] = lowhex (sigval);
700 	  remcomOutBuffer[3] = 0;
701 	  break;
702 	case 'd':
703 	  remote_debug = !(remote_debug);	/* toggle debug flag */
704 	  break;
705 	case 'g':		/* return the value of the CPU registers */
706 	  mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES);
707 	  break;
708 	case 'G':		/* set the value of the CPU registers - return OK */
709 	  hex2mem (ptr, (char *) registers, NUMREGBYTES);
710 	  strcpy (remcomOutBuffer, "OK");
711 	  break;
712 
713 	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
714 	case 'm':
715 	  if (setjmp (remcomEnv) == 0)
716 	    {
717 	      dofault = 0;
718 	      /* TRY, TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
719 	      if (hexToInt (&ptr, &addr))
720 		if (*(ptr++) == ',')
721 		  if (hexToInt (&ptr, &length))
722 		    {
723 		      ptr = 0;
724 		      mem2hex ((char *) addr, remcomOutBuffer, length);
725 		    }
726 	      if (ptr)
727 		strcpy (remcomOutBuffer, "E01");
728 	    }
729 	  else
730 	    strcpy (remcomOutBuffer, "E03");
731 
732 	  /* restore handler for bus error */
733 	  dofault = 1;
734 	  break;
735 
736 	  /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
737 	case 'M':
738 	  if (setjmp (remcomEnv) == 0)
739 	    {
740 	      dofault = 0;
741 
742 	      /* TRY, TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
743 	      if (hexToInt (&ptr, &addr))
744 		if (*(ptr++) == ',')
745 		  if (hexToInt (&ptr, &length))
746 		    if (*(ptr++) == ':')
747 		      {
748 			hex2mem (ptr, (char *) addr, length);
749 			ptr = 0;
750 			strcpy (remcomOutBuffer, "OK");
751 		      }
752 	      if (ptr)
753 		strcpy (remcomOutBuffer, "E02");
754 	    }
755 	  else
756 	    strcpy (remcomOutBuffer, "E03");
757 
758 	  /* restore handler for bus error */
759 	  dofault = 1;
760 	  break;
761 
762 	  /* cAA..AA    Continue at address AA..AA(optional) */
763 	  /* sAA..AA   Step one instruction from AA..AA(optional) */
764 	case 's':
765 	  stepping = 1;
766 	case 'c':
767 	  {
768 	    /* tRY, to read optional parameter, pc unchanged if no parm */
769 	    if (hexToInt (&ptr, &addr))
770 	      registers[PC] = addr;
771 
772 	    if (stepping)
773 	      doSStep ();
774 	  }
775 	  return;
776 	  break;
777 
778 	  /* kill the program */
779 	case 'k':		/* do nothing */
780 	  break;
781 	}			/* switch */
782 
783       /* reply to the request */
784       putpacket (remcomOutBuffer);
785     }
786 }
787 
788 
789 #define GDBCOOKIE 0x5ac
790 static int ingdbmode;
791 /* We've had an exception - choose to go into the monitor or
792    the gdb stub */
793 void handle_exception(int exceptionVector)
794 {
795 #ifdef MONITOR
796     if (ingdbmode != GDBCOOKIE)
797       monitor_handle_exception (exceptionVector);
798     else
799 #endif
800       gdb_handle_exception (exceptionVector);
801 
802 }
803 
804 void
805 gdb_mode (void)
806 {
807   ingdbmode = GDBCOOKIE;
808   breakpoint();
809 }
810 /* This function will generate a breakpoint exception.  It is used at the
811    beginning of a program to sync up with a debugger and can be used
812    otherwise as a quick means to stop program execution and "break" into
813    the debugger. */
814 
815 void
816 breakpoint (void)
817 {
818       BREAKPOINT ();
819 }
820 
821 /**** Processor-specific routines start here ****/
822 /**** Processor-specific routines start here ****/
823 /**** Processor-specific routines start here ****/
824 
825 /* Note:
826 
827    The Renesas SH family uses two exception architectures:
828 
829    SH1 & SH2:
830 
831        These processors utilize an exception vector table.
832        Exceptions are vectored to the address stored at VBR + (exception_num * 4)
833 
834   SH3, SH3E, & SH4:
835 
836        These processors have fixed entry points relative to the VBR for
837        various exception classes.
838 */
839 
840 #if defined(__sh1__) || defined(__sh2__)
841 
842 /* SH1/SH2 exception vector table format */
843 
844 typedef struct
845   {
846     void (*func_cold) ();
847     int *stack_cold;
848     void (*func_warm) ();
849     int *stack_warm;
850     void (*(handler[256 - 4])) ();
851   }
852 vec_type;
853 
854 /* vectable is the SH1/SH2 vector table. It must be at address 0
855    or wherever your vbr points. */
856 
857 const vec_type vectable =
858 {
859   &BINIT,			/* 0: Power-on reset PC */
860   init_stack + init_stack_size, /* 1: Power-on reset SP */
861   &BINIT,			/* 2: Manual reset PC */
862   init_stack + init_stack_size, /* 3: Manual reset SP */
863 {
864   &catch_exception_4,		/* 4: General invalid instruction */
865   &catch_exception_random,	/* 5: Reserved for system */
866   &catch_exception_6,		/* 6: Invalid slot instruction */
867   &catch_exception_random,	/* 7: Reserved for system */
868   &catch_exception_random,	/* 8: Reserved for system */
869   &catch_exception_9,		/* 9: CPU bus error */
870   &catch_exception_10,		/* 10: DMA bus error */
871   &catch_exception_11,		/* 11: NMI */
872   &catch_exception_random,	/* 12: User break */
873   &catch_exception_random,	/* 13: Reserved for system */
874   &catch_exception_random,	/* 14: Reserved for system */
875   &catch_exception_random,	/* 15: Reserved for system */
876   &catch_exception_random,	/* 16: Reserved for system */
877   &catch_exception_random,	/* 17: Reserved for system */
878   &catch_exception_random,	/* 18: Reserved for system */
879   &catch_exception_random,	/* 19: Reserved for system */
880   &catch_exception_random,	/* 20: Reserved for system */
881   &catch_exception_random,	/* 21: Reserved for system */
882   &catch_exception_random,	/* 22: Reserved for system */
883   &catch_exception_random,	/* 23: Reserved for system */
884   &catch_exception_random,	/* 24: Reserved for system */
885   &catch_exception_random,	/* 25: Reserved for system */
886   &catch_exception_random,	/* 26: Reserved for system */
887   &catch_exception_random,	/* 27: Reserved for system */
888   &catch_exception_random,	/* 28: Reserved for system */
889   &catch_exception_random,	/* 29: Reserved for system */
890   &catch_exception_random,	/* 30: Reserved for system */
891   &catch_exception_random,	/* 31: Reserved for system */
892   &catch_exception_32,		/* 32: Trap instr (user vectors) */
893   &catch_exception_33,		/* 33: Trap instr (user vectors) */
894   &catch_exception_random,	/* 34: Trap instr (user vectors) */
895   &catch_exception_random,	/* 35: Trap instr (user vectors) */
896   &catch_exception_random,	/* 36: Trap instr (user vectors) */
897   &catch_exception_random,	/* 37: Trap instr (user vectors) */
898   &catch_exception_random,	/* 38: Trap instr (user vectors) */
899   &catch_exception_random,	/* 39: Trap instr (user vectors) */
900   &catch_exception_random,	/* 40: Trap instr (user vectors) */
901   &catch_exception_random,	/* 41: Trap instr (user vectors) */
902   &catch_exception_random,	/* 42: Trap instr (user vectors) */
903   &catch_exception_random,	/* 43: Trap instr (user vectors) */
904   &catch_exception_random,	/* 44: Trap instr (user vectors) */
905   &catch_exception_random,	/* 45: Trap instr (user vectors) */
906   &catch_exception_random,	/* 46: Trap instr (user vectors) */
907   &catch_exception_random,	/* 47: Trap instr (user vectors) */
908   &catch_exception_random,	/* 48: Trap instr (user vectors) */
909   &catch_exception_random,	/* 49: Trap instr (user vectors) */
910   &catch_exception_random,	/* 50: Trap instr (user vectors) */
911   &catch_exception_random,	/* 51: Trap instr (user vectors) */
912   &catch_exception_random,	/* 52: Trap instr (user vectors) */
913   &catch_exception_random,	/* 53: Trap instr (user vectors) */
914   &catch_exception_random,	/* 54: Trap instr (user vectors) */
915   &catch_exception_random,	/* 55: Trap instr (user vectors) */
916   &catch_exception_random,	/* 56: Trap instr (user vectors) */
917   &catch_exception_random,	/* 57: Trap instr (user vectors) */
918   &catch_exception_random,	/* 58: Trap instr (user vectors) */
919   &catch_exception_random,	/* 59: Trap instr (user vectors) */
920   &catch_exception_random,	/* 60: Trap instr (user vectors) */
921   &catch_exception_random,	/* 61: Trap instr (user vectors) */
922   &catch_exception_random,	/* 62: Trap instr (user vectors) */
923   &catch_exception_random,	/* 63: Trap instr (user vectors) */
924   &catch_exception_random,	/* 64: IRQ0 */
925   &catch_exception_random,	/* 65: IRQ1 */
926   &catch_exception_random,	/* 66: IRQ2 */
927   &catch_exception_random,	/* 67: IRQ3 */
928   &catch_exception_random,	/* 68: IRQ4 */
929   &catch_exception_random,	/* 69: IRQ5 */
930   &catch_exception_random,	/* 70: IRQ6 */
931   &catch_exception_random,	/* 71: IRQ7 */
932   &catch_exception_random,
933   &catch_exception_random,
934   &catch_exception_random,
935   &catch_exception_random,
936   &catch_exception_random,
937   &catch_exception_random,
938   &catch_exception_random,
939   &catch_exception_random,
940   &catch_exception_random,
941      &catch_exception_random,
942      &catch_exception_random,
943      &catch_exception_random,
944      &catch_exception_random,
945      &catch_exception_random,
946      &catch_exception_random,
947      &catch_exception_random,
948      &catch_exception_random,
949      &catch_exception_random,
950      &catch_exception_random,
951      &catch_exception_random,
952      &catch_exception_random,
953      &catch_exception_random,
954      &catch_exception_random,
955      &catch_exception_random,
956      &catch_exception_random,
957      &catch_exception_random,
958      &catch_exception_random,
959      &catch_exception_random,
960      &catch_exception_random,
961      &catch_exception_random,
962      &catch_exception_random,
963      &catch_exception_random,
964      &catch_exception_random,
965      &catch_exception_random,
966      &catch_exception_random,
967      &catch_exception_random,
968      &catch_exception_random,
969      &catch_exception_random,
970      &catch_exception_random,
971      &catch_exception_random,
972      &catch_exception_random,
973      &catch_exception_random,
974      &catch_exception_random,
975      &catch_exception_random,
976      &catch_exception_random,
977      &catch_exception_random,
978      &catch_exception_random,
979      &catch_exception_random,
980      &catch_exception_random,
981      &catch_exception_random,
982      &catch_exception_random,
983      &catch_exception_random,
984      &catch_exception_random,
985      &catch_exception_random,
986      &catch_exception_random,
987      &catch_exception_random,
988      &catch_exception_random,
989      &catch_exception_random,
990      &catch_exception_random,
991      &catch_exception_random,
992      &catch_exception_random,
993      &catch_exception_random,
994      &catch_exception_random,
995      &catch_exception_random,
996      &catch_exception_random,
997      &catch_exception_random,
998      &catch_exception_random,
999      &catch_exception_random,
1000      &catch_exception_random,
1001      &catch_exception_random,
1002      &catch_exception_random,
1003      &catch_exception_random,
1004      &catch_exception_random,
1005      &catch_exception_random,
1006      &catch_exception_random,
1007      &catch_exception_random,
1008      &catch_exception_random,
1009      &catch_exception_random,
1010      &catch_exception_random,
1011      &catch_exception_random,
1012      &catch_exception_random,
1013      &catch_exception_random,
1014      &catch_exception_random,
1015      &catch_exception_random,
1016      &catch_exception_random,
1017      &catch_exception_random,
1018      &catch_exception_random,
1019      &catch_exception_random,
1020      &catch_exception_random,
1021      &catch_exception_random,
1022      &catch_exception_random,
1023      &catch_exception_random,
1024      &catch_exception_random,
1025      &catch_exception_random,
1026      &catch_exception_random,
1027      &catch_exception_random,
1028      &catch_exception_random,
1029      &catch_exception_random,
1030      &catch_exception_random,
1031      &catch_exception_random,
1032      &catch_exception_random,
1033      &catch_exception_random,
1034      &catch_exception_random,
1035      &catch_exception_random,
1036      &catch_exception_random,
1037      &catch_exception_random,
1038      &catch_exception_random,
1039      &catch_exception_random,
1040      &catch_exception_random,
1041      &catch_exception_random,
1042      &catch_exception_random,
1043      &catch_exception_random,
1044      &catch_exception_random,
1045      &catch_exception_random,
1046      &catch_exception_random,
1047      &catch_exception_random,
1048      &catch_exception_random,
1049      &catch_exception_random,
1050      &catch_exception_random,
1051      &catch_exception_random,
1052      &catch_exception_random,
1053      &catch_exception_random,
1054      &catch_exception_random,
1055      &catch_exception_random,
1056      &catch_exception_random,
1057      &catch_exception_random,
1058      &catch_exception_random,
1059      &catch_exception_random,
1060      &catch_exception_random,
1061      &catch_exception_random,
1062      &catch_exception_random,
1063      &catch_exception_random,
1064      &catch_exception_random,
1065      &catch_exception_random,
1066      &catch_exception_random,
1067      &catch_exception_random,
1068      &catch_exception_random,
1069      &catch_exception_random,
1070      &catch_exception_random,
1071      &catch_exception_random,
1072      &catch_exception_random,
1073      &catch_exception_random,
1074      &catch_exception_random,
1075      &catch_exception_random,
1076      &catch_exception_random,
1077      &catch_exception_random,
1078      &catch_exception_random,
1079      &catch_exception_random,
1080      &catch_exception_random,
1081      &catch_exception_random,
1082      &catch_exception_random,
1083      &catch_exception_random,
1084      &catch_exception_random,
1085      &catch_exception_random,
1086      &catch_exception_random,
1087      &catch_exception_random,
1088      &catch_exception_random,
1089      &catch_exception_random,
1090      &catch_exception_random,
1091      &catch_exception_random,
1092      &catch_exception_random,
1093      &catch_exception_random,
1094      &catch_exception_random,
1095      &catch_exception_random,
1096      &catch_exception_random,
1097      &catch_exception_random,
1098      &catch_exception_random,
1099      &catch_exception_random,
1100      &catch_exception_random,
1101      &catch_exception_random,
1102      &catch_exception_random,
1103      &catch_exception_random,
1104      &catch_exception_random,
1105      &catch_exception_random,
1106      &catch_exception_random,
1107      &catch_exception_random,
1108      &catch_exception_random,
1109      &catch_exception_random,
1110      &catch_exception_random,
1111      &catch_exception_random,
1112      &catch_exception_random,
1113      &catch_exception_random,
1114      &catch_exception_random,
1115      &catch_exception_255}};
1116 
1117 #define BCR  (*(volatile short *)(0x05FFFFA0)) /* Bus control register */
1118 #define BAS  (0x800)				/* Byte access select */
1119 #define WCR1 (*(volatile short *)(0x05ffffA2)) /* Wait state control register */
1120 
1121 asm ("_BINIT: mov.l  L1,r15");
1122 asm ("bra _INIT");
1123 asm ("nop");
1124 asm ("L1: .long _init_stack + 8*1024*4");
1125 void
1126 INIT (void)
1127 {
1128   /* First turn on the ram */
1129   WCR1  = 0;    /* Never sample wait */
1130   BCR = BAS;    /* use lowbyte/high byte */
1131 
1132   init_serial();
1133 
1134 #ifdef MONITOR
1135   reset_hook ();
1136 #endif
1137 
1138 
1139   in_nmi = 0;
1140   dofault = 1;
1141   stepped = 0;
1142 
1143   stub_sp = stub_stack + stub_stack_size;
1144   breakpoint ();
1145 
1146   while (1)
1147     ;
1148 }
1149 
1150 
1151 static void sr()
1152 {
1153 
1154 
1155   /* Calling Reset does the same as pressing the button */
1156   asm (".global _Reset
1157         .global _WarmReset
1158 _Reset:
1159 _WarmReset:
1160          mov.l L_sp,r15
1161          bra   _INIT
1162          nop
1163          .align 2
1164 L_sp:    .long _init_stack + 8000");
1165 
1166   asm("saveRegisters:
1167 	mov.l	@(L_reg, pc), r0
1168 	mov.l	@r15+, r1				! pop R0
1169 	mov.l	r2, @(0x08, r0)				! save R2
1170 	mov.l	r1, @r0					! save R0
1171 	mov.l	@r15+, r1				! pop R1
1172 	mov.l	r3, @(0x0c, r0)				! save R3
1173 	mov.l	r1, @(0x04, r0)				! save R1
1174 	mov.l	r4, @(0x10, r0)				! save R4
1175 	mov.l	r5, @(0x14, r0)				! save R5
1176 	mov.l	r6, @(0x18, r0)				! save R6
1177 	mov.l	r7, @(0x1c, r0)				! save R7
1178 	mov.l	r8, @(0x20, r0)				! save R8
1179 	mov.l	r9, @(0x24, r0)				! save R9
1180 	mov.l	r10, @(0x28, r0)			! save R10
1181 	mov.l	r11, @(0x2c, r0)			! save R11
1182 	mov.l	r12, @(0x30, r0)			! save R12
1183 	mov.l	r13, @(0x34, r0)			! save R13
1184 	mov.l	r14, @(0x38, r0)			! save R14
1185 	mov.l	@r15+, r4				! save arg to handleException
1186 	add	#8, r15					! hide PC/SR values on stack
1187 	mov.l	r15, @(0x3c, r0)			! save R15
1188 	add	#-8, r15				! save still needs old SP value
1189 	add	#92, r0					! readjust register pointer
1190 	mov	r15, r2
1191 	add	#4, r2
1192 	mov.l	@r2, r2					! R2 has SR
1193 	mov.l	@r15, r1				! R1 has PC
1194 	mov.l	r2, @-r0				! save SR
1195 	sts.l	macl, @-r0				! save MACL
1196 	sts.l	mach, @-r0				! save MACH
1197 	stc.l	vbr, @-r0				! save VBR
1198 	stc.l	gbr, @-r0				! save GBR
1199 	sts.l	pr, @-r0				! save PR
1200 	mov.l	@(L_stubstack, pc), r2
1201 	mov.l	@(L_hdl_except, pc), r3
1202 	mov.l	@r2, r15
1203 	jsr	@r3
1204 	mov.l	r1, @-r0				! save PC
1205 	mov.l	@(L_stubstack, pc), r0
1206 	mov.l	@(L_reg, pc), r1
1207 	bra	restoreRegisters
1208 	mov.l	r15, @r0				! save __stub_stack
1209 
1210 	.align 2
1211 L_reg:
1212 	.long	_registers
1213 L_stubstack:
1214 	.long	_stub_sp
1215 L_hdl_except:
1216 	.long	_handle_exception");
1217 
1218 }
1219 
1220 static void rr()
1221 {
1222 asm("
1223 	.align 2
1224         .global _resume
1225 _resume:
1226 	mov	r4,r1
1227 restoreRegisters:
1228 	add	#8, r1						! skip to R2
1229 	mov.l	@r1+, r2					! restore R2
1230 	mov.l	@r1+, r3					! restore R3
1231 	mov.l	@r1+, r4					! restore R4
1232 	mov.l	@r1+, r5					! restore R5
1233 	mov.l	@r1+, r6					! restore R6
1234 	mov.l	@r1+, r7					! restore R7
1235 	mov.l	@r1+, r8					! restore R8
1236 	mov.l	@r1+, r9					! restore R9
1237 	mov.l	@r1+, r10					! restore R10
1238 	mov.l	@r1+, r11					! restore R11
1239 	mov.l	@r1+, r12					! restore R12
1240 	mov.l	@r1+, r13					! restore R13
1241 	mov.l	@r1+, r14					! restore R14
1242 	mov.l	@r1+, r15					! restore programs stack
1243 	mov.l	@r1+, r0
1244 	add	#-8, r15					! uncover PC/SR on stack
1245 	mov.l	r0, @r15					! restore PC onto stack
1246 	lds.l	@r1+, pr					! restore PR
1247 	ldc.l	@r1+, gbr					! restore GBR
1248 	ldc.l	@r1+, vbr					! restore VBR
1249 	lds.l	@r1+, mach					! restore MACH
1250 	lds.l	@r1+, macl					! restore MACL
1251 	mov.l	@r1, r0
1252 	add	#-88, r1					! readjust reg pointer to R1
1253 	mov.l	r0, @(4, r15)					! restore SR onto stack+4
1254 	mov.l	r2, @-r15
1255 	mov.l	L_in_nmi, r0
1256 	mov		#0, r2
1257 	mov.b	r2, @r0
1258 	mov.l	@r15+, r2
1259 	mov.l	@r1+, r0					! restore R0
1260 	rte
1261 	mov.l	@r1, r1						! restore R1
1262 
1263 ");
1264 }
1265 
1266 
1267 static __inline__ void code_for_catch_exception(int n)
1268 {
1269   asm("		.globl	_catch_exception_%O0" : : "i" (n) 				);
1270   asm("	_catch_exception_%O0:" :: "i" (n)      						);
1271 
1272   asm("		add	#-4, r15 				! reserve spot on stack ");
1273   asm("		mov.l	r1, @-r15				! push R1		");
1274 
1275   if (n == NMI_VEC)
1276     {
1277       /* Special case for NMI - make sure that they don't nest */
1278       asm("	mov.l	r0, @-r15					! push R0");
1279       asm("	mov.l	L_in_nmi, r0");
1280       asm("	tas.b	@r0						! Fend off against addtnl NMIs");
1281       asm("	bt		noNMI");
1282       asm("	mov.l	@r15+, r0");
1283       asm("	mov.l	@r15+, r1");
1284       asm("	add		#4, r15");
1285       asm("	rte");
1286       asm("	nop");
1287       asm(".align 2");
1288       asm("L_in_nmi: .long	_in_nmi");
1289       asm("noNMI:");
1290     }
1291   else
1292     {
1293 
1294       if (n == CPU_BUS_ERROR_VEC)
1295 	{
1296 	  /* Exception 9 (bus errors) are disasbleable - so that you
1297 	     can probe memory and get zero instead of a fault.
1298 	     Because the vector table may be in ROM we don't revector
1299 	     the interrupt like all the other stubs, we check in here
1300 	     */
1301 	  asm("mov.l	L_dofault,r1");
1302 	  asm("mov.l	@r1,r1");
1303 	  asm("tst	r1,r1");
1304 	  asm("bf	faultaway");
1305 	  asm("bsr	_handle_buserror");
1306 	  asm(".align	2");
1307 	  asm("L_dofault: .long _dofault");
1308 	  asm("faultaway:");
1309 	}
1310       asm("		mov	#15<<4, r1							");
1311       asm("		ldc	r1, sr					! disable interrupts	");
1312       asm("		mov.l	r0, @-r15				! push R0		");
1313     }
1314 
1315   /* Prepare for saving context, we've already pushed r0 and r1, stick exception number
1316      into the frame */
1317   asm("		mov	r15, r0								");
1318   asm("		add	#8, r0								");
1319   asm("		mov	%0,r1" :: "i" (n)        					);
1320   asm("		extu.b  r1,r1								");
1321   asm("		bra	saveRegisters				! save register values	");
1322   asm("		mov.l	r1, @r0					! save exception # 	");
1323 }
1324 
1325 
1326 static  void
1327 exceptions (void)
1328 {
1329   code_for_catch_exception (CPU_BUS_ERROR_VEC);
1330   code_for_catch_exception (DMA_BUS_ERROR_VEC);
1331   code_for_catch_exception (INVALID_INSN_VEC);
1332   code_for_catch_exception (INVALID_SLOT_VEC);
1333   code_for_catch_exception (NMI_VEC);
1334   code_for_catch_exception (TRAP_VEC);
1335   code_for_catch_exception (USER_VEC);
1336   code_for_catch_exception (IO_VEC);
1337 }
1338 
1339 
1340 
1341 
1342 
1343 
1344 /* Support for Serial I/O using on chip uart */
1345 
1346 #define SMR0 (*(volatile char *)(0x05FFFEC0)) /* Channel 0  serial mode register */
1347 #define BRR0 (*(volatile char *)(0x05FFFEC1)) /* Channel 0  bit rate register */
1348 #define SCR0 (*(volatile char *)(0x05FFFEC2)) /* Channel 0  serial control register */
1349 #define TDR0 (*(volatile char *)(0x05FFFEC3)) /* Channel 0  transmit data register */
1350 #define SSR0 (*(volatile char *)(0x05FFFEC4)) /* Channel 0  serial status register */
1351 #define RDR0 (*(volatile char *)(0x05FFFEC5)) /* Channel 0  receive data register */
1352 
1353 #define SMR1 (*(volatile char *)(0x05FFFEC8)) /* Channel 1  serial mode register */
1354 #define BRR1 (*(volatile char *)(0x05FFFEC9)) /* Channel 1  bit rate register */
1355 #define SCR1 (*(volatile char *)(0x05FFFECA)) /* Channel 1  serial control register */
1356 #define TDR1 (*(volatile char *)(0x05FFFECB)) /* Channel 1  transmit data register */
1357 #define SSR1 (*(volatile char *)(0x05FFFECC)) /* Channel 1  serial status register */
1358 #define RDR1 (*(volatile char *)(0x05FFFECD)) /* Channel 1  receive data register */
1359 
1360 /*
1361  * Serial mode register bits
1362  */
1363 
1364 #define SYNC_MODE 		0x80
1365 #define SEVEN_BIT_DATA 		0x40
1366 #define PARITY_ON		0x20
1367 #define ODD_PARITY		0x10
1368 #define STOP_BITS_2		0x08
1369 #define ENABLE_MULTIP		0x04
1370 #define PHI_64			0x03
1371 #define PHI_16			0x02
1372 #define PHI_4			0x01
1373 
1374 /*
1375  * Serial control register bits
1376  */
1377 #define SCI_TIE				0x80	/* Transmit interrupt enable */
1378 #define SCI_RIE				0x40	/* Receive interrupt enable */
1379 #define SCI_TE				0x20	/* Transmit enable */
1380 #define SCI_RE				0x10	/* Receive enable */
1381 #define SCI_MPIE			0x08	/* Multiprocessor interrupt enable */
1382 #define SCI_TEIE			0x04	/* Transmit end interrupt enable */
1383 #define SCI_CKE1			0x02	/* Clock enable 1 */
1384 #define SCI_CKE0			0x01	/* Clock enable 0 */
1385 
1386 /*
1387  * Serial status register bits
1388  */
1389 #define SCI_TDRE			0x80	/* Transmit data register empty */
1390 #define SCI_RDRF			0x40	/* Receive data register full */
1391 #define SCI_ORER			0x20	/* Overrun error */
1392 #define SCI_FER				0x10	/* Framing error */
1393 #define SCI_PER				0x08	/* Parity error */
1394 #define SCI_TEND			0x04	/* Transmit end */
1395 #define SCI_MPB				0x02	/* Multiprocessor bit */
1396 #define SCI_MPBT			0x01	/* Multiprocessor bit transfer */
1397 
1398 
1399 /*
1400  * Port B IO Register (PBIOR)
1401  */
1402 #define	PBIOR 		(*(volatile char *)(0x05FFFFC6))
1403 #define	PB15IOR 	0x8000
1404 #define	PB14IOR 	0x4000
1405 #define	PB13IOR 	0x2000
1406 #define	PB12IOR 	0x1000
1407 #define	PB11IOR 	0x0800
1408 #define	PB10IOR 	0x0400
1409 #define	PB9IOR 		0x0200
1410 #define	PB8IOR 		0x0100
1411 #define	PB7IOR 		0x0080
1412 #define	PB6IOR 		0x0040
1413 #define	PB5IOR 		0x0020
1414 #define	PB4IOR 		0x0010
1415 #define	PB3IOR 		0x0008
1416 #define	PB2IOR 		0x0004
1417 #define	PB1IOR 		0x0002
1418 #define	PB0IOR 		0x0001
1419 
1420 /*
1421  * Port B Control Register (PBCR1)
1422  */
1423 #define	PBCR1 		(*(volatile short *)(0x05FFFFCC))
1424 #define	PB15MD1 	0x8000
1425 #define	PB15MD0 	0x4000
1426 #define	PB14MD1 	0x2000
1427 #define	PB14MD0 	0x1000
1428 #define	PB13MD1 	0x0800
1429 #define	PB13MD0 	0x0400
1430 #define	PB12MD1 	0x0200
1431 #define	PB12MD0 	0x0100
1432 #define	PB11MD1 	0x0080
1433 #define	PB11MD0 	0x0040
1434 #define	PB10MD1 	0x0020
1435 #define	PB10MD0 	0x0010
1436 #define	PB9MD1 		0x0008
1437 #define	PB9MD0 		0x0004
1438 #define	PB8MD1 		0x0002
1439 #define	PB8MD0 		0x0001
1440 
1441 #define	PB15MD 		PB15MD1|PB14MD0
1442 #define	PB14MD 		PB14MD1|PB14MD0
1443 #define	PB13MD 		PB13MD1|PB13MD0
1444 #define	PB12MD 		PB12MD1|PB12MD0
1445 #define	PB11MD 		PB11MD1|PB11MD0
1446 #define	PB10MD 		PB10MD1|PB10MD0
1447 #define	PB9MD 		PB9MD1|PB9MD0
1448 #define	PB8MD 		PB8MD1|PB8MD0
1449 
1450 #define PB_TXD1 	PB11MD1
1451 #define PB_RXD1 	PB10MD1
1452 #define PB_TXD0 	PB9MD1
1453 #define PB_RXD0 	PB8MD1
1454 
1455 /*
1456  * Port B Control Register (PBCR2)
1457  */
1458 #define	PBCR2 	0x05FFFFCE
1459 #define	PB7MD1 	0x8000
1460 #define	PB7MD0 	0x4000
1461 #define	PB6MD1 	0x2000
1462 #define	PB6MD0 	0x1000
1463 #define	PB5MD1 	0x0800
1464 #define	PB5MD0 	0x0400
1465 #define	PB4MD1 	0x0200
1466 #define	PB4MD0 	0x0100
1467 #define	PB3MD1 	0x0080
1468 #define	PB3MD0 	0x0040
1469 #define	PB2MD1 	0x0020
1470 #define	PB2MD0 	0x0010
1471 #define	PB1MD1 	0x0008
1472 #define	PB1MD0 	0x0004
1473 #define	PB0MD1 	0x0002
1474 #define	PB0MD0 	0x0001
1475 
1476 #define	PB7MD 	PB7MD1|PB7MD0
1477 #define	PB6MD 	PB6MD1|PB6MD0
1478 #define	PB5MD 	PB5MD1|PB5MD0
1479 #define	PB4MD 	PB4MD1|PB4MD0
1480 #define	PB3MD 	PB3MD1|PB3MD0
1481 #define	PB2MD 	PB2MD1|PB2MD0
1482 #define	PB1MD 	PB1MD1|PB1MD0
1483 #define	PB0MD 	PB0MD1|PB0MD0
1484 
1485 
1486 #ifdef MHZ
1487 #define BPS			32 * 9600 * MHZ / ( BAUD * 10)
1488 #else
1489 #define BPS			32	/* 9600 for 10 Mhz */
1490 #endif
1491 
1492 void handleError (char theSSR);
1493 
1494 void
1495 nop (void)
1496 {
1497 
1498 }
1499 void
1500 init_serial (void)
1501 {
1502   int i;
1503 
1504   /* Clear TE and RE in Channel 1's SCR   */
1505   SCR1 &= ~(SCI_TE | SCI_RE);
1506 
1507   /* Set communication to be async, 8-bit data, no parity, 1 stop bit and use internal clock */
1508 
1509   SMR1 = 0;
1510   BRR1 = BPS;
1511 
1512   SCR1 &= ~(SCI_CKE1 | SCI_CKE0);
1513 
1514   /* let the hardware settle */
1515 
1516   for (i = 0; i < 1000; i++)
1517     nop ();
1518 
1519   /* Turn on in and out */
1520   SCR1 |= SCI_RE | SCI_TE;
1521 
1522   /* Set the PFC to make RXD1 (pin PB8) an input pin and TXD1 (pin PB9) an output pin */
1523   PBCR1 &= ~(PB_TXD1 | PB_RXD1);
1524   PBCR1 |= PB_TXD1 | PB_RXD1;
1525 }
1526 
1527 
1528 int
1529 getDebugCharReady (void)
1530 {
1531   char mySSR;
1532   mySSR = SSR1 & ( SCI_PER | SCI_FER | SCI_ORER );
1533   if ( mySSR )
1534     handleError ( mySSR );
1535   return SSR1 & SCI_RDRF ;
1536 }
1537 
1538 char
1539 getDebugChar (void)
1540 {
1541   char ch;
1542   char mySSR;
1543 
1544   while ( ! getDebugCharReady())
1545     ;
1546 
1547   ch = RDR1;
1548   SSR1 &= ~SCI_RDRF;
1549 
1550   mySSR = SSR1 & (SCI_PER | SCI_FER | SCI_ORER);
1551 
1552   if (mySSR)
1553     handleError (mySSR);
1554 
1555   return ch;
1556 }
1557 
1558 int
1559 putDebugCharReady (void)
1560 {
1561   return (SSR1 & SCI_TDRE);
1562 }
1563 
1564 void
1565 putDebugChar (char ch)
1566 {
1567   while (!putDebugCharReady())
1568     ;
1569 
1570   /*
1571    * Write data into TDR and clear TDRE
1572    */
1573   TDR1 = ch;
1574   SSR1 &= ~SCI_TDRE;
1575 }
1576 
1577 void
1578 handleError (char theSSR)
1579 {
1580   SSR1 &= ~(SCI_ORER | SCI_PER | SCI_FER);
1581 }
1582 
1583 #endif
1584