/***************************************************************************
** $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 <data>
**   is encapsulated for transmission in the form:
**
**   $ <data> # CSUM1 CSUM2
**
**   <data> must be ASCII alphanumeric and cannot include characters
**   '$' or '#'.  If <data> 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 <data>, 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
**
**   <data> 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        <other>         On other requests, the stub should
**                                   ignore the request and send an empty
**                                   response ($#<checksum>).  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 <string.h>
#include <setjmp.h>
#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 $<data>#<checksum>
**
**
****************************************************************************/
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;

  /*  $<packet info>#<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

