blob: 86255b74e12b71c8340560f626392b0ad67e21ff [file] [log] [blame]
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19/* sh-stub.c -- debugging stub for the Hitachi-SH.
20
21 NOTE!! This code has to be compiled with optimization, otherwise the
22 function inlining which generates the exception handlers won't work.
23
24*/
25
26/* This is originally based on an m68k software stub written by Glenn
27 Engel at HP, but has changed quite a bit.
28
29 Modifications for the SH by Ben Lee and Steve Chamberlain
30
31 Even more modifications for GCC 3.0 and The Rockbox by Linus
32 Nielsen Feltzing
33*/
34
35/****************************************************************************
36
37 THIS SOFTWARE IS NOT COPYRIGHTED
38
39 HP offers the following for use in the public domain. HP makes no
40 warranty with regard to the software or it's performance and the
41 user accepts the software "AS IS" with all faults.
42
43 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
44 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
45 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
46
47****************************************************************************/
48
49
50/* Remote communication protocol.
51
52 A debug packet whose contents are <data>
53 is encapsulated for transmission in the form:
54
55 $ <data> # CSUM1 CSUM2
56
57 <data> must be ASCII alphanumeric and cannot include characters
58 '$' or '#'. If <data> starts with two characters followed by
59 ':', then the existing stubs interpret this as a sequence number.
60
61 CSUM1 and CSUM2 are ascii hex representation of an 8-bit
62 checksum of <data>, the most significant nibble is sent first.
63 the hex digits 0-9,a-f are used.
64
65 Receiver responds with:
66
67 + - if CSUM is correct and ready for next packet
68 - - if CSUM is incorrect
69
70 <data> is as follows:
71 All values are encoded in ascii hex digits.
72
73 Request Packet
74
75 read registers g
76 reply XX....X Each byte of register data
77 is described by two hex digits.
78 Registers are in the internal order
79 for GDB, and the bytes in a register
80 are in the same order the machine uses.
81 or ENN for an error.
82
83 write regs GXX..XX Each byte of register data
84 is described by two hex digits.
85 reply OK for success
86 ENN for an error
87
88 write reg Pn...=r... Write register n... with value r...,
89 which contains two hex digits for each
90 byte in the register (target byte
91 order).
92 reply OK for success
93 ENN for an error
94 (not supported by all stubs).
95
96 read mem mAA..AA,LLLL AA..AA is address, LLLL is length.
97 reply XX..XX XX..XX is mem contents
98 Can be fewer bytes than requested
99 if able to read only part of the data.
100 or ENN NN is errno
101
102 write mem MAA..AA,LLLL:XX..XX
103 AA..AA is address,
104 LLLL is number of bytes,
105 XX..XX is data
106 reply OK for success
107 ENN for an error (this includes the case
108 where only part of the data was
109 written).
110
111 cont cAA..AA AA..AA is address to resume
112 If AA..AA is omitted,
113 resume at same address.
114
115 step sAA..AA AA..AA is address to resume
116 If AA..AA is omitted,
117 resume at same address.
118
119 last signal ? Reply the current reason for stopping.
120 This is the same reply as is generated
121 for step or cont : SAA where AA is the
122 signal number.
123
124 There is no immediate reply to step or cont.
125 The reply comes when the machine stops.
126 It is SAA AA is the "signal number"
127
128 or... TAAn...:r...;n:r...;n...:r...;
129 AA = signal number
130 n... = register number
131 r... = register contents
132 or... WAA The process exited, and AA is
133 the exit status. This is only
134 applicable for certains sorts of
135 targets.
136 kill request k
137
138 toggle debug d toggle debug flag (see 386 & 68k stubs)
139 reset r reset -- see sparc stub.
140 reserved <other> On other requests, the stub should
141 ignore the request and send an empty
142 response ($#<checksum>). This way
143 we can extend the protocol and GDB
144 can tell whether the stub it is
145 talking to uses the old or the new.
146 search tAA:PP,MM Search backwards starting at address
147 AA for a match with pattern PP and
148 mask MM. PP and MM are 4 bytes.
149 Not supported by all stubs.
150
151 general query qXXXX Request info about XXXX.
152 general set QXXXX=yyyy Set value of XXXX to yyyy.
153 query sect offs qOffsets Get section offsets. Reply is
154 Text=xxx;Data=yyy;Bss=zzz
155 console output Otext Send text to stdout. Only comes from
156 remote target.
157
158 Responses can be run-length encoded to save space. A '*' means that
159 the next character is an ASCII encoding giving a repeat count which
160 stands for that many repititions of the character preceding the '*'.
161 The encoding is n+29, yielding a printable character where n >=3
162 (which is where rle starts to win). Don't use an n > 126.
163
164 So
165 "0* " means the same as "0000". */
166
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000167#include "sh7034.h"
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000168#include <string.h>
Linus Nielsen Feltzing1dc42d12003-05-17 00:31:50 +0000169
170typedef int jmp_buf[20];
171
172void longjmp(jmp_buf __jmpb, int __retval);
173int setjmp(jmp_buf __jmpb);
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000174
175/* We need to undefine this from the sh7034.h file */
176#undef GBR
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000177
178/* Hitachi SH architecture instruction encoding masks */
179
180#define COND_BR_MASK 0xff00
181#define UCOND_DBR_MASK 0xe000
182#define UCOND_RBR_MASK 0xf0df
183#define TRAPA_MASK 0xff00
184
185#define COND_DISP 0x00ff
186#define UCOND_DISP 0x0fff
187#define UCOND_REG 0x0f00
188
189/* Hitachi SH instruction opcodes */
190
191#define BF_INSTR 0x8b00
192#define BT_INSTR 0x8900
193#define BRA_INSTR 0xa000
194#define BSR_INSTR 0xb000
195#define JMP_INSTR 0x402b
196#define JSR_INSTR 0x400b
197#define RTS_INSTR 0x000b
198#define RTE_INSTR 0x002b
199#define TRAPA_INSTR 0xc300
200#define SSTEP_INSTR 0xc37f
201
202/* Hitachi SH processor register masks */
203
204#define T_BIT_MASK 0x0001
205
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000206/*
207 * BUFMAX defines the maximum number of characters in inbound/outbound
208 * buffers. At least NUMREGBYTES*2 are needed for register packets.
209 */
210#define BUFMAX 1024
211
212/*
213 * Number of bytes for registers
214 */
215#define NUMREGBYTES 112 /* 92 */
216
217/*
218 * Forward declarations
219 */
220
221static int hex (char);
222static char *mem2hex (char *mem, char *buf, int count);
223static char *hex2mem (char *buf, char *mem, int count);
224static int hex2int (char **ptr, int *intValue);
225static unsigned char *getpacket (void);
226static void putpacket (register char *buffer);
227static int computeSignal (int exceptionVector);
228void handle_buserror (void);
229void handle_exception (int exceptionVector);
Linus Nielsen Feltzing88c398a2002-04-23 20:33:45 +0000230void init_serial(void);
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000231
232void serial_putc (char ch);
233char serial_getc (void);
234
235/* These are in the file but in asm statements so the compiler can't see them */
236void catch_exception_4 (void);
237void catch_exception_5 (void);
238void catch_exception_6 (void);
239void catch_exception_7 (void);
240void catch_exception_8 (void);
241void catch_exception_9 (void);
242void catch_exception_10 (void);
243void catch_exception_11 (void);
244void catch_exception_12 (void);
245void catch_exception_13 (void);
246void catch_exception_14 (void);
247void catch_exception_15 (void);
248void catch_exception_16 (void);
249void catch_exception_17 (void);
250void catch_exception_18 (void);
251void catch_exception_19 (void);
252void catch_exception_20 (void);
253void catch_exception_21 (void);
254void catch_exception_22 (void);
255void catch_exception_23 (void);
256void catch_exception_24 (void);
257void catch_exception_25 (void);
258void catch_exception_26 (void);
259void catch_exception_27 (void);
260void catch_exception_28 (void);
261void catch_exception_29 (void);
262void catch_exception_30 (void);
263void catch_exception_31 (void);
264void catch_exception_32 (void);
265void catch_exception_33 (void);
266void catch_exception_34 (void);
267void catch_exception_35 (void);
268void catch_exception_36 (void);
269void catch_exception_37 (void);
270void catch_exception_38 (void);
271void catch_exception_39 (void);
272void catch_exception_40 (void);
273void catch_exception_41 (void);
274void catch_exception_42 (void);
275void catch_exception_43 (void);
276void catch_exception_44 (void);
277void catch_exception_45 (void);
278void catch_exception_46 (void);
279void catch_exception_47 (void);
280void catch_exception_48 (void);
281void catch_exception_49 (void);
282void catch_exception_50 (void);
283void catch_exception_51 (void);
284void catch_exception_52 (void);
285void catch_exception_53 (void);
286void catch_exception_54 (void);
287void catch_exception_55 (void);
288void catch_exception_56 (void);
289void catch_exception_57 (void);
290void catch_exception_58 (void);
291void catch_exception_59 (void);
292void catch_exception_60 (void);
293void catch_exception_61 (void);
294void catch_exception_62 (void);
295void catch_exception_63 (void);
296void catch_exception_64 (void);
297void catch_exception_65 (void);
298void catch_exception_66 (void);
299void catch_exception_67 (void);
300void catch_exception_68 (void);
301void catch_exception_69 (void);
302void catch_exception_70 (void);
303void catch_exception_71 (void);
304void catch_exception_72 (void);
305void catch_exception_73 (void);
306void catch_exception_74 (void);
307void catch_exception_75 (void);
308void catch_exception_76 (void);
309void catch_exception_77 (void);
310void catch_exception_78 (void);
311void catch_exception_79 (void);
312void catch_exception_80 (void);
313void catch_exception_81 (void);
314void catch_exception_82 (void);
315void catch_exception_83 (void);
316void catch_exception_84 (void);
317void catch_exception_85 (void);
318void catch_exception_86 (void);
319void catch_exception_87 (void);
320void catch_exception_88 (void);
321void catch_exception_89 (void);
322void catch_exception_90 (void);
323void catch_exception_91 (void);
324void catch_exception_92 (void);
325void catch_exception_93 (void);
326void catch_exception_94 (void);
327void catch_exception_95 (void);
328void catch_exception_96 (void);
329void catch_exception_97 (void);
330void catch_exception_98 (void);
331void catch_exception_99 (void);
332void catch_exception_100 (void);
333void catch_exception_101 (void);
334void catch_exception_102 (void);
335void catch_exception_103 (void);
336void catch_exception_104 (void);
337void catch_exception_105 (void);
338void catch_exception_106 (void);
339void catch_exception_107 (void);
340void catch_exception_108 (void);
341void catch_exception_109 (void);
342void catch_exception_110 (void);
343void catch_exception_111 (void);
344void catch_exception_112 (void);
345void catch_exception_113 (void);
346void catch_exception_114 (void);
347void catch_exception_115 (void);
348void catch_exception_116 (void);
349void catch_exception_117 (void);
350void catch_exception_118 (void);
351void catch_exception_119 (void);
352void catch_exception_120 (void);
353void catch_exception_121 (void);
354void catch_exception_122 (void);
355void catch_exception_123 (void);
356void catch_exception_124 (void);
357void catch_exception_125 (void);
358void catch_exception_126 (void);
359void catch_exception_127 (void);
360
361void breakpoint (void);
362
363
Linus Nielsen Feltzing8ee52132002-04-23 21:59:20 +0000364//#define stub_stack_size 2*1024
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000365
Linus Nielsen Feltzing8ee52132002-04-23 21:59:20 +0000366//int stub_stack[stub_stack_size] __attribute__ ((section (".stack"))) = {0};
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000367
Linus Nielsen Feltzing8ee52132002-04-23 21:59:20 +0000368extern int stub_stack[];
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000369
Linus Nielsen Feltzing88c398a2002-04-23 20:33:45 +0000370void INIT (void);
371void start (void);
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000372
373#define CPU_BUS_ERROR_VEC 9
374#define DMA_BUS_ERROR_VEC 10
375#define NMI_VEC 11
376#define INVALID_INSN_VEC 4
377#define INVALID_SLOT_VEC 6
378#define TRAP_VEC 32
379#define IO_VEC 33
380#define USER_VEC 127
381
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000382char in_nmi; /* Set when handling an NMI, so we don't reenter */
383int dofault; /* Non zero, bus errors will raise exception */
384
385int *stub_sp;
386
387/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
388int remote_debug;
389
390/* jump buffer used for setjmp/longjmp */
391jmp_buf remcomEnv;
392
393enum regnames
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000394{
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000395 R0, R1, R2, R3, R4, R5, R6, R7,
396 R8, R9, R10, R11, R12, R13, R14,
397 R15, PC, PR, GBR, VBR, MACH, MACL, SR,
398 TICKS, STALLS, CYCLES, INSTS, PLR
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000399};
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000400
401typedef struct
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000402{
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000403 short *memAddr;
404 short oldInstr;
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000405}
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000406stepData;
407
408int registers[NUMREGBYTES / 4];
409stepData instrBuffer;
410char stepped;
411static const char hexchars[] = "0123456789abcdef";
412static char remcomInBuffer[BUFMAX];
413static char remcomOutBuffer[BUFMAX];
414
Linus Nielsen Feltzing7958ea42002-05-11 20:04:48 +0000415#define ATA_NSECTOR (*((volatile unsigned char*)0x06100102))
416#define ATA_COMMAND (*((volatile unsigned char*)0x06100107))
Linus Nielsen Feltzing1dc42d12003-05-17 00:31:50 +0000417
Linus Nielsen Feltzing2af9bea2003-05-17 00:34:12 +0000418/* You may need to change this depending on your ATA I/O address
419** 0x200 - 0x06200206
420** 0x300 - 0x06200306
421*/
Linus Nielsen Feltzing1dc42d12003-05-17 00:31:50 +0000422#define ATA_CONTROL (*((volatile unsigned char*)0x06200206))
Linus Nielsen Feltzing7958ea42002-05-11 20:04:48 +0000423#define ATA_ALT_STATUS ATA_CONTROL
424
425#define STATUS_BSY 0x80
426#define STATUS_RDY 0x40
427
428#define CMD_STANDBY_IMMEDIATE 0xE0
429#define CMD_STANDBY 0xE2
430
431void ata_wait_for_bsy(void)
432{
433 while (ATA_ALT_STATUS & STATUS_BSY);
434}
435
436int ata_wait_for_rdy(void)
437{
438 ata_wait_for_bsy();
439 return ATA_ALT_STATUS & STATUS_RDY;
440}
441
442int ata_spindown(int time)
443{
444 /* activate ATA */
445 PADR &= ~0x80;
446
447 if(!ata_wait_for_rdy())
448 return -1;
449
450 if ( time == -1 ) {
451 ATA_COMMAND = CMD_STANDBY_IMMEDIATE;
452 }
453 else {
454 if (time > 255)
455 return -1;
456 ATA_NSECTOR = time & 0xff;
457 ATA_COMMAND = CMD_STANDBY;
458 }
459
460 if (!ata_wait_for_rdy())
461 return -1;
462
463 return 0;
464}
465
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000466void blink(void)
467{
468 while(1)
469 {
470 int i;
471 PBDR ^= 0x40; /* toggle PB6 */
472 for(i = 0;i < 500000;i++)
473 {
474 }
475 }
476}
477
478char highhex(int x)
479{
480 return hexchars[(x >> 4) & 0xf];
481}
482
483char lowhex(int x)
484{
485 return hexchars[x & 0xf];
486}
487
488/*
489 * Assembly macros
490 */
491
492#define BREAKPOINT() asm("trapa #0x20"::);
493
494
495/*
496 * Routines to handle hex data
497 */
498
499static int hex (char ch)
500{
501 if ((ch >= 'a') && (ch <= 'f'))
502 return (ch - 'a' + 10);
503 if ((ch >= '0') && (ch <= '9'))
504 return (ch - '0');
505 if ((ch >= 'A') && (ch <= 'F'))
506 return (ch - 'A' + 10);
507 return (-1);
508}
509
510/* convert the memory, pointed to by mem into hex, placing result in buf */
511/* return a pointer to the last char put in buf (null) */
512static char *mem2hex (char *mem, char *buf, int count)
513{
514 int i;
515 int ch;
516 for (i = 0; i < count; i++)
517 {
518 ch = *mem++;
519 *buf++ = highhex (ch);
520 *buf++ = lowhex (ch);
521 }
522 *buf = 0;
523 return (buf);
524}
525
526/* convert the hex array pointed to by buf into binary, to be placed in mem */
527/* return a pointer to the character after the last byte written */
528static char *hex2mem (char *buf, char *mem, int count)
529{
530 int i;
531 unsigned char ch;
532 for (i = 0; i < count; i++)
533 {
534 ch = hex (*buf++) << 4;
535 ch = ch + hex (*buf++);
536 *mem++ = ch;
537 }
538 return (mem);
539}
540
541/**********************************************/
542/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
543/* RETURN NUMBER OF CHARS PROCESSED */
544/**********************************************/
545static int hex2int (char **ptr, int *intValue)
546{
547 int numChars = 0;
548 int hexValue;
549
550 *intValue = 0;
551
552 while (**ptr)
553 {
554 hexValue = hex (**ptr);
555 if (hexValue >= 0)
556 {
557 *intValue = (*intValue << 4) | hexValue;
558 numChars++;
559 }
560 else
561 break;
562
563 (*ptr)++;
564 }
565
566 return (numChars);
567}
568
569/*
570 * Routines to get and put packets
571 */
572
573/* scan for the sequence $<data>#<checksum> */
574
575unsigned char *getpacket (void)
576{
577 unsigned char *buffer = &remcomInBuffer[0];
578 unsigned char checksum;
579 unsigned char xmitcsum;
580 int count;
581 char ch;
582
583 while (1)
584 {
585 /* wait around for the start character, ignore all other characters */
586 while ((ch = serial_getc ()) != '$')
587 ;
588
589 retry:
590 checksum = 0;
591 xmitcsum = -1;
592 count = 0;
593
594 /* now, read until a # or end of buffer is found */
595 while (count < BUFMAX)
596 {
597 ch = serial_getc ();
598 if (ch == '$')
599 goto retry;
600 if (ch == '#')
601 break;
602 checksum = checksum + ch;
603 buffer[count] = ch;
604 count = count + 1;
605 }
606 buffer[count] = 0;
607
608 if (ch == '#')
609 {
610 ch = serial_getc ();
611 xmitcsum = hex (ch) << 4;
612 ch = serial_getc ();
613 xmitcsum += hex (ch);
614
615 if (checksum != xmitcsum)
616 {
617 serial_putc ('-'); /* failed checksum */
618 }
619 else
620 {
621 serial_putc ('+'); /* successful transfer */
622
623 /* if a sequence char is present, reply the sequence ID */
624 if (buffer[2] == ':')
625 {
626 serial_putc (buffer[0]);
627 serial_putc (buffer[1]);
628
629 return &buffer[3];
630 }
631
632 return &buffer[0];
633 }
634 }
635 }
636}
637
638
639/* send the packet in buffer. */
640
641static void putpacket (register char *buffer)
642{
643 register int checksum;
644
645 /* $<packet info>#<checksum>. */
646 do
647 {
648 char *src = buffer;
649 serial_putc ('$');
650 checksum = 0;
651
652 while (*src)
653 {
654 int runlen;
655
656 /* Do run length encoding */
657 for (runlen = 0; runlen < 100; runlen ++)
658 {
659 if (src[0] != src[runlen])
660 {
661 if (runlen > 3)
662 {
663 int encode;
664 /* Got a useful amount */
665 serial_putc (*src);
666 checksum += *src;
667 serial_putc ('*');
668 checksum += '*';
669 checksum += (encode = runlen + ' ' - 4);
670 serial_putc (encode);
671 src += runlen;
672 }
673 else
674 {
675 serial_putc (*src);
676 checksum += *src;
677 src++;
678 }
679 break;
680 }
681 }
682 }
683
684
685 serial_putc ('#');
686 serial_putc (highhex(checksum));
687 serial_putc (lowhex(checksum));
688 }
689 while (serial_getc() != '+');
690}
691
692
693/* a bus error has occurred, perform a longjmp
694 to return execution and allow handling of the error */
695
696void handle_buserror (void)
697{
698 longjmp (remcomEnv, 1);
699}
700
Linus Nielsen Feltzing1dc42d12003-05-17 00:31:50 +0000701#define SIGINT 2 /* interrupt */
702#define SIGILL 4 /* illegal instruction (not reset when caught) */
703#define SIGTRAP 5 /* trace trap (not reset when caught) */
704#define SIGEMT 7 /* EMT instruction */
705#define SIGBUS 10 /* bus error */
706
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000707/*
708 * this function takes the SH-1 exception number and attempts to
709 * translate this number into a unix compatible signal value
710 */
711static int computeSignal (int exceptionVector)
712{
713 int sigval;
714 switch (exceptionVector)
715 {
716 case INVALID_INSN_VEC:
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000717 sigval = SIGILL;
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000718 break;
719 case INVALID_SLOT_VEC:
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000720 sigval = SIGILL;
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000721 break;
722 case CPU_BUS_ERROR_VEC:
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000723 sigval = SIGBUS;
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000724 break;
725 case DMA_BUS_ERROR_VEC:
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000726 sigval = SIGBUS;
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000727 break;
728 case NMI_VEC:
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000729 sigval = SIGINT;
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000730 break;
731
732 case TRAP_VEC:
733 case USER_VEC:
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000734 sigval = SIGTRAP;
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000735 break;
736
737 default:
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000738 sigval = SIGEMT; /* "software generated"*/
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000739 break;
740 }
741 return (sigval);
742}
743
744void doSStep (void)
745{
746 short *instrMem;
747 int displacement;
748 int reg;
749 unsigned short opcode;
750
751 instrMem = (short *) registers[PC];
752
753 opcode = *instrMem;
754 stepped = 1;
755
756 if ((opcode & COND_BR_MASK) == BT_INSTR)
757 {
758 if (registers[SR] & T_BIT_MASK)
759 {
760 displacement = (opcode & COND_DISP) << 1;
761 if (displacement & 0x80)
762 displacement |= 0xffffff00;
763 /*
764 * Remember PC points to second instr.
765 * after PC of branch ... so add 4
766 */
767 instrMem = (short *) (registers[PC] + displacement + 4);
768 }
769 else
770 instrMem += 1;
771 }
772 else if ((opcode & COND_BR_MASK) == BF_INSTR)
773 {
774 if (registers[SR] & T_BIT_MASK)
775 instrMem += 1;
776 else
777 {
778 displacement = (opcode & COND_DISP) << 1;
779 if (displacement & 0x80)
780 displacement |= 0xffffff00;
781 /*
782 * Remember PC points to second instr.
783 * after PC of branch ... so add 4
784 */
785 instrMem = (short *) (registers[PC] + displacement + 4);
786 }
787 }
788 else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR)
789 {
790 displacement = (opcode & UCOND_DISP) << 1;
791 if (displacement & 0x0800)
792 displacement |= 0xfffff000;
793
794 /*
795 * Remember PC points to second instr.
796 * after PC of branch ... so add 4
797 */
798 instrMem = (short *) (registers[PC] + displacement + 4);
799 }
800 else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR)
801 {
802 reg = (char) ((opcode & UCOND_REG) >> 8);
803
804 instrMem = (short *) registers[reg];
805 }
806 else if (opcode == RTS_INSTR)
807 instrMem = (short *) registers[PR];
808 else if (opcode == RTE_INSTR)
809 instrMem = (short *) registers[15];
810 else if ((opcode & TRAPA_MASK) == TRAPA_INSTR)
811 instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2);
812 else
813 instrMem += 1;
814
815 instrBuffer.memAddr = instrMem;
816 instrBuffer.oldInstr = *instrMem;
817 *instrMem = SSTEP_INSTR;
818}
819
820
821/* Undo the effect of a previous doSStep. If we single stepped,
822 restore the old instruction. */
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000823void undoSStep (void)
824{
825 if (stepped)
826 {
827 short *instrMem;
828 instrMem = instrBuffer.memAddr;
829 *instrMem = instrBuffer.oldInstr;
830 }
831 stepped = 0;
832}
833
834/*
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000835 * This function does all exception handling. It only does two things -
836 * it figures out why it was called and tells gdb, and then it reacts
837 * to gdb's requests.
838 *
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000839*/
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000840void gdb_handle_exception (int exceptionVector)
841{
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000842 int sigval, stepping;
843 int addr, length;
844 char *ptr;
845
846 /* reply to host that an exception has occurred */
847 sigval = computeSignal (exceptionVector);
848 remcomOutBuffer[0] = 'S';
849 remcomOutBuffer[1] = highhex(sigval);
850 remcomOutBuffer[2] = lowhex (sigval);
851 remcomOutBuffer[3] = 0;
852
853 putpacket (remcomOutBuffer);
854
855 /*
856 * exception 127 indicates a software trap
857 * inserted in place of code ... so back up
858 * PC by one instruction, since this instruction
859 * will later be replaced by its original one!
860 */
861 if (exceptionVector == USER_VEC
862 || exceptionVector == TRAP_VEC)
863 registers[PC] -= 2;
864
865 /*
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000866 * Do the things needed to undo
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000867 * any stepping we may have done!
868 */
869 undoSStep ();
870
871 stepping = 0;
872
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000873 while (1)
874 {
875 remcomOutBuffer[0] = 0;
876 ptr = getpacket ();
877
878 switch (*ptr++)
879 {
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000880 case '?':
881 remcomOutBuffer[0] = 'S';
882 remcomOutBuffer[1] = highhex (sigval);
883 remcomOutBuffer[2] = lowhex (sigval);
884 remcomOutBuffer[3] = 0;
885 break;
886 case 'd':
887 remote_debug = !(remote_debug); /* toggle debug flag */
888 break;
889 case 'g': /* return the value of the CPU registers */
890 mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES);
891 break;
892 case 'G': /* set the value of the CPU registers - return OK */
893 hex2mem (ptr, (char *) registers, NUMREGBYTES);
894 strcpy (remcomOutBuffer, "OK");
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000895 break;
896
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000897 /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
898 case 'm':
899 if (setjmp (remcomEnv) == 0)
900 {
901 dofault = 0;
902 /* TRY, TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
903 if (hex2int (&ptr, &addr))
904 if (*(ptr++) == ',')
905 if (hex2int (&ptr, &length))
906 {
907 ptr = 0;
908 mem2hex ((char *) addr, remcomOutBuffer, length);
909 }
910 if (ptr)
911 strcpy (remcomOutBuffer, "E01");
912 }
913 else
914 strcpy (remcomOutBuffer, "E03");
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000915
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +0000916 /* restore handler for bus error */
917 dofault = 1;
918 break;
919
920 /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
921 case 'M':
922 if (setjmp (remcomEnv) == 0)
923 {
924 dofault = 0;
925
926 /* TRY, TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
927 if (hex2int (&ptr, &addr))
928 if (*(ptr++) == ',')
929 if (hex2int (&ptr, &length))
930 if (*(ptr++) == ':')
931 {
932 hex2mem (ptr, (char *) addr, length);
933 ptr = 0;
934 strcpy (remcomOutBuffer, "OK");
935 }
936 if (ptr)
937 strcpy (remcomOutBuffer, "E02");
938 }
939 else
940 strcpy (remcomOutBuffer, "E03");
941
942 /* restore handler for bus error */
943 dofault = 1;
944 break;
945
946 /* cAA..AA Continue at address AA..AA(optional) */
947 /* sAA..AA Step one instruction from AA..AA(optional) */
948 case 's':
949 stepping = 1;
950 case 'c':
951 {
952 /* tRY, to read optional parameter, pc unchanged if no parm */
953 if (hex2int (&ptr, &addr))
954 registers[PC] = addr;
955
956 if (stepping)
957 doSStep ();
958 }
959
960 return;
961 break;
962
963 /* kill the program */
964 case 'k': /* do nothing */
965 break;
966
967 default:
968 break;
969 } /* switch */
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000970
971 /* reply to the request */
972 putpacket (remcomOutBuffer);
973 }
974}
975
976
977/* We've had an exception - go into the gdb stub */
978void handle_exception(int exceptionVector)
979{
980 gdb_handle_exception (exceptionVector);
981}
982
983/* This function will generate a breakpoint exception. It is used at the
984 beginning of a program to sync up with a debugger and can be used
985 otherwise as a quick means to stop program execution and "break" into
986 the debugger. */
987void breakpoint (void)
988{
989 BREAKPOINT ();
990}
991
992/**** Processor-specific routines start here ****/
993/**** Processor-specific routines start here ****/
994/**** Processor-specific routines start here ****/
995
Linus Nielsen Feltzing8ee52132002-04-23 21:59:20 +0000996extern int stack[];
997
Björn Stenbergd42d78f2002-04-15 08:35:08 +0000998/* SH1/SH2 exception vector table format */
999typedef struct
1000{
Linus Nielsen Feltzing88c398a2002-04-23 20:33:45 +00001001 void (*func_cold) (void);
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001002 int *stack_cold;
Linus Nielsen Feltzing88c398a2002-04-23 20:33:45 +00001003 void (*func_warm) (void);
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001004 int *stack_warm;
Linus Nielsen Feltzing88c398a2002-04-23 20:33:45 +00001005 void (*(handler[128 - 4])) (void);
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001006} vec_type;
1007
1008/* vectable is the SH1/SH2 vector table. It must be at address 0
1009** or wherever your vbr points.
1010** Note that we only define the first 128 vectors, since the Jukebox
1011** firmware has its entry point at 0x200
1012*/
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001013const vec_type vectable __attribute__ ((section (".vectors"))) =
1014{
1015 &start, /* 0: Power-on reset PC */
Linus Nielsen Feltzing8ee52132002-04-23 21:59:20 +00001016 stack, /* 1: Power-on reset SP */
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001017 &start, /* 2: Manual reset PC */
Linus Nielsen Feltzing8ee52132002-04-23 21:59:20 +00001018 stack, /* 3: Manual reset SP */
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001019 {
1020 &catch_exception_4, /* 4: General invalid instruction */
1021 &catch_exception_5, /* 5: Reserved for system */
1022 &catch_exception_6, /* 6: Invalid slot instruction */
1023 &catch_exception_7, /* 7: Reserved for system */
1024 &catch_exception_8, /* 8: Reserved for system */
1025 &catch_exception_9, /* 9: CPU bus error */
1026 &catch_exception_10, /* 10: DMA bus error */
1027 &catch_exception_11, /* 11: NMI */
1028 &catch_exception_12, /* 12: User break */
1029 &catch_exception_13, /* 13: Reserved for system */
1030 &catch_exception_14, /* 14: Reserved for system */
1031 &catch_exception_15, /* 15: Reserved for system */
1032 &catch_exception_16, /* 16: Reserved for system */
1033 &catch_exception_17, /* 17: Reserved for system */
1034 &catch_exception_18, /* 18: Reserved for system */
1035 &catch_exception_19, /* 19: Reserved for system */
1036 &catch_exception_20, /* 20: Reserved for system */
1037 &catch_exception_21, /* 21: Reserved for system */
1038 &catch_exception_22, /* 22: Reserved for system */
1039 &catch_exception_23, /* 23: Reserved for system */
1040 &catch_exception_24, /* 24: Reserved for system */
1041 &catch_exception_25, /* 25: Reserved for system */
1042 &catch_exception_26, /* 26: Reserved for system */
1043 &catch_exception_27, /* 27: Reserved for system */
1044 &catch_exception_28, /* 28: Reserved for system */
1045 &catch_exception_29, /* 29: Reserved for system */
1046 &catch_exception_30, /* 30: Reserved for system */
1047 &catch_exception_31, /* 31: Reserved for system */
1048 &catch_exception_32, /* 32: Trap instr (user vectors) */
1049 &catch_exception_33, /* 33: Trap instr (user vectors) */
1050 &catch_exception_34, /* 34: Trap instr (user vectors) */
1051 &catch_exception_35, /* 35: Trap instr (user vectors) */
1052 &catch_exception_36, /* 36: Trap instr (user vectors) */
1053 &catch_exception_37, /* 37: Trap instr (user vectors) */
1054 &catch_exception_38, /* 38: Trap instr (user vectors) */
1055 &catch_exception_39, /* 39: Trap instr (user vectors) */
1056 &catch_exception_40, /* 40: Trap instr (user vectors) */
1057 &catch_exception_41, /* 41: Trap instr (user vectors) */
1058 &catch_exception_42, /* 42: Trap instr (user vectors) */
1059 &catch_exception_43, /* 43: Trap instr (user vectors) */
1060 &catch_exception_44, /* 44: Trap instr (user vectors) */
1061 &catch_exception_45, /* 45: Trap instr (user vectors) */
1062 &catch_exception_46, /* 46: Trap instr (user vectors) */
1063 &catch_exception_47, /* 47: Trap instr (user vectors) */
1064 &catch_exception_48, /* 48: Trap instr (user vectors) */
1065 &catch_exception_49, /* 49: Trap instr (user vectors) */
1066 &catch_exception_50, /* 50: Trap instr (user vectors) */
1067 &catch_exception_51, /* 51: Trap instr (user vectors) */
1068 &catch_exception_52, /* 52: Trap instr (user vectors) */
1069 &catch_exception_53, /* 53: Trap instr (user vectors) */
1070 &catch_exception_54, /* 54: Trap instr (user vectors) */
1071 &catch_exception_55, /* 55: Trap instr (user vectors) */
1072 &catch_exception_56, /* 56: Trap instr (user vectors) */
1073 &catch_exception_57, /* 57: Trap instr (user vectors) */
1074 &catch_exception_58, /* 58: Trap instr (user vectors) */
1075 &catch_exception_59, /* 59: Trap instr (user vectors) */
1076 &catch_exception_60, /* 60: Trap instr (user vectors) */
1077 &catch_exception_61, /* 61: Trap instr (user vectors) */
1078 &catch_exception_62, /* 62: Trap instr (user vectors) */
1079 &catch_exception_63, /* 63: Trap instr (user vectors) */
1080 &catch_exception_64, /* 64: IRQ0 */
1081 &catch_exception_65, /* 65: IRQ1 */
1082 &catch_exception_66, /* 66: IRQ2 */
1083 &catch_exception_67, /* 67: IRQ3 */
1084 &catch_exception_68, /* 68: IRQ4 */
1085 &catch_exception_69, /* 69: IRQ5 */
1086 &catch_exception_70, /* 70: IRQ6 */
1087 &catch_exception_71, /* 71: IRQ7 */
1088 &catch_exception_72,
1089 &catch_exception_73,
1090 &catch_exception_74,
1091 &catch_exception_75,
1092 &catch_exception_76,
1093 &catch_exception_77,
1094 &catch_exception_78,
1095 &catch_exception_79,
1096 &catch_exception_80,
1097 &catch_exception_81,
1098 &catch_exception_82,
1099 &catch_exception_83,
1100 &catch_exception_84,
1101 &catch_exception_85,
1102 &catch_exception_86,
1103 &catch_exception_87,
1104 &catch_exception_88,
1105 &catch_exception_89,
1106 &catch_exception_90,
1107 &catch_exception_91,
1108 &catch_exception_92,
1109 &catch_exception_93,
1110 &catch_exception_94,
1111 &catch_exception_95,
1112 &catch_exception_96,
1113 &catch_exception_97,
1114 &catch_exception_98,
1115 &catch_exception_99,
1116 &catch_exception_100,
1117 &catch_exception_101,
1118 &catch_exception_102,
1119 &catch_exception_103,
1120 &catch_exception_104,
1121 &catch_exception_105,
1122 &catch_exception_106,
1123 &catch_exception_107,
1124 &catch_exception_108,
1125 &catch_exception_109,
1126 &catch_exception_110,
1127 &catch_exception_111,
1128 &catch_exception_112,
1129 &catch_exception_113,
1130 &catch_exception_114,
1131 &catch_exception_115,
1132 &catch_exception_116,
1133 &catch_exception_117,
1134 &catch_exception_118,
1135 &catch_exception_119,
1136 &catch_exception_120,
1137 &catch_exception_121,
1138 &catch_exception_122,
1139 &catch_exception_123,
1140 &catch_exception_124,
1141 &catch_exception_125,
1142 &catch_exception_126,
1143 &catch_exception_127}};
1144
1145void INIT (void)
1146{
1147 /* Disable all timer interrupts */
1148 TIER0 = 0;
1149 TIER1 = 0;
1150 TIER2 = 0;
1151 TIER3 = 0;
1152 TIER4 = 0;
1153
1154 init_serial();
1155
1156 in_nmi = 0;
1157 dofault = 1;
1158 stepped = 0;
1159
Linus Nielsen Feltzing7958ea42002-05-11 20:04:48 +00001160 ata_spindown(-1);
1161
Linus Nielsen Feltzing8ee52132002-04-23 21:59:20 +00001162 stub_sp = stub_stack;
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001163 breakpoint ();
1164
1165 /* We should never come here */
1166 blink();
1167}
1168
Linus Nielsen Feltzing88c398a2002-04-23 20:33:45 +00001169void sr(void)
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001170{
1171 /* Calling Reset does the same as pressing the button */
1172 asm (".global _Reset\n"
1173 " .global _WarmReset\n"
1174 "_Reset:\n"
1175 "_WarmReset:\n"
1176 " mov.l L_sp,r15\n"
1177 " bra _INIT\n"
1178 " nop\n"
1179 " .align 2\n"
Linus Nielsen Feltzing8ee52132002-04-23 21:59:20 +00001180 "L_sp: .long _stack");
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001181
1182 asm("saveRegisters:\n");
1183 asm(" mov.l @(L_reg, pc), r0\n"
1184 " mov.l @r15+, r1 ! pop R0\n"
1185 " mov.l r2, @(0x08, r0) ! save R2\n"
1186 " mov.l r1, @r0 ! save R0\n"
1187 " mov.l @r15+, r1 ! pop R1\n"
1188 " mov.l r3, @(0x0c, r0) ! save R3\n"
1189 " mov.l r1, @(0x04, r0) ! save R1\n"
1190 " mov.l r4, @(0x10, r0) ! save R4\n"
1191 " mov.l r5, @(0x14, r0) ! save R5\n"
1192 " mov.l r6, @(0x18, r0) ! save R6\n"
1193 " mov.l r7, @(0x1c, r0) ! save R7\n"
1194 " mov.l r8, @(0x20, r0) ! save R8\n"
1195 " mov.l r9, @(0x24, r0) ! save R9\n"
1196 " mov.l r10, @(0x28, r0) ! save R10\n"
1197 " mov.l r11, @(0x2c, r0) ! save R11\n"
1198 " mov.l r12, @(0x30, r0) ! save R12\n"
1199 " mov.l r13, @(0x34, r0) ! save R13\n"
1200 " mov.l r14, @(0x38, r0) ! save R14\n"
1201 " mov.l @r15+, r4 ! save arg to handleException\n"
1202 " add #8, r15 ! hide PC/SR values on stack\n"
1203 " mov.l r15, @(0x3c, r0) ! save R15\n"
1204 " add #-8, r15 ! save still needs old SP value\n"
1205 " add #92, r0 ! readjust register pointer\n"
1206 " mov r15, r2\n"
1207 " add #4, r2\n"
1208 " mov.l @r2, r2 ! R2 has SR\n"
1209 " mov.l @r15, r1 ! R1 has PC\n"
1210 " mov.l r2, @-r0 ! save SR\n"
1211 " sts.l macl, @-r0 ! save MACL\n"
1212 " sts.l mach, @-r0 ! save MACH\n"
1213 " stc.l vbr, @-r0 ! save VBR\n"
1214 " stc.l gbr, @-r0 ! save GBR\n"
1215 " sts.l pr, @-r0 ! save PR\n"
1216 " mov.l @(L_stubstack, pc), r2\n"
1217 " mov.l @(L_hdl_except, pc), r3\n"
1218 " mov.l @r2, r15\n"
1219 " jsr @r3\n"
1220 " mov.l r1, @-r0 ! save PC\n"
1221 " mov.l @(L_stubstack, pc), r0\n"
1222 " mov.l @(L_reg, pc), r1\n"
1223 " bra restoreRegisters\n"
1224 " mov.l r15, @r0 ! save __stub_stack\n"
1225
1226 " .align 2\n"
1227 "L_reg:\n"
1228 " .long _registers\n"
1229 "L_stubstack:\n"
1230 " .long _stub_sp\n"
1231 "L_hdl_except:\n"
1232 " .long _handle_exception");
1233}
1234
Linus Nielsen Feltzing88c398a2002-04-23 20:33:45 +00001235void rr(void)
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001236{
1237 asm(" .align 2 \n"
1238 " .global _resume\n"
1239 "_resume:\n"
1240 " mov r4,r1\n"
1241 "restoreRegisters:\n"
1242 " add #8, r1 ! skip to R2\n"
1243 " mov.l @r1+, r2 ! restore R2\n"
1244 " mov.l @r1+, r3 ! restore R3\n"
1245 " mov.l @r1+, r4 ! restore R4\n"
1246 " mov.l @r1+, r5 ! restore R5\n"
1247 " mov.l @r1+, r6 ! restore R6\n"
1248 " mov.l @r1+, r7 ! restore R7\n"
1249 " mov.l @r1+, r8 ! restore R8\n"
1250 " mov.l @r1+, r9 ! restore R9\n"
1251 " mov.l @r1+, r10 ! restore R10\n"
1252 " mov.l @r1+, r11 ! restore R11\n"
1253 " mov.l @r1+, r12 ! restore R12\n"
1254 " mov.l @r1+, r13 ! restore R13\n"
1255 " mov.l @r1+, r14 ! restore R14\n"
1256 " mov.l @r1+, r15 ! restore programs stack\n"
1257 " mov.l @r1+, r0\n"
1258 " add #-8, r15 ! uncover PC/SR on stack \n"
1259 " mov.l r0, @r15 ! restore PC onto stack\n"
1260 " lds.l @r1+, pr ! restore PR\n"
1261 " ldc.l @r1+, gbr ! restore GBR\n"
1262 " ldc.l @r1+, vbr ! restore VBR\n"
1263 " lds.l @r1+, mach ! restore MACH\n"
1264 " lds.l @r1+, macl ! restore MACL\n"
1265 " mov.l @r1, r0 \n"
1266 " add #-88, r1 ! readjust reg pointer to R1\n"
1267 " mov.l r0, @(4, r15) ! restore SR onto stack+4\n"
1268 " mov.l r2, @-r15\n"
1269 " mov.l L_in_nmi, r0\n"
1270 " mov #0, r2\n"
1271 " mov.b r2, @r0\n"
1272 " mov.l @r15+, r2\n"
1273 " mov.l @r1+, r0 ! restore R0\n"
1274 " rte\n"
1275 " mov.l @r1, r1 ! restore R1");
1276}
1277
Linus Nielsen Feltzingf9389fe2002-04-23 20:21:31 +00001278static inline void code_for_catch_exception(unsigned int n)
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001279{
1280 asm(" .globl _catch_exception_%O0" : : "X" (n) );
1281 asm(" _catch_exception_%O0:" :: "X" (n) );
1282
1283 asm(" add #-4, r15 ! reserve spot on stack ");
1284 asm(" mov.l r1, @-r15 ! push R1 ");
1285
1286 if (n == NMI_VEC)
1287 {
1288 /* Special case for NMI - make sure that they don't nest */
1289 asm(" mov.l r0, @-r15 ! push R0");
1290 asm(" mov.l L_in_nmi, r0");
1291 asm(" tas.b @r0 ! Fend off against addtnl NMIs");
1292 asm(" bt noNMI");
1293 asm(" mov.l @r15+, r0");
1294 asm(" mov.l @r15+, r1");
1295 asm(" add #4, r15");
1296 asm(" rte");
1297 asm(" nop");
1298 asm(".align 2");
1299 asm("L_in_nmi: .long _in_nmi");
1300 asm("noNMI:");
1301 }
1302 else
1303 {
1304
1305 if (n == CPU_BUS_ERROR_VEC)
1306 {
1307 /* Exception 9 (bus errors) are disasbleable - so that you
1308 can probe memory and get zero instead of a fault.
1309 Because the vector table may be in ROM we don't revector
1310 the interrupt like all the other stubs, we check in here
1311 */
1312 asm("mov.l L_dofault,r1");
1313 asm("mov.l @r1,r1");
1314 asm("tst r1,r1");
1315 asm("bf faultaway");
1316 asm("bsr _handle_buserror");
1317 asm(".align 2");
1318 asm("L_dofault: .long _dofault");
1319 asm("faultaway:");
1320 }
1321 asm(" mov #15<<4, r1 ");
1322 asm(" ldc r1, sr ! disable interrupts ");
1323 asm(" mov.l r0, @-r15 ! push R0 ");
1324 }
1325
1326 /* Prepare for saving context, we've already pushed r0 and r1, stick
1327 exception number into the frame */
1328 asm(" mov r15, r0 ");
1329 asm(" add #8, r0 ");
1330 asm(" mov %0,r1" :: "X" (n));
1331 asm(" extu.b r1,r1 ");
1332 asm(" bra saveRegisters ! save register values ");
1333 asm(" mov.l r1, @r0 ! save exception # ");
1334}
1335
1336/* Here we call all defined exceptions, so the inline assembler gets
1337 generated */
1338void exceptions (void)
1339{
1340 code_for_catch_exception (4);
1341 code_for_catch_exception (5);
1342 code_for_catch_exception (6);
1343 code_for_catch_exception (7);
1344 code_for_catch_exception (8);
1345 code_for_catch_exception (9);
1346 code_for_catch_exception (10);
1347 code_for_catch_exception (11);
1348 code_for_catch_exception (12);
1349 code_for_catch_exception (13);
1350 code_for_catch_exception (14);
1351 code_for_catch_exception (15);
1352 code_for_catch_exception (16);
1353 code_for_catch_exception (17);
1354 code_for_catch_exception (18);
1355 code_for_catch_exception (19);
1356 code_for_catch_exception (20);
1357 code_for_catch_exception (21);
1358 code_for_catch_exception (22);
1359 code_for_catch_exception (23);
1360 code_for_catch_exception (24);
1361 code_for_catch_exception (25);
1362 code_for_catch_exception (26);
1363 code_for_catch_exception (27);
1364 code_for_catch_exception (28);
1365 code_for_catch_exception (29);
1366 code_for_catch_exception (30);
1367 code_for_catch_exception (31);
1368 code_for_catch_exception (32);
1369 code_for_catch_exception (33);
1370 code_for_catch_exception (34);
1371 code_for_catch_exception (35);
1372 code_for_catch_exception (36);
1373 code_for_catch_exception (37);
1374 code_for_catch_exception (38);
1375 code_for_catch_exception (39);
1376 code_for_catch_exception (40);
1377 code_for_catch_exception (41);
1378 code_for_catch_exception (42);
1379 code_for_catch_exception (43);
1380 code_for_catch_exception (44);
1381 code_for_catch_exception (45);
1382 code_for_catch_exception (46);
1383 code_for_catch_exception (47);
1384 code_for_catch_exception (48);
1385 code_for_catch_exception (49);
1386 code_for_catch_exception (50);
1387 code_for_catch_exception (51);
1388 code_for_catch_exception (52);
1389 code_for_catch_exception (53);
1390 code_for_catch_exception (54);
1391 code_for_catch_exception (55);
1392 code_for_catch_exception (56);
1393 code_for_catch_exception (57);
1394 code_for_catch_exception (58);
1395 code_for_catch_exception (59);
1396 code_for_catch_exception (60);
1397 code_for_catch_exception (61);
1398 code_for_catch_exception (62);
1399 code_for_catch_exception (63);
1400 code_for_catch_exception (64);
1401 code_for_catch_exception (65);
1402 code_for_catch_exception (66);
1403 code_for_catch_exception (67);
1404 code_for_catch_exception (68);
1405 code_for_catch_exception (69);
1406 code_for_catch_exception (70);
1407 code_for_catch_exception (71);
1408 code_for_catch_exception (72);
1409 code_for_catch_exception (73);
1410 code_for_catch_exception (74);
1411 code_for_catch_exception (75);
1412 code_for_catch_exception (76);
1413 code_for_catch_exception (77);
1414 code_for_catch_exception (78);
1415 code_for_catch_exception (79);
1416 code_for_catch_exception (80);
1417 code_for_catch_exception (81);
1418 code_for_catch_exception (82);
1419 code_for_catch_exception (83);
1420 code_for_catch_exception (84);
1421 code_for_catch_exception (85);
1422 code_for_catch_exception (86);
1423 code_for_catch_exception (87);
1424 code_for_catch_exception (88);
1425 code_for_catch_exception (89);
1426 code_for_catch_exception (90);
1427 code_for_catch_exception (91);
1428 code_for_catch_exception (92);
1429 code_for_catch_exception (93);
1430 code_for_catch_exception (94);
1431 code_for_catch_exception (95);
1432 code_for_catch_exception (96);
1433 code_for_catch_exception (97);
1434 code_for_catch_exception (98);
1435 code_for_catch_exception (99);
1436 code_for_catch_exception (100);
1437 code_for_catch_exception (101);
1438 code_for_catch_exception (102);
1439 code_for_catch_exception (103);
1440 code_for_catch_exception (104);
1441 code_for_catch_exception (105);
1442 code_for_catch_exception (106);
1443 code_for_catch_exception (107);
1444 code_for_catch_exception (108);
1445 code_for_catch_exception (109);
1446 code_for_catch_exception (110);
1447 code_for_catch_exception (111);
1448 code_for_catch_exception (112);
1449 code_for_catch_exception (113);
1450 code_for_catch_exception (114);
1451 code_for_catch_exception (115);
1452 code_for_catch_exception (116);
1453 code_for_catch_exception (117);
1454 code_for_catch_exception (118);
1455 code_for_catch_exception (119);
1456 code_for_catch_exception (120);
1457 code_for_catch_exception (121);
1458 code_for_catch_exception (122);
1459 code_for_catch_exception (123);
1460 code_for_catch_exception (124);
1461 code_for_catch_exception (125);
1462 code_for_catch_exception (126);
1463 code_for_catch_exception (127);
1464}
1465
1466/*
1467 * Port B Control Register (PBCR1)
1468 */
1469#define PB15MD1 0x8000
1470#define PB15MD0 0x4000
1471#define PB14MD1 0x2000
1472#define PB14MD0 0x1000
1473#define PB13MD1 0x0800
1474#define PB13MD0 0x0400
1475#define PB12MD1 0x0200
1476#define PB12MD0 0x0100
1477#define PB11MD1 0x0080
1478#define PB11MD0 0x0040
1479#define PB10MD1 0x0020
1480#define PB10MD0 0x0010
1481#define PB9MD1 0x0008
1482#define PB9MD0 0x0004
1483#define PB8MD1 0x0002
1484#define PB8MD0 0x0001
1485
1486#define PB15MD PB15MD1|PB14MD0
1487#define PB14MD PB14MD1|PB14MD0
1488#define PB13MD PB13MD1|PB13MD0
1489#define PB12MD PB12MD1|PB12MD0
1490#define PB11MD PB11MD1|PB11MD0
1491#define PB10MD PB10MD1|PB10MD0
1492#define PB9MD PB9MD1|PB9MD0
1493#define PB8MD PB8MD1|PB8MD0
1494
1495#define PB_TXD1 PB11MD1
1496#define PB_RXD1 PB10MD1
1497#define PB_TXD0 PB9MD1
1498#define PB_RXD0 PB8MD1
1499
1500#define PB7MD PB7MD1|PB7MD0
1501#define PB6MD PB6MD1|PB6MD0
1502#define PB5MD PB5MD1|PB5MD0
1503#define PB4MD PB4MD1|PB4MD0
1504#define PB3MD PB3MD1|PB3MD0
1505#define PB2MD PB2MD1|PB2MD0
1506#define PB1MD PB1MD1|PB1MD0
1507#define PB0MD PB0MD1|PB0MD0
1508
1509
1510void handleError (char theSSR);
1511
1512void nop (void)
1513{
1514}
1515
1516void init_serial (void)
1517{
1518 int i;
1519
1520 /* Clear Channel 1's SCR */
1521 SCR1 = 0;
1522
1523 /* Set communication to be async, 8-bit data,
1524 no parity, 1 stop bit and use internal clock */
1525 SMR1 = 0;
Linus Nielsen Feltzing1dc42d12003-05-17 00:31:50 +00001526
1527#ifdef RECORDER
1528 #warning 115200
1529 BRR1 = 2; /* 115200 */
1530#else
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001531 BRR1 = 9; /* 38400 */
Linus Nielsen Feltzing1dc42d12003-05-17 00:31:50 +00001532#endif
Björn Stenbergd42d78f2002-04-15 08:35:08 +00001533
1534 SCR1 &= ~(SCI_CKE1 | SCI_CKE0);
1535
1536 /* let the hardware settle */
1537 for (i = 0; i < 1000; i++)
1538 nop ();
1539
1540 /* Turn on in and out */
1541 SCR1 |= SCI_RE | SCI_TE;
1542
1543 /* Set the PFC to make RXD1 (pin PB8) an input pin
1544 and TXD1 (pin PB9) an output pin */
1545 PBCR1 &= ~(PB_TXD1 | PB_RXD1);
1546 PBCR1 |= PB_TXD1 | PB_RXD1;
1547}
1548
1549
1550int serial_waitc(void)
1551{
1552 char mySSR;
1553 mySSR = SSR1 & ( SCI_PER | SCI_FER | SCI_ORER );
1554 if ( mySSR )
1555 handleError ( mySSR );
1556 return SSR1 & SCI_RDRF ;
1557}
1558
1559char serial_getc (void)
1560{
1561 char ch;
1562 char mySSR;
1563
1564 while ( ! serial_waitc())
1565 ;
1566
1567 ch = RDR1;
1568 SSR1 &= ~SCI_RDRF;
1569
1570 mySSR = SSR1 & (SCI_PER | SCI_FER | SCI_ORER);
1571
1572 if (mySSR)
1573 handleError (mySSR);
1574
1575 return ch;
1576}
1577
1578void serial_putc (char ch)
1579{
1580 while (!(SSR1 & SCI_TDRE))
1581 {
1582 ;
1583 }
1584
1585 /*
1586 * Write data into TDR and clear TDRE
1587 */
1588 TDR1 = ch;
1589 SSR1 &= ~SCI_TDRE;
1590}
1591
1592void handleError (char theSSR)
1593{
1594 /* Clear all error bits, otherwise the receiver will stop */
1595 SSR1 &= ~(SCI_ORER | SCI_PER | SCI_FER);
1596}
Linus Nielsen Feltzing1dc42d12003-05-17 00:31:50 +00001597
1598void *memcpy(void *dest, const void *src0, size_t n)
1599{
1600 char *dst = (char *) dest;
1601 char *src = (char *) src0;
1602
1603 void *save = dest;
1604
1605 while(n--)
1606 {
1607 *dst++ = *src++;
1608 }
1609
1610 return save;
1611}