/*************************************************************************** ** $Id: sh_stub.c 1.4 1996/04/15 23:21:35 mike Exp $ **************************************************************************** ** Copyright (c) 1995 Hitachi America, Ltd. & Paragon Innovations, Inc. ** All Rights Reserved **************************************************************************** ** $DOCNUM:1078-01-001-8012$ ** Revision History ** ---------------- ** $Log: sh_stub.c $ ** Revision 1.4 1996/04/15 23:21:35 mike ** Updated for SH-1 release ** Revision 1.3 1996/03/06 18:41:04 mike ** Replaced register defines with include for sh_cpu.h ** Moved DRAM/SDRAM register defines to sh_cpu.h ** Added SDRAM initialization and crystal X4 multiplier software ** Changed code_for_catch_exception function/asm macro to work with new ** compiler 'asm' requirements/changes ** Changed default baud rate to 9600 ** Revision 1.2 95/10/11 02:42:22 Kris ** Changed copyright notice ** Revision 1.1 1995/10/04 00:57:07 Kris ** Initial revision ** ** **************************************************************************** ** STUB.C $TITLE:STUB.C SH$ ** ---------- ** debugging stub for the Hitachi-SH. ** ** NOTE!! This code has to be compiled with optimization, otherwise the ** function inlining which generates the exception handlers won't work. ** ** This is originally based on an m68k software stub written by Glenn ** Engel at HP, but has changed quite a bit. ** ** Modifications for the SH originally by Ben Lee and Steve Chamberlain ** ** THIS SOFTWARE IS NOT COPYRIGHTED ** ** HP offers the following for use in the public domain. HP makes no ** warranty with regard to the software or it's performance and the ** user accepts the software "AS IS" with all faults. ** ** HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD ** TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** Remote communication protocol. ** ** A debug packet whose contents are ** is encapsulated for transmission in the form: ** ** $ # CSUM1 CSUM2 ** ** must be ASCII alphanumeric and cannot include characters ** '$' or '#'. If starts with two characters followed by ** ':', then the existing stubs interpret this as a sequence number. ** ** CSUM1 and CSUM2 are ascii hex representation of an 8-bit ** checksum of , the most significant nibble is sent first. ** the hex digits 0-9,a-f are used. ** ** Receiver responds with: ** ** + - if CSUM is correct and ready for next packet ** - - if CSUM is incorrect ** ** is as follows: ** All values are encoded in ascii hex digits. ** ** Request Packet ** ** read registers g ** reply XX....X Each byte of register data ** is described by two hex digits. ** Registers are in the internal order ** for GDB, and the bytes in a register ** are in the same order the machine uses. ** or ENN for an error. ** ** write regs GXX..XX Each byte of register data ** is described by two hex digits. ** reply OK for success ** ENN for an error ** ** write reg Pn...=r... Write register n... with value r..., ** which contains two hex digits for each ** byte in the register (target byte ** order). ** reply OK for success ** ENN for an error ** (not supported by all stubs). ** ** read mem mAA..AA,LLLL AA..AA is address, LLLL is length. ** reply XX..XX XX..XX is mem contents ** Can be fewer bytes than requested ** if able to read only part of the data. ** or ENN NN is errno ** ** write mem MAA..AA,LLLL:XX..XX AA..AA is address, ** LLLL is number of bytes, ** XX..XX is data ** reply OK for success ** ENN for an error (this includes the case ** where only part of the data was ** written). ** ** cont cAA..AA AA..AA is address to resume ** If AA..AA is omitted, ** resume at same address. ** ** step sAA..AA AA..AA is address to resume ** If AA..AA is omitted, ** resume at same address. ** ** last signal ? Reply the current reason for stopping. ** This is the same reply as is generated ** for step or cont : SAA where AA is the ** signal number. ** ** There is no immediate reply to step or cont. ** The reply comes when the machine stops. ** It is SAA AA is the "signal number" ** ** or... TAAn...:r...;n:r...;n...:r...; ** AA = signal number ** n... = register number ** r... = register contents ** or... WAA The process exited, and AA is ** the exit status. This is only ** applicable for certains sorts of ** targets. ** kill request k ** ** toggle debug d toggle debug flag (see 386 & 68k stubs) ** reset r reset -- see sparc stub. ** reserved On other requests, the stub should ** ignore the request and send an empty ** response ($#). This way ** we can extend the protocol and GDB ** can tell whether the stub it is ** talking to uses the old or the new. ** search tAA:PP,MM Search backwards starting at address ** AA for a match with pattern PP and ** mask MM. PP and MM are 4 bytes. ** Not supported by all stubs. ** ** general query qXXXX Request info about XXXX. ** general set QXXXX=yyyy Set value of XXXX to yyyy. ** query sect offs qOffsets Get section offsets. Reply is ** Text=xxx;Data=yyy;Bss=zzz ** console output Otext Send text to stdout. Only comes from ** remote target. ** ** Responses can be run-length encoded to save space. A '*' means that ** the next two characters are hex digits giving a repeat count which ** stands for that many repititions of the character preceding the '*'. ** Note that this means that responses cannot contain '*'. Example: ** "0*03" means the same as "0000". ** ** ****************************************************************************/ /*-------------------------------------------------------------------------- INCLUDES --------------------------------------------------------------------------*/ #include #include #include "sh_cpu.h" /*-------------------------------------------------------------------------- FUNCTION PROTOTYPES --------------------------------------------------------------------------*/ static int hex (char); static char *mem2hex (char *, char *, int); static char *hex2mem (char *, char *, int); static int hexToInt (char **, int *); static void getpacket (char *); static void putpacket (char *); static void handle_buserror (void); static int computeSignal (int exceptionVector); static void handle_exception (int exceptionVector); void init_serial(); void mem_enable_sdram(); void mem_enable_dram(); void vfd_display_bitmap( unsigned char start[][] ); void vfd_clear(); void vfd_init(); void vfd_test_bars(); /* char hw_rx_char (int port);*/ char __inline__ hw_rx_char (const int port); int hw_tx_char (int port, char x); void handleError_P1 (int port, char theSSR); /* These are in the file but in asm statements so the compiler can't see them */ void catch_exception_4 (void); void catch_exception_6 (void); void catch_exception_9 (void); void catch_exception_10 (void); void catch_exception_11 (void); void catch_exception_32 (void); void catch_exception_33 (void); void catch_exception_255 (void); void breakpoint (void); void cold_start (); void cold_start_1 (); /*-------------------------------------------------------------------------- TYPE DEFINITIONS --------------------------------------------------------------------------*/ typedef void (*Function) (); typedef struct { void (*func_cold) (); int *stack_cold; void (*func_warm) (); int *stack_warm; void (*(handler[256 - 4])) (); } vec_type; typedef struct { short *memAddr; short oldInstr; } stepData; /*-------------------------------------------------------------------------- CONSTANT & MACRO DEFINITIONS --------------------------------------------------------------------------*/ #define MOV_MASK 0xf000 #define MOVL_INSN 0xd000 #define MOVW_INSN 0x9000 #define COND_BR_MASK 0xff00 #define UCOND_DBR_MASK 0xe000 #define UCOND_RBR_MASK 0xf0df #define TRAPA_MASK 0xff00 #define COND_DISP 0x00ff #define UCOND_DISP 0x0fff #define UCOND_REG 0x0f00 #define BF_INSTR 0x8b00 #define BT_INSTR 0x8900 #define BRA_INSTR 0xa000 #define BSR_INSTR 0xb000 #define BSR_MASK 0xf000 #define JMP_INSTR 0x402b #define JSR_INSTR 0x400b #define RTS_INSTR 0x000b #define RTE_INSTR 0x002b #define TRAPA_INSTR 0xc300 #define SSTEP_INSTR 0xc3ff #define T_BIT_MASK 0x0001 /* * BUFMAX defines the maximum number of characters in inbound/outbound * buffers at least NUMREGBYTES*2 are needed for register packets */ #define BUFMAX 400 /* Same as value in gdb/remote.c */ /* * Number of bytes for registers */ #define NUMREGBYTES 112 /* 92 */ #define catch_exception_random catch_exception_255 /* Treat all odd ones like 255 */ #define init_stack_size 100 /* if you change this you should also modify BINIT */ #define stub_stack_size 512 /* When you link take care that this is at address 0 - or wherever your vbr points */ #define CPU_BUS_ERROR_VEC 9 #define DMA_BUS_ERROR_VEC 10 #define NMI_VEC 11 #define INVALID_INSN_VEC 4 #define INVALID_SLOT_VEC 6 #define TRAP_VEC 32 #define IO_VEC 33 #define USER_VEC 255 enum regnames { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, PC, PR, GBR, VBR, MACH, MACL, SR, TICKS, STALLS, CYCLES, INSTS, PLR }; #define BREAKPOINT() asm("trapa #0x20"::); #define GDBCOOKIE 0x5ac /* Support for Serial I/O using on chip uart */ #ifdef SH2 #define SMR0 (*(volatile char *)(0xFFFFFE00)) /* Channel 0 serial mode register */ #define BRR0 (*(volatile char *)(0xFFFFFE01)) /* Channel 0 bit rate register */ #define SCR0 (*(volatile char *)(0xFFFFFE02)) /* Channel 0 serial control register */ #define TDR0 (*(volatile char *)(0xFFFFFE03)) /* Channel 0 transmit data register */ #define SSR0 (*(volatile char *)(0xFFFFFE04)) /* Channel 0 serial status register */ #define RDR0 (*(volatile char *)(0xFFFFFE05)) /* Channel 0 receive data register */ #else #define SMR0 (*(volatile char *)(0x05FFFEC0)) /* Channel 0 serial mode register */ #define BRR0 (*(volatile char *)(0x05FFFEC1)) /* Channel 0 bit rate register */ #define SCR0 (*(volatile char *)(0x05FFFEC2)) /* Channel 0 serial control register */ #define TDR0 (*(volatile char *)(0x05FFFEC3)) /* Channel 0 transmit data register */ #define SSR0 (*(volatile char *)(0x05FFFEC4)) /* Channel 0 serial status register */ #define RDR0 (*(volatile char *)(0x05FFFEC5)) /* Channel 0 receive data register */ #define SMR1 (*(volatile char *)(0x05FFFEC8)) /* Channel 1 serial mode register */ #define BRR1 (*(volatile char *)(0x05FFFEC9)) /* Channel 1 bit rate register */ #define SCR1 (*(volatile char *)(0x05FFFECA)) /* Channel 1 serial control register */ #define TDR1 (*(volatile char *)(0x05FFFECB)) /* Channel 1 transmit data register */ #define SSR1 (*(volatile char *)(0x05FFFECC)) /* Channel 1 serial status register */ #define RDR1 (*(volatile char *)(0x05FFFECD)) /* Channel 1 receive data register */ #endif /* * Serial mode register bits */ #define SYNC_MODE 0x80 #define SEVEN_BIT_DATA 0x40 #define PARITY_ON 0x20 #define ODD_PARITY 0x10 #define STOP_BITS_2 0x08 #define ENABLE_MULTIP 0x04 #ifdef SH2 #define PHI_256 0x03 #define PHI_64 0x02 #define PHI_16 0x01 #define PHI_4 0x00 #else #define PHI_64 0x03 #define PHI_16 0x02 #define PHI_4 0x01 #endif /* * Serial control register bits */ #define SCI_TIE 0x80 /* Transmit interrupt enable */ #define SCI_RIE 0x40 /* Receive interrupt enable */ #define SCI_TE 0x20 /* Transmit enable */ #define SCI_RE 0x10 /* Receive enable */ #define SCI_MPIE 0x08 /* Multiprocessor interrupt enable */ #define SCI_TEIE 0x04 /* Transmit end interrupt enable */ #define SCI_CKE1 0x02 /* Clock enable 1 */ #define SCI_CKE0 0x01 /* Clock enable 0 */ /* * Serial status register bits */ #define SCI_TDRE 0x80 /* Transmit data register empty */ #define SCI_RDRF 0x40 /* Receive data register full */ #define SCI_ORER 0x20 /* Overrun error */ #define SCI_FER 0x10 /* Framing error */ #define SCI_PER 0x08 /* Parity error */ #define SCI_TEND 0x04 /* Transmit end */ #define SCI_MPB 0x02 /* Multiprocessor bit */ #define SCI_MPBT 0x01 /* Multiprocessor bit transfer */ #ifndef SH2 /* * Port B IO Register (PBIOR) */ #define PBIOR (*(volatile char *)(0x05FFFFC6)) #define PB15IOR 0x8000 #define PB14IOR 0x4000 #define PB13IOR 0x2000 #define PB12IOR 0x1000 #define PB11IOR 0x0800 #define PB10IOR 0x0400 #define PB9IOR 0x0200 #define PB8IOR 0x0100 #define PB7IOR 0x0080 #define PB6IOR 0x0040 #define PB5IOR 0x0020 #define PB4IOR 0x0010 #define PB3IOR 0x0008 #define PB2IOR 0x0004 #define PB1IOR 0x0002 #define PB0IOR 0x0001 /* * Port B Control Register (PBCR1) */ #define PBCR1 (*(volatile short *)(0x05FFFFCC)) #define PB15MD1 0x8000 #define PB15MD0 0x4000 #define PB14MD1 0x2000 #define PB14MD0 0x1000 #define PB13MD1 0x0800 #define PB13MD0 0x0400 #define PB12MD1 0x0200 #define PB12MD0 0x0100 #define PB11MD1 0x0080 #define PB11MD0 0x0040 #define PB10MD1 0x0020 #define PB10MD0 0x0010 #define PB9MD1 0x0008 #define PB9MD0 0x0004 #define PB8MD1 0x0002 #define PB8MD0 0x0001 #define PB15MD PB15MD1|PB14MD0 #define PB14MD PB14MD1|PB14MD0 #define PB13MD PB13MD1|PB13MD0 #define PB12MD PB12MD1|PB12MD0 #define PB11MD PB11MD1|PB11MD0 #define PB10MD PB10MD1|PB10MD0 #define PB9MD PB9MD1|PB9MD0 #define PB8MD PB8MD1|PB8MD0 #define PB_TXD1 PB11MD1 #define PB_RXD1 PB10MD1 #define PB_TXD0 PB9MD1 #define PB_RXD0 PB8MD1 /* * Port B Control Register (PBCR2) */ #define PBCR2 0x05FFFFCE #define PB7MD1 0x8000 #define PB7MD0 0x4000 #define PB6MD1 0x2000 #define PB6MD0 0x1000 #define PB5MD1 0x0800 #define PB5MD0 0x0400 #define PB4MD1 0x0200 #define PB4MD0 0x0100 #define PB3MD1 0x0080 #define PB3MD0 0x0040 #define PB2MD1 0x0020 #define PB2MD0 0x0010 #define PB1MD1 0x0008 #define PB1MD0 0x0004 #define PB0MD1 0x0002 #define PB0MD0 0x0001 #define PB7MD PB7MD1|PB7MD0 #define PB6MD PB6MD1|PB6MD0 #define PB5MD PB5MD1|PB5MD0 #define PB4MD PB4MD1|PB4MD0 #define PB3MD PB3MD1|PB3MD0 #define PB2MD PB2MD1|PB2MD0 #define PB1MD PB1MD1|PB1MD0 #define PB0MD PB0MD1|PB0MD0 #endif #ifdef MHZ #define BPS 32 * 9600 * MHZ / ( BAUD * 10) #else #define BPS 32 /* 9600 for 10 Mhz */ #endif #ifdef SH2 #define SCR_PORT (SCR0) #define SMR_PORT (SMR0) #define BRR_PORT (BRR0) #define PB_TXD_PORT (PB_TXD0) #define PB_RXD_PORT (PB_RXD0) #define RDR_PORT (RDR0) #define SSR_PORT (SSR0) #define TDR_PORT (TDR0) #else #define SCR_PORT (port ?SCR1 : SCR0) #define SMR_PORT (port ?SMR1 : SMR0) #define BRR_PORT (port ?BRR1 : BRR0) #define PBCR_PORT PBCR1 /* Same for both, just different bit */ #define PB_TXD_PORT (port ?PB_TXD1 : PB_TXD0) #define PB_RXD_PORT (port ?PB_RXD1 : PB_RXD0) #define RDR_PORT (port ?RDR1 : RDR0) #define SSR_PORT (port ?SSR1 : SSR0) #define TDR_PORT (port ?TDR1 : TDR0) #endif /*-------------------------------------------------------------------------- GLOBAL DECLARATIONS --------------------------------------------------------------------------*/ static char *copyright="MSG:Modifications by Paragon Innovations, Inc."; static char *id="$Id: sh_stub.c 1.4 1996/04/15 23:21:35 mike Exp $"; int spsave; int init_stack[init_stack_size] __attribute__ ((section ("stack"))) = {0}; int stub_stack[stub_stack_size] __attribute__ ((section ("stack"))) = {0}; int dofault; /* Non zero, bus errors will raise exception */ int *stub_sp; /* debug > 0 prints ill-formed commands in valid packets & checksum errors */ int remote_debug; /* jump buffer used for setjmp/longjmp */ jmp_buf remcomEnv; unsigned long int registers[NUMREGBYTES / 4]; stepData instrBuffer; static const char hexchars[] = "0123456789abcdef"; char remcomInBuffer[BUFMAX]; char remcomOutBuffer[BUFMAX]; #ifdef SH2 typedef struct { unsigned char baud[6]; } baud_rate_type; static const baud_rate_type baud_rate[9] = { /* 1200, 2400, 4800, 9600, 19200, 38400 Baud Rates supported*/ {31, 15, 7, 3, 1, 1 }, /* 4.9152M */ {46, 22, 11, 5, 2, 1 }, /* 7.15909M */ {77, 38, 19, 9, 4, 2 }, /* 12.0000M */ {127, 63, 31, 15, 7, 3 }, /* 19.6608M */ {129, 64, 32, 15, 7, 3 }, /* 20.0000M */ {155, 77, 38, 19, 9, 4 }, /* 24.0000M */ {159, 79, 39, 19, 9, 4 }, /* 24.5760M */ {183, 91, 45, 22, 11, 5 }, /* 28.322M */ {185, 92, 46, 22, 11, 5 } /* 28.636M */ }; #endif static unsigned short runarea[100]; static int ingdbmode; const vec_type vectable __attribute__ ((section (".vec")))= { &cold_start, /* 0: Power-on reset PC */ init_stack + init_stack_size, /* 1: Power-on reset SP */ &cold_start, /* 2: Manual reset PC */ init_stack + init_stack_size, /* 3: Manual reset SP */ { &catch_exception_4, /* 4: General invalid instruction */ &catch_exception_random, /* 5: Reserved for system */ &catch_exception_6, /* 6: Invalid slot instruction */ &catch_exception_random, /* 7: Reserved for system */ &catch_exception_random, /* 8: Reserved for system */ &catch_exception_9, /* 9: CPU bus error */ &catch_exception_10, /* 10: DMA bus error */ &catch_exception_11, /* 11: NMI */ &catch_exception_random, /* 12: User break */ &catch_exception_random, /* 13: Reserved for system */ &catch_exception_random, /* 14: Reserved for system */ &catch_exception_random, /* 15: Reserved for system */ &catch_exception_random, /* 16: Reserved for system */ &catch_exception_random, /* 17: Reserved for system */ &catch_exception_random, /* 18: Reserved for system */ &catch_exception_random, /* 19: Reserved for system */ &catch_exception_random, /* 20: Reserved for system */ &catch_exception_random, /* 21: Reserved for system */ &catch_exception_random, /* 22: Reserved for system */ &catch_exception_random, /* 23: Reserved for system */ &catch_exception_random, /* 24: Reserved for system */ &catch_exception_random, /* 25: Reserved for system */ &catch_exception_random, /* 26: Reserved for system */ &catch_exception_random, /* 27: Reserved for system */ &catch_exception_random, /* 28: Reserved for system */ &catch_exception_random, /* 29: Reserved for system */ &catch_exception_random, /* 30: Reserved for system */ &catch_exception_random, /* 31: Reserved for system */ &catch_exception_32, /* 32: Trap instr (user vectors) */ &catch_exception_33, /* 33: Trap instr (user vectors) */ &catch_exception_random, /* 34: Trap instr (user vectors) */ &catch_exception_random, /* 35: Trap instr (user vectors) */ &catch_exception_random, /* 36: Trap instr (user vectors) */ &catch_exception_random, /* 37: Trap instr (user vectors) */ &catch_exception_random, /* 38: Trap instr (user vectors) */ &catch_exception_random, /* 39: Trap instr (user vectors) */ &catch_exception_random, /* 40: Trap instr (user vectors) */ &catch_exception_random, /* 41: Trap instr (user vectors) */ &catch_exception_random, /* 42: Trap instr (user vectors) */ &catch_exception_random, /* 43: Trap instr (user vectors) */ &catch_exception_random, /* 44: Trap instr (user vectors) */ &catch_exception_random, /* 45: Trap instr (user vectors) */ &catch_exception_random, /* 46: Trap instr (user vectors) */ &catch_exception_random, /* 47: Trap instr (user vectors) */ &catch_exception_random, /* 48: Trap instr (user vectors) */ &catch_exception_random, /* 49: Trap instr (user vectors) */ &catch_exception_random, /* 50: Trap instr (user vectors) */ &catch_exception_random, /* 51: Trap instr (user vectors) */ &catch_exception_random, /* 52: Trap instr (user vectors) */ &catch_exception_random, /* 53: Trap instr (user vectors) */ &catch_exception_random, /* 54: Trap instr (user vectors) */ &catch_exception_random, /* 55: Trap instr (user vectors) */ &catch_exception_random, /* 56: Trap instr (user vectors) */ &catch_exception_random, /* 57: Trap instr (user vectors) */ &catch_exception_random, /* 58: Trap instr (user vectors) */ &catch_exception_random, /* 59: Trap instr (user vectors) */ &catch_exception_random, /* 60: Trap instr (user vectors) */ &catch_exception_random, /* 61: Trap instr (user vectors) */ &catch_exception_random, /* 62: Trap instr (user vectors) */ &catch_exception_random, /* 63: Trap instr (user vectors) */ &catch_exception_random, /* 64: IRQ0 */ &catch_exception_random, /* 65: IRQ1 */ &catch_exception_random, /* 66: IRQ2 */ &catch_exception_random, /* 67: IRQ3 */ &catch_exception_random, /* 68: IRQ4 */ &catch_exception_random, /* 69: IRQ5 */ &catch_exception_random, /* 70: IRQ6 */ &catch_exception_random, /* 71: IRQ7 */ &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_random, &catch_exception_255 } }; /**************************************************************************** ** Procedure: highhex ** ** Arguments: x ** ** Returns: char ** ** Desc: Returns ascii hex value of upper nibble ** ** ****************************************************************************/ char highhex(int x) { return hexchars[(x >> 4) & 0xf]; } /* end - highhex */ /**************************************************************************** ** Procedure: lowhex ** ** Arguments: x ** ** Returns: char ** ** Desc: Returns ascii hex value of lower nibble ** ** ****************************************************************************/ char lowhex(int x) { return hexchars[x & 0xf]; } /* end - lowhex */ /* * Routines to handle hex data */ /**************************************************************************** ** Procedure: hex ** ** Arguments: ch ascii character ** ** Returns: int ** ** Desc: returns numerical value of ascii character ex. 'A' -> 0xA ** ** ****************************************************************************/ static int hex (char ch) { if ((ch >= 'a') && (ch <= 'f')) return (ch - 'a' + 10); if ((ch >= '0') && (ch <= '9')) return (ch - '0'); if ((ch >= 'A') && (ch <= 'F')) return (ch - 'A' + 10); return (-1); } /* end - hex */ /**************************************************************************** ** Procedure: mem2hex ** ** Arguments: mem ** buf ** count ** ** Returns: char ** ** Desc: convert the memory, pointed to by mem into hex, placing result in buf ** return a pointer to the last char put in buf (null) ** ****************************************************************************/ static char *mem2hex (char *mem, char *buf, int count) { int i; int ch; for (i = 0; i < count; i++) { ch = *mem++; *buf++ = highhex (ch); *buf++ = lowhex (ch); } *buf = 0; return (buf); } /* end - mem2hex */ /**************************************************************************** ** Procedure: hex2mem ** ** Arguments: buf ** mem ** count ** ** Returns: pointer to char ** ** Desc: convert the hex array pointed to by buf into binary, to be placed in mem ** return a pointer to the character after the last byte written ** ****************************************************************************/ static char *hex2mem (char *buf, char *mem, int count) { int i; unsigned char ch; for (i = 0; i < count; i++) { ch = hex (*buf++) << 4; ch = ch + hex (*buf++); *mem++ = ch; } return (mem); } /* end - hex2mem */ /**************************************************************************** ** Procedure: hexToInt ** ** Arguments: ptr ** ** Returns: intValue ** ** Desc: WHILE WE FIND NICE HEX CHARS, BUILD AN INT ** RETURN NUMBER OF CHARS PROCESSED ** ****************************************************************************/ static int hexToInt (char **ptr, int *intValue) { int numChars = 0; int hexValue; *intValue = 0; while (**ptr) { hexValue = hex (**ptr); if (hexValue >= 0) { *intValue = (*intValue << 4) | hexValue; numChars++; } else break; (*ptr)++; } return (numChars); } /* end - hexToInt */ /* * Routines to get and put packets */ /**************************************************************************** ** Procedure: getpacket ** ** Arguments: buffer ** ** Returns: none ** ** Desc: scan for the sequence $# ** ** ****************************************************************************/ static void getpacket (char *buffer) { unsigned char checksum; unsigned char xmitcsum; int i; int count; char ch; do { /* wait around for the start character, ignore all other characters */ while ((ch = hw_rx_char (PORT)) != '$'); checksum = 0; xmitcsum = -1; count = 0; /* now, read until a # or end of buffer is found */ while (count < BUFMAX) { ch = hw_rx_char (PORT); if (ch == '#') break; checksum = checksum + ch; buffer[count] = ch; count = count + 1; } buffer[count] = 0; if (ch == '#') { xmitcsum = hex (hw_rx_char (PORT)) << 4; xmitcsum += hex (hw_rx_char (PORT)); if (checksum != xmitcsum) hw_tx_char (PORT, '-'); /* failed checksum */ else { hw_tx_char (PORT, '+'); /* successful transfer */ /* if a sequence char is present, reply the sequence ID */ if (buffer[2] == ':') { hw_tx_char (PORT, buffer[0]); hw_tx_char (PORT, buffer[1]); /* remove sequence chars from buffer */ count = strlen (buffer); for (i = 3; i <= count; i++) buffer[i - 3] = buffer[i]; } } } } while (checksum != xmitcsum); } /* end - getpacket */ /**************************************************************************** ** Procedure: putpacket ** ** Arguments: buffer ** ** Returns: none ** ** Desc: send the packet in buffer. The host gets one chance to read it. ** This routine does not wait for a positive acknowledge. ** ****************************************************************************/ static void putpacket (register char *buffer) { register int checksum; /* $#. */ do { char *src = buffer; hw_tx_char (PORT, '$'); checksum = 0; while (*src) { int runlen; /* Do run length encoding */ for (runlen = 0; runlen < 100; runlen ++) { if (src[0] != src[runlen]) { if (runlen > 3) { int encode; /* Got a useful amount */ hw_tx_char (PORT, *src); checksum += *src; hw_tx_char (PORT, '*'); checksum += '*'; checksum += (encode = runlen + ' ' - 4); hw_tx_char (PORT, encode); src += runlen; } else { hw_tx_char (PORT, *src); checksum += *src; src++; } break; } } /* end - for loop */ } hw_tx_char (PORT, '#'); hw_tx_char (PORT, highhex(checksum)); hw_tx_char (PORT, lowhex(checksum)); } while (hw_rx_char(PORT) != '+'); } /* end - putpacket */ /**************************************************************************** ** Procedure: handle_buserror ** ** Arguments: none ** ** Returns: none ** ** Desc: a bus error has occurred, perform a longjmp ** to return execution and allow handling of the error ** ****************************************************************************/ void handle_buserror (void) { longjmp (remcomEnv, 1); } /* end - handle_buserror */ /* * this function takes the SH-1 exception number and attempts to * translate this number into a unix compatible signal value */ static int computeSignal (int exceptionVector) { int sigval; switch (exceptionVector) { case INVALID_INSN_VEC: sigval = 4; break; case INVALID_SLOT_VEC: sigval = 4; break; case CPU_BUS_ERROR_VEC: sigval = 10; break; case DMA_BUS_ERROR_VEC: sigval = 10; break; case NMI_VEC: sigval = 2; break; case TRAP_VEC: case USER_VEC: sigval = 5; break; default: sigval = 7; /* "software generated"*/ break; } return (sigval); } /* end computeSignal */ /**************************************************************************** ** Procedure: stepwrapper ** ** Arguments: none ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ void stepwrapper(void) { asm volatile(" sts.l pr,@-r15 mov.l r8,@-r15 mov.l r9,@-r15 mov.l r10,@-r15 mov.l r11,@-r15 mov.l r12,@-r15 mov.l r13,@-r15 mov.l r14,@-r15 /* save current sp */ mov.l L_spsave,r0 mov.l r15, @r0 /* load the context */ mov.l L_regptr1,r0 mov.l @r0+, r1 /* r0 not ready yet */ mov.l @r0+, r1 mov.l @r0+, r2 mov.l @r0+, r3 mov.l @r0+, r4 mov.l @r0+, r5 mov.l @r0+, r6 mov.l @r0+, r7 mov.l @r0+, r8 mov.l @r0+, r9 mov.l @r0+, r10 mov.l @r0+, r11 mov.l @r0+, r12 mov.l @r0+, r13 mov.l @r0+, r14 mov.l @r0+, r15 mov.l @r0+, r1 /* pc, which we don't care about */ lds.l @r0+,pr ldc.l @r0+,gbr ldc.l @r0+,vbr lds.l @r0+,mach lds.l @r0+,macl ldc.l @r0+,sr mov.l L_regptr1,r1 mov.l @(0,r1),r0 mov.l @(4,r1),r1 .word 0xdead /* overwrite with insn to single step */ /* Now restore */ mov.l r0,@-r15 mov.l L_regptr1,r0 add #23*4,r0 stc.l sr,@-r0 sts.l macl,@-r0 sts.l mach,@-r0 stc.l vbr,@-r0 stc.l gbr,@-r0 sts.l pr,@-r0 mov.l r15,@-r0 /* pc which we'll throw away */ mov.l r15,@-r0 /* needs to be adjusted*/ mov.l r14,@-r0 mov.l r13,@-r0 mov.l r12,@-r0 mov.l r11,@-r0 mov.l r10,@-r0 mov.l r9,@-r0 mov.l r8,@-r0 mov.l r7,@-r0 mov.l r6,@-r0 mov.l r5,@-r0 mov.l r4,@-r0 mov.l r3,@-r0 mov.l r2,@-r0 mov.l r1,@-r0 /* fixup what we had to play with */ mov.l @r15+, r1 mov.l r1,@-r0 mov.l r15,@(15*4,r0) mov.l L_spsave,r0 mov.l @r0,r15 bra over nop .align 4 L_regptr1: .long _registers L_spsave: .long _spsave over: mov.l @r15+, r14 mov.l @r15+, r13 mov.l @r15+, r12 mov.l @r15+, r11 mov.l @r15+, r10 mov.l @r15+, r9 mov.l @r15+, r8 lds.l @r15+, pr"); } /* end - stepwrapper */ /**************************************************************************** ** Procedure: exec_one_insn ** ** Arguments: insn ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ void exec_one_insn (int insn) { unsigned short *p; int spc = registers[PC]; void (*pfunc)(); memcpy(runarea, stepwrapper, sizeof(runarea)); for (p = runarea; *p != 0xdead; p++) ; /* Found where to bang in the insn to step */ *p = insn; pfunc = (void *)runarea; pfunc(); registers[PC] = spc; } /* end - exec_one_insn */ /**************************************************************************** ** Procedure: db ** ** Arguments: pc ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ static void db(unsigned long pc) { exec_one_insn ( *(unsigned short *)(registers[PC]+2)); registers[PC] = pc; } /* end - db */ void hw_dostep(void) { int displacement; int reg; unsigned short opcode; opcode = *((unsigned short *)(registers[PC])); if ((opcode & MOV_MASK) == MOVL_INSN) { long * addr = (long *)((registers[PC] & ~3) + (opcode & 0xff) *4 + 4); registers[(opcode>>8) & 0xf] = *(long *)addr; registers[PC] += 2; } else if ((opcode & MOV_MASK) == MOVW_INSN) { short * addr = (short *)((registers[PC] & ~1) + (opcode & 0xff) *2 + 4); registers[(opcode>>8) & 0xf] = *(short *)addr; registers[PC] += 2; } else if ((opcode & BSR_MASK) == BSR_INSTR) { displacement = (opcode & UCOND_DISP) << 1; if (displacement & 0x0800) displacement |= 0xfffff000; registers[PR] = registers[PC] + 4; db(registers[PC] + 4 + displacement); } else if ((opcode & COND_BR_MASK) == BT_INSTR) { if (registers[SR] & T_BIT_MASK) { displacement = (opcode & COND_DISP) << 1; if (displacement & 0x80) displacement |= 0xffffff00; registers[PC] = registers[PC] + displacement+ 4; } else registers[PC] += 2; } else if ((opcode & COND_BR_MASK) == BF_INSTR) { if (registers[SR] & T_BIT_MASK) { registers[PC] += 2; } else { displacement = (opcode & COND_DISP) << 1; if (displacement & 0x80) displacement |= 0xffffff00; registers[PC] = registers[PC] + displacement + 4; } } else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR) { displacement = (opcode & UCOND_DISP) << 1; if (displacement & 0x0800) displacement |= 0xfffff000; db (registers[PC] + displacement + 4); } else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR) { reg = (char) ((opcode & UCOND_REG) >> 8); registers[PR] = registers[PC] + 4; db(registers[reg]); } else if (opcode == RTS_INSTR) { db (registers[PR]); } else { /* copy the insn an execute it inplace */ exec_one_insn (opcode); registers[PC] += 2; } } /* end - hw_dostep */ /**************************************************************************** ** Procedure: gdb_handle_exception ** ** Arguments: exceptionVector ** ** Returns: none ** ** Desc: This function does all exception handling. It only does two things - ** it figures out why it was called and tells gdb, and then it reacts ** to gdb's requests. ** ** When in the monitor mode we talk a human on the serial line rather than gdb. ** ****************************************************************************/ void gdb_handle_exception (int exceptionVector) { int sigval; int addr, length; char *ptr; /* reply to host that an exception has occurred */ sigval = computeSignal (exceptionVector); remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = highhex(sigval); remcomOutBuffer[2] = lowhex (sigval); remcomOutBuffer[3] = 0; putpacket (remcomOutBuffer); /* * exception 255 indicates a software trap * inserted in place of code ... so back up * PC by one instruction, since this instruction * will later be replaced by its original one! */ if (exceptionVector == 0xff || exceptionVector == 0x20) registers[PC] -= 2; while (1) { remcomOutBuffer[0] = 0; getpacket (remcomInBuffer); switch (remcomInBuffer[0]) { case '?': remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = highhex (sigval); remcomOutBuffer[2] = lowhex (sigval); remcomOutBuffer[3] = 0; break; case 'd': remote_debug = !(remote_debug); /* toggle debug flag */ break; case 'g': /* return the value of the CPU registers */ mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES); break; case 'G': /* set the value of the CPU registers - return OK */ hex2mem (&remcomInBuffer[1], (char *) registers, NUMREGBYTES); strcpy (remcomOutBuffer, "OK"); break; /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ case 'm': if (setjmp (remcomEnv) == 0) { dofault = 0; /* TRY, TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ ptr = &remcomInBuffer[1]; if (hexToInt (&ptr, &addr)) if (*(ptr++) == ',') if (hexToInt (&ptr, &length)) { ptr = 0; mem2hex ((char *) addr, remcomOutBuffer, length); } if (ptr) strcpy (remcomOutBuffer, "E01"); } else strcpy (remcomOutBuffer, "E03"); /* restore handler for bus error */ dofault = 1; break; /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ case 'M': if (setjmp (remcomEnv) == 0) { dofault = 0; /* TRY, TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ ptr = &remcomInBuffer[1]; if (hexToInt (&ptr, &addr)) if (*(ptr++) == ',') if (hexToInt (&ptr, &length)) if (*(ptr++) == ':') { hex2mem (ptr, (char *) addr, length); ptr = 0; strcpy (remcomOutBuffer, "OK"); } if (ptr) strcpy (remcomOutBuffer, "E02"); } else strcpy (remcomOutBuffer, "E03"); /* restore handler for bus error */ dofault = 1; break; /* cAA..AA Continue at address AA..AA(optional) */ /* sAA..AA Step one instruction from AA..AA(optional) */ case 'c': case 's': { /* tRY, to read optional parameter, pc unchanged if no parm */ ptr = &remcomInBuffer[1]; if (hexToInt (&ptr, &addr)) registers[PC] = addr; if (remcomInBuffer[0] == 's') { hw_dostep (); remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = '0'; remcomOutBuffer[2] = '5'; remcomOutBuffer[3] = 0; } else return; } break; /* kill the program */ case 'k': /* do nothing */ break; } /* switch */ /* reply to the request */ putpacket (remcomOutBuffer); } } /* end - gdb_handle_exception */ /**************************************************************************** ** Procedure: handle_exception ** ** Arguments: exceptionVector ** ** Returns: none ** ** Desc: We've had an exception - choose to go into the monitor or ** the gdb stub ** ****************************************************************************/ void handle_exception(int exceptionVector) { #ifdef MONITOR if (ingdbmode != GDBCOOKIE) { void monitor_handle_exception(); monitor_handle_exception (exceptionVector); } else #endif gdb_handle_exception (exceptionVector); } /* end - handle_exception */ /**************************************************************************** ** Procedure: gdb_mode ** ** Arguments: none ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ void gdb_mode() { ingdbmode = GDBCOOKIE; breakpoint(); } /* end - gdb_mode */ /**************************************************************************** ** Procedure: breakpoint ** ** Arguments: none ** ** Returns: none ** ** Desc: This function will generate a breakpoint exception. It is used at the ** beginning of a program to sync up with a debugger and can be used ** otherwise as a quick means to stop program execution and "break" into ** the debugger. ** ****************************************************************************/ void breakpoint (void) { BREAKPOINT (); } asm (".global _cold_start"); asm ("_cold_start: mov.l FL1,r15"); asm ("bra _cold_start_1"); asm ("nop"); asm (".align 4"); asm ("FL1: .long _init_stack + 100*4"); /**************************************************************************** ** Procedure: cold_start_1 ** ** Arguments: none ** ** Returns: none ** ** Desc: POWER-UP RESET CALLS ASSY ROUTINE THAT DOES A "BTA _COLD_START_1" ** All initialization can occur here ** ** ****************************************************************************/ void cold_start_1 (void) { extern int yydebug; #ifdef SH2 mem_enable_sdram(); /* enable SDRAM by default */ init_serial(); asm volatile(" nop !--------------------------------------------------------------- ! Purge cache memory and setup frequency modification register !--------------------------------------------------------------- mova clock2_end,r0 ! Load end of clock mod mov r0,r11 ! mova clock2_start,r0 ! Load beginning of clock mod mov.l DIRECT_RW,r1 ! Load Address of cache mov.l PURGE,r12 ! Load offset for purge ! Disable Cache and purge mov.l CCR,r2 mov #0,r3 mov.b r3,@r2 ! Done disabling cache xor r13,r13 ! Clear register ! ! Transfer Freq. Modification program to data array ! clk_trans: mov.l @r0,r2 ! move 16 bytes to internal registers mov.l @(4,r0),r3 ! mov.l @(8,r0),r4 ! mov.l @(12,r0),r5 ! mov.l r2,@r1 ! move 16 bytes to data array mov.l r3,@(4,r1) ! mov.l r4,@(8,r1) ! mov.l r5,@(12,r1) ! mov.l r13, @r12 ! Suggusted by Del for purge add #0x10, r12 ! Increment purge (Del) add #0x10,r0 ! Increment to next page (16 bytes) add #0x10,r1 ! cmp/gt r11,r0 ! ?? Are we done yet bf clk_trans ! No, jump nop mova post_freq_mod,r0 ! Get address to continue in regular code mov r0,r3 ! copy to correct register mov.l DIRECT_RW,r0 ! Address of data array jmp @r0 ! Continue exectution in processor RAM nop nop .align 4 ! align on 16 byte boundary clock2_start: mov.l WTCSR,r0 ! Set WTCSR mov.w WTCSR_VALUE,r1 ! mov.w r1, @r0 ! mov.l FMR,r0 ! Load FMR mov #2, r1 ! mov.b r1, @r0 ! nop ! Man. says at least 8 nops nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop ! jmp @r3 ! continue with rest of program nop ! Slot intruction (just in case) !!!!!! These constants must be transfered with the code !!!!!!!!!!!!! .align 2 FMR: .long 0xfffffe90 ! Frequency Modification Register WTCSR: .long 0xfffffe80 ! Watchdog Control/Status Register WTCSR_VALUE: .word 0xa507 ! Watchdog timer control/status value clock2_end: nop ! !--------------------------------------------------------------- CCR: .long 0xfffffe92 ! CCR PURGE: .long 0x40000000 ! Cache Purge area base DIRECT_RW: .long 0xc0000000 ! Cache as RAM read/write area base post_freq_mod: nop nop "); #else /* First turn on the ram */ WCR1 = WCR1_VALUE; BCR = BCR_VALUE; /* use lowbyte/high byte */ #endif init_serial(); yydebug =1 ; vfd_clear(); vfd_test_bars(); #ifdef MONITOR { void init_for_cold_start(); init_for_cold_start(); } #endif dofault = 1; stub_sp = stub_stack + stub_stack_size; breakpoint (); while (1) ; } /* end - cold_start_1 */ asm (".global _warm_start"); asm ("_warm_start: mov.l FL2,r15"); asm ("bra _warm_start_1"); asm ("nop"); asm (".align 4"); asm ("FL2: .long _init_stack + 100*4"); /**************************************************************************** ** Procedure: warm_start_1 ** ** Arguments: none ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ void warm_start_1() { #ifdef MONITOR void init_for_warm_start(); init_for_warm_start(); #endif stub_sp = stub_stack + stub_stack_size; breakpoint(); while (1) ; } /* end - warm_start */ /**************************************************************************** ** Procedure: foo ** ** Arguments: none ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ void foo() { asm(" .align 2 L_sp: .long _init_stack + 8000"); asm("saveRegisters: mov.l @(L_reg, pc), r0 mov.l @r15+, r1 ! pop R0 mov.l r2, @(0x08, r0) ! save R2 mov.l r1, @r0 ! save R0 mov.l @r15+, r1 ! pop R1 mov.l r3, @(0x0c, r0) ! save R3 mov.l r1, @(0x04, r0) ! save R1 mov.l r4, @(0x10, r0) ! save R4 mov.l r5, @(0x14, r0) ! save R5 mov.l r6, @(0x18, r0) ! save R6 mov.l r7, @(0x1c, r0) ! save R7 mov.l r8, @(0x20, r0) ! save R8 mov.l r9, @(0x24, r0) ! save R9 mov.l r10, @(0x28, r0) ! save R10 mov.l r11, @(0x2c, r0) ! save R11 mov.l r12, @(0x30, r0) ! save R12 mov.l r13, @(0x34, r0) ! save R13 mov.l r14, @(0x38, r0) ! save R14 mov.l @r15+, r4 ! save arg to handleException add #8, r15 ! hide PC/SR values on stack mov.l r15, @(0x3c, r0) ! save R15 add #-8, r15 ! save still needs old SP value add #92, r0 ! readjust register pointer mov r15, r2 add #4, r2 mov.l @r2, r2 ! R2 has SR mov.l @r15, r1 ! R1 has PC mov.l r2, @-r0 ! save SR sts.l macl, @-r0 ! save MACL sts.l mach, @-r0 ! save MACH stc.l vbr, @-r0 ! save VBR stc.l gbr, @-r0 ! save GBR sts.l pr, @-r0 ! save PR mov.l @(L_stubstack, pc), r2 mov.l @(L_hdl_except, pc), r3 mov.l @r2, r15 jsr @r3 mov.l r1, @-r0 ! save PC mov.l @(L_stubstack, pc), r0 mov.l @(L_reg, pc), r1 bra restoreRegisters mov.l r15, @r0 ! save __stub_stack .align 2 L_reg: .long _registers L_stubstack: .long _stub_sp L_hdl_except: .long _handle_exception"); } /* end - foo */ /**************************************************************************** ** Procedure: rr ** ** Arguments: none ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ static void rr() { asm(" .align 2 .global _resume _resume: mov r4,r1 restoreRegisters: add #8, r1 ! skip to R2 mov.l @r1+, r2 ! restore R2 mov.l @r1+, r3 ! restore R3 mov.l @r1+, r4 ! restore R4 mov.l @r1+, r5 ! restore R5 mov.l @r1+, r6 ! restore R6 mov.l @r1+, r7 ! restore R7 mov.l @r1+, r8 ! restore R8 mov.l @r1+, r9 ! restore R9 mov.l @r1+, r10 ! restore R10 mov.l @r1+, r11 ! restore R11 mov.l @r1+, r12 ! restore R12 mov.l @r1+, r13 ! restore R13 mov.l @r1+, r14 ! restore R14 mov.l @r1+, r15 ! restore programs stack mov.l @r1+, r0 add #-8, r15 ! uncover PC/SR on stack mov.l r0, @r15 ! restore PC onto stack lds.l @r1+, pr ! restore PR ldc.l @r1+, gbr ! restore GBR ldc.l @r1+, vbr ! restore VBR lds.l @r1+, mach ! restore MACH lds.l @r1+, macl ! restore MACL mov.l @r1, r0 add #-88, r1 ! readjust reg pointer to R1 mov.l r0, @(4, r15) ! restore SR onto stack+4 mov.l r2, @-r15 mov.l @r15+, r2 mov.l @r1+, r0 ! restore R0 rte mov.l @r1, r1 ! restore R1 "); } /* end - rr */ #define code_for_catch_exception(n) \ asm(" .globl _catch_exception_"#n ); \ asm(" _catch_exception_"#n":" ); \ asm(" add #-4, r15 ! reserve spot on stack "); \ asm(" mov.l r1, @-r15 ! push R1 "); \ asm(" mov #15<<4, r1 "); \ asm(" ldc r1, sr ! disable interrupts "); \ asm(" mov.l r0, @-r15 ! push R0 "); \ asm(" mov r15, r0 "); \ asm(" add #8, r0 "); \ asm(" mov #"#n",r1" ); \ asm(" extu.b r1,r1 "); \ asm(" bra saveRegisters ! save register values "); \ asm(" mov.l r1, @r0 ! save exception # "); #define code_for_catch_exception9(n) \ asm(" .globl _catch_exception_"#n ); \ asm(" _catch_exception_"#n":" ); \ asm(" add #-4, r15 ! reserve spot on stack "); \ asm(" mov.l r1, @-r15 ! push R1 "); \ asm("mov.l L_dofault,r1"); \ asm("mov.l @r1,r1"); \ asm("tst r1,r1"); \ asm("bf faultaway"); \ asm("bsr _handle_buserror"); \ asm(".align 2"); \ asm("L_dofault: .long _dofault"); \ asm("faultaway:"); \ asm(" mov #15<<4, r1 "); \ asm(" ldc r1, sr ! disable interrupts "); \ asm(" mov.l r0, @-r15 ! push R0 "); \ asm(" mov r15, r0 "); \ asm(" add #8, r0 "); \ asm(" mov #"#n",r1" ); \ asm(" extu.b r1,r1 "); \ asm(" bra saveRegisters ! save register values "); \ asm(" mov.l r1, @r0 ! save exception # "); /**************************************************************************** ** Procedure: exceptions ** ** Arguments: none ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ static void exceptions() { code_for_catch_exception9 (9); /* CPU_BUS_ERROR_VEC */ code_for_catch_exception (10); /* DMA_BUS_ERROR_VEC */ code_for_catch_exception (4); /* INVALID_INSN_VEC */ code_for_catch_exception (6); /* INVALID_SLOT_VEC */ code_for_catch_exception (11); /* NMI_VEC */ code_for_catch_exception (32); /* TRAP_VEC */ code_for_catch_exception (255); /* USER_VEC */ code_for_catch_exception (33); /* IO_VEC */ } /* end - exceptions */ /**************************************************************************** ** Procedure: nop ** ** Arguments: none ** ** Returns: none ** ** Desc: Do nothing ** ** ****************************************************************************/ void nop () { } /* end - nop */ /**************************************************************************** ** Procedure: hw_init_serial ** ** Arguments: port ** speed ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ void hw_init_serial(int port, int speed) { unsigned int i; /* Clear TE and RE in Channel 1's SCR */ SCR_PORT &= ~(SCI_TE | SCI_RE); /* Set communication to be async, 8-bit data, no parity, 1 stop bit and use internal clock */ SMR_PORT = 0; #ifdef SH2 switch ( speed ) { case 1200: i = 0; break; case 2400: i = 1; break; case 4800: i = 2; break; case 9600: i = 3; break; case 19200: i = 4; break; case 38400: i = 5; break; default: i = 3; break; } BRR_PORT = baud_rate[SH2_MHZ].baud[i]; SCR_PORT &= ~SCI_CKE1; SCR_PORT |= SCI_CKE0; #else BRR_PORT = BPS * 9600 / speed; SCR_PORT &= ~(SCI_CKE1 | SCI_CKE0); #endif /* let the hardware settle */ for (i = 0; i < 12; i++) nop (); /* Turn on in and out */ SCR_PORT |= SCI_RE | SCI_TE; #ifndef SH2 /* Set the PFC to make RXD1 (pin PB8) an input pin and TXD1 (pin PB9) an output pin */ PBCR_PORT &= ~(PB_TXD_PORT | PB_RXD_PORT); PBCR_PORT |= PB_TXD_PORT | PB_RXD_PORT; #endif } /* end - hw_init_serial */ /**************************************************************************** ** Procedure: hw_rx_ready ** ** Arguments: port ** ** Returns: ** ** Desc: ** ** ****************************************************************************/ int __inline__ hw_rx_ready (const int port) { char mySSR; mySSR = SSR_PORT & ( SCI_PER | SCI_FER | SCI_ORER ); if ( mySSR ) handleError_P1 ( port, mySSR ); return SSR_PORT & SCI_RDRF ; } /* end - hw_rx_ready */ /**************************************************************************** ** Procedure: dorx ** ** Arguments: port ** ** Returns: ** ** Desc: ** ** ****************************************************************************/ int __inline__ dorx(const int port) { char ch; char mySSR; while ( ! hw_rx_ready(port)) ; ch = RDR_PORT; SSR_PORT &= ~SCI_RDRF; mySSR = SSR_PORT & (SCI_PER | SCI_FER | SCI_ORER); if (mySSR) handleError_P1 (port, mySSR); return ch; } /* end - dorx */ /**************************************************************************** ** Procedure: hw_rx_char ** ** Arguments: port ** ** Returns: char ** ** Desc: Inline the char getter, with the port constant evalled, to make ** things much faster ** ****************************************************************************/ char __inline__ hw_rx_char (const int port) { if (port == 1) return dorx(1); else return dorx(0); } /* end - hw_rx_char */ /**************************************************************************** ** Procedure: hw_tx_ready ** ** Arguments: port ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ int hw_tx_ready(int port) { return (SSR_PORT & SCI_TDRE); } /* end - hw_tx_ready */ /**************************************************************************** ** Procedure: hw_tx_char ** ** Arguments: port ** ch ** ** Returns: ** ** Desc: ** ** ****************************************************************************/ int hw_tx_char (int port, char ch) { while (!hw_tx_ready(port)) ; /* * Write data into TDR and clear TDRE */ TDR_PORT = ch; SSR_PORT &= ~SCI_TDRE; return 0; } /* end - hw_tx_char */ /**************************************************************************** ** Procedure: handleError_P1 ** ** Arguments: port ** theSSR ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ void handleError_P1 (int port, char theSSR) { SSR_PORT &= ~(SCI_ORER | SCI_PER | SCI_FER); } /* end - handleError_P1 */ /**************************************************************************** ** Procedure: init_serial ** ** Arguments: none ** ** Returns: none ** ** Desc: ** ** ****************************************************************************/ void init_serial() { hw_init_serial(0, 9600); #ifndef SH2 hw_init_serial(1, 9600); #endif } /* end - init_serial */ #ifdef SH2 /**************************************************************************** ** Procedure: mem_enable_sdram ** ** Arguments: none ** ** Returns: none ** ** Desc: Enable SDRAM memory ** ** ****************************************************************************/ void mem_enable_sdram() { WCR = WCR_SDRAM_VALUE; BCR1 = BCR1_SDRAM_VALUE; BCR2 = BCR2_SDRAM_VALUE; MCR = MCR_SDRAM_VALUE; RTCSR = RTCSR_SDRAM_VALUE; SDRAM_MODE = 0; /* Value isn't important, only the address */ } /* end - mem_enable_sdram */ #endif #ifdef SH2 /**************************************************************************** ** Procedure: mem_enable_dram ** ** Arguments: none ** ** Returns: none ** ** Desc: Enable DRAM memory ** ** ****************************************************************************/ void mem_enable_dram() { WCR = WCR_DRAM_VALUE; BCR1 = BCR1_DRAM_VALUE; BCR2 = BCR2_DRAM_VALUE; MCR = MCR_DRAM_VALUE; RTCSR = RTCSR_DRAM_VALUE; } /* end - mem_enable_dram */ #endif