xref: /netbsd-src/external/gpl3/gdb/dist/sim/erc32/erc32.c (revision 1f4e7eb9e5e045e008f1894823a8e4e6c9f46890)
1212397c6Schristos /* This file is part of SIS (SPARC instruction simulator)
2212397c6Schristos 
3*1f4e7eb9Schristos    Copyright (C) 1995-2024 Free Software Foundation, Inc.
4212397c6Schristos    Contributed by Jiri Gaisler, European Space Agency
5212397c6Schristos 
6212397c6Schristos    This program is free software; you can redistribute it and/or modify
7212397c6Schristos    it under the terms of the GNU General Public License as published by
8212397c6Schristos    the Free Software Foundation; either version 3 of the License, or
9212397c6Schristos    (at your option) any later version.
10212397c6Schristos 
11212397c6Schristos    This program is distributed in the hope that it will be useful,
12212397c6Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
13212397c6Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14212397c6Schristos    GNU General Public License for more details.
15212397c6Schristos 
16212397c6Schristos    You should have received a copy of the GNU General Public License
17212397c6Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
184e98e3e1Schristos 
194e98e3e1Schristos /* The control space devices */
204e98e3e1Schristos 
214b169a6bSchristos /* This must come before any other includes.  */
224b169a6bSchristos #include "defs.h"
234b169a6bSchristos 
244e98e3e1Schristos #include <sys/types.h>
254e98e3e1Schristos #include <stdio.h>
264e98e3e1Schristos #include <string.h>
274b169a6bSchristos #ifdef HAVE_TERMIOS_H
284e98e3e1Schristos #include <termios.h>
294b169a6bSchristos #endif
304e98e3e1Schristos #include <sys/fcntl.h>
314e98e3e1Schristos #include <sys/file.h>
324e98e3e1Schristos #include <unistd.h>
334e98e3e1Schristos #include "sis.h"
344e98e3e1Schristos #include "sim-config.h"
354e98e3e1Schristos 
364e98e3e1Schristos extern int      ctrl_c;
374b169a6bSchristos extern int32_t    sis_verbose;
384b169a6bSchristos extern int32_t    sparclite, sparclite_board;
394e98e3e1Schristos extern int      rom8,wrp,uben;
404e98e3e1Schristos extern char     uart_dev1[], uart_dev2[];
414e98e3e1Schristos 
424e98e3e1Schristos int dumbio = 0; /* normal, smart, terminal oriented IO by default */
434e98e3e1Schristos 
444e98e3e1Schristos /* MEC registers */
454e98e3e1Schristos #define MEC_START 	0x01f80000
464e98e3e1Schristos #define MEC_END 	0x01f80100
474e98e3e1Schristos 
484e98e3e1Schristos /* Memory exception waitstates */
494e98e3e1Schristos #define MEM_EX_WS 	1
504e98e3e1Schristos 
514e98e3e1Schristos /* ERC32 always adds one waitstate during RAM std */
524e98e3e1Schristos #define STD_WS 1
534e98e3e1Schristos 
544e98e3e1Schristos #ifdef ERRINJ
554e98e3e1Schristos extern int errmec;
564e98e3e1Schristos #endif
574e98e3e1Schristos 
584e98e3e1Schristos #define MEC_WS	0		/* Waitstates per MEC access (0 ws) */
594e98e3e1Schristos #define MOK	0
604e98e3e1Schristos 
614e98e3e1Schristos /* MEC register addresses */
624e98e3e1Schristos 
634e98e3e1Schristos #define MEC_MCR		0x000
644e98e3e1Schristos #define MEC_SFR  	0x004
654e98e3e1Schristos #define MEC_PWDR  	0x008
664e98e3e1Schristos #define MEC_MEMCFG	0x010
674e98e3e1Schristos #define MEC_IOCR	0x014
684e98e3e1Schristos #define MEC_WCR		0x018
694e98e3e1Schristos 
704e98e3e1Schristos #define MEC_MAR0  	0x020
714e98e3e1Schristos #define MEC_MAR1  	0x024
724e98e3e1Schristos 
734e98e3e1Schristos #define MEC_SSA1 	0x020
744e98e3e1Schristos #define MEC_SEA1 	0x024
754e98e3e1Schristos #define MEC_SSA2 	0x028
764e98e3e1Schristos #define MEC_SEA2 	0x02C
774e98e3e1Schristos #define MEC_ISR		0x044
784e98e3e1Schristos #define MEC_IPR		0x048
794e98e3e1Schristos #define MEC_IMR 	0x04C
804e98e3e1Schristos #define MEC_ICR 	0x050
814e98e3e1Schristos #define MEC_IFR 	0x054
824e98e3e1Schristos #define MEC_WDOG  	0x060
834e98e3e1Schristos #define MEC_TRAPD  	0x064
844e98e3e1Schristos #define MEC_RTC_COUNTER	0x080
854e98e3e1Schristos #define MEC_RTC_RELOAD	0x080
864e98e3e1Schristos #define MEC_RTC_SCALER	0x084
874e98e3e1Schristos #define MEC_GPT_COUNTER	0x088
884e98e3e1Schristos #define MEC_GPT_RELOAD	0x088
894e98e3e1Schristos #define MEC_GPT_SCALER	0x08C
904e98e3e1Schristos #define MEC_TIMER_CTRL	0x098
914e98e3e1Schristos #define MEC_SFSR	0x0A0
924e98e3e1Schristos #define MEC_FFAR	0x0A4
934e98e3e1Schristos #define MEC_ERSR	0x0B0
944e98e3e1Schristos #define MEC_DBG		0x0C0
954e98e3e1Schristos #define MEC_TCR		0x0D0
964e98e3e1Schristos 
974e98e3e1Schristos #define MEC_BRK		0x0C4
984e98e3e1Schristos #define MEC_WPR		0x0C8
994e98e3e1Schristos 
1004e98e3e1Schristos #define MEC_UARTA	0x0E0
1014e98e3e1Schristos #define MEC_UARTB	0x0E4
1024e98e3e1Schristos #define MEC_UART_CTRL	0x0E8
1034e98e3e1Schristos #define SIM_LOAD	0x0F0
1044e98e3e1Schristos 
1054e98e3e1Schristos /* Memory exception causes */
1064e98e3e1Schristos #define PROT_EXC	0x3
1074e98e3e1Schristos #define UIMP_ACC	0x4
1084e98e3e1Schristos #define MEC_ACC		0x6
1094e98e3e1Schristos #define WATCH_EXC	0xa
1104e98e3e1Schristos #define BREAK_EXC	0xb
1114e98e3e1Schristos 
1124e98e3e1Schristos /* Size of UART buffers (bytes) */
1134e98e3e1Schristos #define UARTBUF	1024
1144e98e3e1Schristos 
1154e98e3e1Schristos /* Number of simulator ticks between flushing the UARTS. 	 */
1164e98e3e1Schristos /* For good performance, keep above 1000			 */
1174e98e3e1Schristos #define UART_FLUSH_TIME	  3000
1184e98e3e1Schristos 
1194e98e3e1Schristos /* MEC timer control register bits */
1204e98e3e1Schristos #define TCR_GACR 1
1214e98e3e1Schristos #define TCR_GACL 2
1224e98e3e1Schristos #define TCR_GASE 4
1234e98e3e1Schristos #define TCR_GASL 8
1244e98e3e1Schristos #define TCR_TCRCR 0x100
1254e98e3e1Schristos #define TCR_TCRCL 0x200
1264e98e3e1Schristos #define TCR_TCRSE 0x400
1274e98e3e1Schristos #define TCR_TCRSL 0x800
1284e98e3e1Schristos 
1294e98e3e1Schristos /* New uart defines */
1304e98e3e1Schristos #define UART_TX_TIME	1000
1314e98e3e1Schristos #define UART_RX_TIME	1000
1324e98e3e1Schristos #define UARTA_DR	0x1
1334e98e3e1Schristos #define UARTA_SRE	0x2
1344e98e3e1Schristos #define UARTA_HRE	0x4
1354e98e3e1Schristos #define UARTA_OR	0x40
1364e98e3e1Schristos #define UARTA_CLR	0x80
1374e98e3e1Schristos #define UARTB_DR	0x10000
1384e98e3e1Schristos #define UARTB_SRE	0x20000
1394e98e3e1Schristos #define UARTB_HRE	0x40000
1404e98e3e1Schristos #define UARTB_OR	0x400000
1414e98e3e1Schristos #define UARTB_CLR	0x800000
1424e98e3e1Schristos 
1434e98e3e1Schristos #define UART_DR		0x100
1444e98e3e1Schristos #define UART_TSE	0x200
1454e98e3e1Schristos #define UART_THE	0x400
1464e98e3e1Schristos 
1474e98e3e1Schristos /* MEC registers */
1484e98e3e1Schristos 
1494e98e3e1Schristos static char     fname[256];
1504b169a6bSchristos static int32_t    find = 0;
1514b169a6bSchristos static uint32_t   mec_ssa[2];	/* Write protection start address */
1524b169a6bSchristos static uint32_t   mec_sea[2];	/* Write protection end address */
1534b169a6bSchristos static uint32_t   mec_wpr[2];	/* Write protection control fields */
1544b169a6bSchristos static uint32_t   mec_sfsr;
1554b169a6bSchristos static uint32_t   mec_ffar;
1564b169a6bSchristos static uint32_t   mec_ipr;
1574b169a6bSchristos static uint32_t   mec_imr;
1584b169a6bSchristos static uint32_t   mec_isr;
1594b169a6bSchristos static uint32_t   mec_icr;
1604b169a6bSchristos static uint32_t   mec_ifr;
1614b169a6bSchristos static uint32_t   mec_mcr;	/* MEC control register */
1624b169a6bSchristos static uint32_t   mec_memcfg;	/* Memory control register */
1634b169a6bSchristos static uint32_t   mec_wcr;	/* MEC waitstate register */
1644b169a6bSchristos static uint32_t   mec_iocr;	/* MEC IO control register */
1654b169a6bSchristos static uint32_t   posted_irq;
1664b169a6bSchristos static uint32_t   mec_ersr;	/* MEC error and status register */
1674b169a6bSchristos static uint32_t   mec_tcr;	/* MEC test comtrol register */
1684e98e3e1Schristos 
1694b169a6bSchristos static uint32_t   rtc_counter;
1704b169a6bSchristos static uint32_t   rtc_reload;
1714b169a6bSchristos static uint32_t   rtc_scaler;
1724b169a6bSchristos static uint32_t   rtc_scaler_start;
1734b169a6bSchristos static uint32_t   rtc_enabled;
1744b169a6bSchristos static uint32_t   rtc_cr;
1754b169a6bSchristos static uint32_t   rtc_se;
1764e98e3e1Schristos 
1774b169a6bSchristos static uint32_t   gpt_counter;
1784b169a6bSchristos static uint32_t   gpt_reload;
1794b169a6bSchristos static uint32_t   gpt_scaler;
1804b169a6bSchristos static uint32_t   gpt_scaler_start;
1814b169a6bSchristos static uint32_t   gpt_enabled;
1824b169a6bSchristos static uint32_t   gpt_cr;
1834b169a6bSchristos static uint32_t   gpt_se;
1844e98e3e1Schristos 
1854b169a6bSchristos static uint32_t   wdog_scaler;
1864b169a6bSchristos static uint32_t   wdog_counter;
1874b169a6bSchristos static uint32_t   wdog_rst_delay;
1884b169a6bSchristos static uint32_t   wdog_rston;
1894e98e3e1Schristos 
1904e98e3e1Schristos enum wdog_type {
1914e98e3e1Schristos     init, disabled, enabled, stopped
1924e98e3e1Schristos };
1934e98e3e1Schristos 
1944e98e3e1Schristos static enum wdog_type wdog_status;
1954e98e3e1Schristos 
1964e98e3e1Schristos 
1974e98e3e1Schristos /* ROM size 1024 Kbyte */
1984e98e3e1Schristos #define ROM_SZ	 	0x100000
1994e98e3e1Schristos #define ROM_MASK 	0x0fffff
2004e98e3e1Schristos 
2014e98e3e1Schristos /* RAM size 4 Mbyte */
2024e98e3e1Schristos #define RAM_START 	0x02000000
2034e98e3e1Schristos #define RAM_END 	0x02400000
2044e98e3e1Schristos #define RAM_MASK 	0x003fffff
2054e98e3e1Schristos 
2064e98e3e1Schristos /* SPARClite boards all seem to have RAM at the same place. */
2074e98e3e1Schristos #define RAM_START_SLITE	0x40000000
2084e98e3e1Schristos #define RAM_END_SLITE 	0x40400000
2094e98e3e1Schristos #define RAM_MASK_SLITE 	0x003fffff
2104e98e3e1Schristos 
2114e98e3e1Schristos /* Memory support variables */
2124e98e3e1Schristos 
2134b169a6bSchristos static uint32_t   mem_ramr_ws;	/* RAM read waitstates */
2144b169a6bSchristos static uint32_t   mem_ramw_ws;	/* RAM write waitstates */
2154b169a6bSchristos static uint32_t   mem_romr_ws;	/* ROM read waitstates */
2164b169a6bSchristos static uint32_t   mem_romw_ws;	/* ROM write waitstates */
2174b169a6bSchristos static uint32_t	mem_ramstart;	/* RAM start */
2184b169a6bSchristos static uint32_t	mem_ramend;	/* RAM end */
2194b169a6bSchristos static uint32_t	mem_rammask;	/* RAM address mask */
2204b169a6bSchristos static uint32_t   mem_ramsz;	/* RAM size */
2214b169a6bSchristos static uint32_t   mem_romsz;	/* ROM size */
2224b169a6bSchristos static uint32_t   mem_accprot;	/* RAM write protection enabled */
2234b169a6bSchristos static uint32_t   mem_blockprot;	/* RAM block write protection enabled */
2244e98e3e1Schristos 
2254e98e3e1Schristos static unsigned char	romb[ROM_SZ];
2264e98e3e1Schristos static unsigned char	ramb[RAM_END - RAM_START];
2274e98e3e1Schristos 
2284e98e3e1Schristos 
2294e98e3e1Schristos /* UART support variables */
2304e98e3e1Schristos 
2314b169a6bSchristos static int32_t    fd1, fd2;	/* file descriptor for input file */
2324b169a6bSchristos static int32_t    Ucontrol;	/* UART status register */
2334e98e3e1Schristos static unsigned char aq[UARTBUF], bq[UARTBUF];
2344b169a6bSchristos static int32_t    anum, aind = 0;
2354b169a6bSchristos static int32_t    bnum, bind = 0;
2364e98e3e1Schristos static char     wbufa[UARTBUF], wbufb[UARTBUF];
2374e98e3e1Schristos static unsigned wnuma;
2384e98e3e1Schristos static unsigned wnumb;
2394e98e3e1Schristos static FILE    *f1in, *f1out, *f2in, *f2out;
2404b169a6bSchristos #ifdef HAVE_TERMIOS_H
2414e98e3e1Schristos static struct termios ioc1, ioc2, iocold1, iocold2;
2424b169a6bSchristos #endif
2434e98e3e1Schristos static int      f1open = 0, f2open = 0;
2444e98e3e1Schristos 
2454e98e3e1Schristos static char     uarta_sreg, uarta_hreg, uartb_sreg, uartb_hreg;
2464b169a6bSchristos static uint32_t   uart_stat_reg;
2474b169a6bSchristos static uint32_t   uarta_data, uartb_data;
2484e98e3e1Schristos 
2494e98e3e1Schristos #ifdef ERA
2504e98e3e1Schristos int era = 0;
2514e98e3e1Schristos int erareg;
2524e98e3e1Schristos #endif
2534e98e3e1Schristos 
2544e98e3e1Schristos /* Forward declarations */
2554e98e3e1Schristos 
25603467a24Schristos static void	decode_ersr (void);
2574e98e3e1Schristos #ifdef ERRINJ
25803467a24Schristos static void	iucomperr (void);
2594e98e3e1Schristos #endif
26003467a24Schristos static void	mecparerror (void);
26103467a24Schristos static void	decode_memcfg (void);
26203467a24Schristos static void	decode_wcr (void);
26303467a24Schristos static void	decode_mcr (void);
26403467a24Schristos static void	close_port (void);
26503467a24Schristos static void	mec_reset (void);
2664b169a6bSchristos static void	mec_intack (int32_t level);
26703467a24Schristos static void	chk_irq (void);
2684b169a6bSchristos static void	mec_irq (int32_t level);
2694b169a6bSchristos static void	set_sfsr (uint32_t fault, uint32_t addr,
2704b169a6bSchristos 			  uint32_t asi, uint32_t read);
2714b169a6bSchristos static int32_t	mec_read (uint32_t addr, uint32_t asi, uint32_t *data);
2724b169a6bSchristos static int	mec_write (uint32_t addr, uint32_t data);
27303467a24Schristos static void	port_init (void);
2744b169a6bSchristos static uint32_t	read_uart (uint32_t addr);
2754b169a6bSchristos static void	write_uart (uint32_t addr, uint32_t data);
27603467a24Schristos static void	flush_uart (void);
2774b169a6bSchristos static void	uarta_tx (int32_t);
2784b169a6bSchristos static void	uartb_tx (int32_t);
2794b169a6bSchristos static void	uart_rx (int32_t);
2804b169a6bSchristos static void	uart_intr (int32_t);
28103467a24Schristos static void	uart_irq_start (void);
2824b169a6bSchristos static void	wdog_intr (int32_t);
28303467a24Schristos static void	wdog_start (void);
2844b169a6bSchristos static void	rtc_intr (int32_t);
28503467a24Schristos static void	rtc_start (void);
2864b169a6bSchristos static uint32_t	rtc_counter_read (void);
2874b169a6bSchristos static void	rtc_scaler_set (uint32_t val);
2884b169a6bSchristos static void	rtc_reload_set (uint32_t val);
2894b169a6bSchristos static void	gpt_intr (int32_t);
29003467a24Schristos static void	gpt_start (void);
2914b169a6bSchristos static uint32_t	gpt_counter_read (void);
2924b169a6bSchristos static void	gpt_scaler_set (uint32_t val);
2934b169a6bSchristos static void	gpt_reload_set (uint32_t val);
2944b169a6bSchristos static void	timer_ctrl (uint32_t val);
2954b169a6bSchristos static void *	get_mem_ptr (uint32_t addr, uint32_t size);
2964b169a6bSchristos static void	store_bytes (unsigned char *mem, uint32_t waddr,
2974b169a6bSchristos 			uint32_t *data, int sz, int32_t *ws);
2984e98e3e1Schristos 
2994e98e3e1Schristos extern int	ext_irl;
3004e98e3e1Schristos 
3014e98e3e1Schristos 
3024e98e3e1Schristos /* One-time init */
3034e98e3e1Schristos 
3044e98e3e1Schristos void
3054b169a6bSchristos init_sim(void)
3064e98e3e1Schristos {
3074e98e3e1Schristos     port_init();
3084e98e3e1Schristos }
3094e98e3e1Schristos 
3104e98e3e1Schristos /* Power-on reset init */
3114e98e3e1Schristos 
3124e98e3e1Schristos void
3134b169a6bSchristos reset(void)
3144e98e3e1Schristos {
3154e98e3e1Schristos     mec_reset();
3164e98e3e1Schristos     uart_irq_start();
3174e98e3e1Schristos     wdog_start();
3184e98e3e1Schristos }
3194e98e3e1Schristos 
3204e98e3e1Schristos static void
3214b169a6bSchristos decode_ersr(void)
3224e98e3e1Schristos {
3234e98e3e1Schristos     if (mec_ersr & 0x01) {
3244e98e3e1Schristos 	if (!(mec_mcr & 0x20)) {
3254e98e3e1Schristos 	    if (mec_mcr & 0x40) {
3264e98e3e1Schristos 	        sys_reset();
3274e98e3e1Schristos 	        mec_ersr = 0x8000;
3284e98e3e1Schristos 	        if (sis_verbose)
3294e98e3e1Schristos 	            printf("Error manager reset - IU in error mode\n");
3304e98e3e1Schristos 	    } else {
3314e98e3e1Schristos 	        sys_halt();
3324e98e3e1Schristos 	        mec_ersr |= 0x2000;
3334e98e3e1Schristos 	        if (sis_verbose)
3344e98e3e1Schristos 	            printf("Error manager halt - IU in error mode\n");
3354e98e3e1Schristos 	    }
3364e98e3e1Schristos 	} else
3374e98e3e1Schristos 	    mec_irq(1);
3384e98e3e1Schristos     }
3394e98e3e1Schristos     if (mec_ersr & 0x04) {
3404e98e3e1Schristos 	if (!(mec_mcr & 0x200)) {
3414e98e3e1Schristos 	    if (mec_mcr & 0x400) {
3424e98e3e1Schristos 	        sys_reset();
3434e98e3e1Schristos 	        mec_ersr = 0x8000;
3444e98e3e1Schristos 	        if (sis_verbose)
3454e98e3e1Schristos 	            printf("Error manager reset - IU comparison error\n");
3464e98e3e1Schristos 	    } else {
3474e98e3e1Schristos 	        sys_halt();
3484e98e3e1Schristos 	        mec_ersr |= 0x2000;
3494e98e3e1Schristos 	        if (sis_verbose)
3504e98e3e1Schristos 	            printf("Error manager halt - IU comparison error\n");
3514e98e3e1Schristos 	    }
3524e98e3e1Schristos 	} else
3534e98e3e1Schristos 	    mec_irq(1);
3544e98e3e1Schristos     }
3554e98e3e1Schristos     if (mec_ersr & 0x20) {
3564e98e3e1Schristos 	if (!(mec_mcr & 0x2000)) {
3574e98e3e1Schristos 	    if (mec_mcr & 0x4000) {
3584e98e3e1Schristos 	        sys_reset();
3594e98e3e1Schristos 	        mec_ersr = 0x8000;
3604e98e3e1Schristos 	        if (sis_verbose)
3614e98e3e1Schristos 	            printf("Error manager reset - MEC hardware error\n");
3624e98e3e1Schristos 	    } else {
3634e98e3e1Schristos 	        sys_halt();
3644e98e3e1Schristos 	        mec_ersr |= 0x2000;
3654e98e3e1Schristos 	        if (sis_verbose)
3664e98e3e1Schristos 	            printf("Error manager halt - MEC hardware error\n");
3674e98e3e1Schristos 	    }
3684e98e3e1Schristos 	} else
3694e98e3e1Schristos 	    mec_irq(1);
3704e98e3e1Schristos     }
3714e98e3e1Schristos }
3724e98e3e1Schristos 
3734e98e3e1Schristos #ifdef ERRINJ
3744e98e3e1Schristos static void
3754e98e3e1Schristos iucomperr()
3764e98e3e1Schristos {
3774e98e3e1Schristos     mec_ersr |= 0x04;
3784e98e3e1Schristos     decode_ersr();
3794e98e3e1Schristos }
3804e98e3e1Schristos #endif
3814e98e3e1Schristos 
3824e98e3e1Schristos static void
3834b169a6bSchristos mecparerror(void)
3844e98e3e1Schristos {
3854e98e3e1Schristos     mec_ersr |= 0x20;
3864e98e3e1Schristos     decode_ersr();
3874e98e3e1Schristos }
3884e98e3e1Schristos 
3894e98e3e1Schristos 
3904e98e3e1Schristos /* IU error mode manager */
3914e98e3e1Schristos 
3924e98e3e1Schristos void
3934b169a6bSchristos error_mode(uint32_t pc)
3944e98e3e1Schristos {
3954e98e3e1Schristos 
3964e98e3e1Schristos     mec_ersr |= 0x1;
3974e98e3e1Schristos     decode_ersr();
3984e98e3e1Schristos }
3994e98e3e1Schristos 
4004e98e3e1Schristos 
4014e98e3e1Schristos /* Check memory settings */
4024e98e3e1Schristos 
4034e98e3e1Schristos static void
4044b169a6bSchristos decode_memcfg(void)
4054e98e3e1Schristos {
4064e98e3e1Schristos     if (rom8) mec_memcfg &= ~0x20000;
4074e98e3e1Schristos     else mec_memcfg |= 0x20000;
4084e98e3e1Schristos 
4094e98e3e1Schristos     mem_ramsz = (256 * 1024) << ((mec_memcfg >> 10) & 7);
4104e98e3e1Schristos     mem_romsz = (128 * 1024) << ((mec_memcfg >> 18) & 7);
4114e98e3e1Schristos 
4124e98e3e1Schristos     if (sparclite_board) {
4134e98e3e1Schristos 	mem_ramstart = RAM_START_SLITE;
4144e98e3e1Schristos 	mem_ramend = RAM_END_SLITE;
4154e98e3e1Schristos 	mem_rammask = RAM_MASK_SLITE;
4164e98e3e1Schristos     }
4174e98e3e1Schristos     else {
4184e98e3e1Schristos 	mem_ramstart = RAM_START;
4194e98e3e1Schristos 	mem_ramend = RAM_END;
4204e98e3e1Schristos 	mem_rammask = RAM_MASK;
4214e98e3e1Schristos     }
4224e98e3e1Schristos     if (sis_verbose)
4234e98e3e1Schristos 	printf("RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n",
4244e98e3e1Schristos 	       mem_ramstart, mem_ramsz >> 10, mem_romsz >> 10);
4254e98e3e1Schristos }
4264e98e3e1Schristos 
4274e98e3e1Schristos static void
4284b169a6bSchristos decode_wcr(void)
4294e98e3e1Schristos {
4304e98e3e1Schristos     mem_ramr_ws = mec_wcr & 3;
4314e98e3e1Schristos     mem_ramw_ws = (mec_wcr >> 2) & 3;
4324e98e3e1Schristos     mem_romr_ws = (mec_wcr >> 4) & 0x0f;
4334e98e3e1Schristos     if (rom8) {
4344e98e3e1Schristos     	if (mem_romr_ws > 0 )  mem_romr_ws--;
4354e98e3e1Schristos 	mem_romr_ws = 5 + (4*mem_romr_ws);
4364e98e3e1Schristos     }
4374e98e3e1Schristos     mem_romw_ws = (mec_wcr >> 8) & 0x0f;
4384e98e3e1Schristos     if (sis_verbose)
4394e98e3e1Schristos 	printf("Waitstates = RAM read: %d, RAM write: %d, ROM read: %d, ROM write: %d\n",
4404e98e3e1Schristos 	       mem_ramr_ws, mem_ramw_ws, mem_romr_ws, mem_romw_ws);
4414e98e3e1Schristos }
4424e98e3e1Schristos 
4434e98e3e1Schristos static void
4444b169a6bSchristos decode_mcr(void)
4454e98e3e1Schristos {
4464e98e3e1Schristos     mem_accprot = (mec_wpr[0] | mec_wpr[1]);
4474e98e3e1Schristos     mem_blockprot = (mec_mcr >> 3) & 1;
4484e98e3e1Schristos     if (sis_verbose && mem_accprot)
4494e98e3e1Schristos 	printf("Memory block write protection enabled\n");
4504e98e3e1Schristos     if (mec_mcr & 0x08000) {
4514e98e3e1Schristos 	mec_ersr |= 0x20;
4524e98e3e1Schristos 	decode_ersr();
4534e98e3e1Schristos     }
4544e98e3e1Schristos     if (sis_verbose && (mec_mcr & 2))
4554e98e3e1Schristos 	printf("Software reset enabled\n");
4564e98e3e1Schristos     if (sis_verbose && (mec_mcr & 1))
4574e98e3e1Schristos 	printf("Power-down mode enabled\n");
4584e98e3e1Schristos }
4594e98e3e1Schristos 
4604e98e3e1Schristos /* Flush ports when simulator stops */
4614e98e3e1Schristos 
4624e98e3e1Schristos void
4634b169a6bSchristos sim_halt(void)
4644e98e3e1Schristos {
4654e98e3e1Schristos #ifdef FAST_UART
4664e98e3e1Schristos     flush_uart();
4674e98e3e1Schristos #endif
4684e98e3e1Schristos }
4694e98e3e1Schristos 
4704e98e3e1Schristos int
4714e98e3e1Schristos sim_stop(SIM_DESC sd)
4724e98e3e1Schristos {
4734e98e3e1Schristos   ctrl_c = 1;
4744e98e3e1Schristos   return 1;
4754e98e3e1Schristos }
4764e98e3e1Schristos 
4774e98e3e1Schristos static void
4784b169a6bSchristos close_port(void)
4794e98e3e1Schristos {
4804e98e3e1Schristos     if (f1open && f1in != stdin)
4814e98e3e1Schristos 	fclose(f1in);
4824e98e3e1Schristos     if (f2open && f2in != stdin)
4834e98e3e1Schristos 	fclose(f2in);
4844e98e3e1Schristos }
4854e98e3e1Schristos 
4864e98e3e1Schristos void
4874b169a6bSchristos exit_sim(void)
4884e98e3e1Schristos {
4894e98e3e1Schristos     close_port();
4904e98e3e1Schristos }
4914e98e3e1Schristos 
4924e98e3e1Schristos static void
4934b169a6bSchristos mec_reset(void)
4944e98e3e1Schristos {
4954e98e3e1Schristos     int             i;
4964e98e3e1Schristos 
4974e98e3e1Schristos     find = 0;
4984e98e3e1Schristos     for (i = 0; i < 2; i++)
4994e98e3e1Schristos 	mec_ssa[i] = mec_sea[i] = mec_wpr[i] = 0;
5004e98e3e1Schristos     mec_mcr = 0x01350014;
5014e98e3e1Schristos     mec_iocr = 0;
5024e98e3e1Schristos     mec_sfsr = 0x078;
5034e98e3e1Schristos     mec_ffar = 0;
5044e98e3e1Schristos     mec_ipr = 0;
5054e98e3e1Schristos     mec_imr = 0x7ffe;
5064e98e3e1Schristos     mec_isr = 0;
5074e98e3e1Schristos     mec_icr = 0;
5084e98e3e1Schristos     mec_ifr = 0;
5094e98e3e1Schristos     mec_memcfg = 0x10000;
5104e98e3e1Schristos     mec_wcr = -1;
5114e98e3e1Schristos     mec_ersr = 0;		/* MEC error and status register */
5124e98e3e1Schristos     mec_tcr = 0;		/* MEC test comtrol register */
5134e98e3e1Schristos 
5144e98e3e1Schristos     decode_memcfg();
5154e98e3e1Schristos     decode_wcr();
5164e98e3e1Schristos     decode_mcr();
5174e98e3e1Schristos 
5184e98e3e1Schristos     posted_irq = 0;
5194e98e3e1Schristos     wnuma = wnumb = 0;
5204e98e3e1Schristos     anum = aind = bnum = bind = 0;
5214e98e3e1Schristos 
5224e98e3e1Schristos     uart_stat_reg = UARTA_SRE | UARTA_HRE | UARTB_SRE | UARTB_HRE;
5234e98e3e1Schristos     uarta_data = uartb_data = UART_THE | UART_TSE;
5244e98e3e1Schristos 
5254e98e3e1Schristos     rtc_counter = 0xffffffff;
5264e98e3e1Schristos     rtc_reload = 0xffffffff;
5274e98e3e1Schristos     rtc_scaler = 0xff;
5284e98e3e1Schristos     rtc_enabled = 0;
5294e98e3e1Schristos     rtc_cr = 0;
5304e98e3e1Schristos     rtc_se = 0;
5314e98e3e1Schristos 
5324e98e3e1Schristos     gpt_counter = 0xffffffff;
5334e98e3e1Schristos     gpt_reload = 0xffffffff;
5344e98e3e1Schristos     gpt_scaler = 0xffff;
5354e98e3e1Schristos     gpt_enabled = 0;
5364e98e3e1Schristos     gpt_cr = 0;
5374e98e3e1Schristos     gpt_se = 0;
5384e98e3e1Schristos 
5394e98e3e1Schristos     wdog_scaler = 255;
5404e98e3e1Schristos     wdog_rst_delay = 255;
5414e98e3e1Schristos     wdog_counter = 0xffff;
5424e98e3e1Schristos     wdog_rston = 0;
5434e98e3e1Schristos     wdog_status = init;
5444e98e3e1Schristos 
5454e98e3e1Schristos #ifdef ERA
5464e98e3e1Schristos     erareg = 0;
5474e98e3e1Schristos #endif
5484e98e3e1Schristos 
5494e98e3e1Schristos }
5504e98e3e1Schristos 
5514e98e3e1Schristos 
5524e98e3e1Schristos 
5534e98e3e1Schristos static void
5544b169a6bSchristos mec_intack(int32_t level)
5554e98e3e1Schristos {
5564e98e3e1Schristos     int             irq_test;
5574e98e3e1Schristos 
5584e98e3e1Schristos     if (sis_verbose)
5594e98e3e1Schristos 	printf("interrupt %d acknowledged\n", level);
5604e98e3e1Schristos     irq_test = mec_tcr & 0x80000;
5614e98e3e1Schristos     if ((irq_test) && (mec_ifr & (1 << level)))
5624e98e3e1Schristos 	mec_ifr &= ~(1 << level);
5634e98e3e1Schristos     else
5644e98e3e1Schristos 	mec_ipr &= ~(1 << level);
5654e98e3e1Schristos    chk_irq();
5664e98e3e1Schristos }
5674e98e3e1Schristos 
5684e98e3e1Schristos static void
5694b169a6bSchristos chk_irq(void)
5704e98e3e1Schristos {
5714b169a6bSchristos     int32_t           i;
5724b169a6bSchristos     uint32_t          itmp;
5734e98e3e1Schristos     int		    old_irl;
5744e98e3e1Schristos 
5754e98e3e1Schristos     old_irl = ext_irl;
5764e98e3e1Schristos     if (mec_tcr & 0x80000) itmp = mec_ifr;
5774e98e3e1Schristos     else itmp  = 0;
5784e98e3e1Schristos     itmp = ((mec_ipr | itmp) & ~mec_imr) & 0x0fffe;
5794e98e3e1Schristos     ext_irl = 0;
5804e98e3e1Schristos     if (itmp != 0) {
5814e98e3e1Schristos 	for (i = 15; i > 0; i--) {
5824e98e3e1Schristos 	    if (((itmp >> i) & 1) != 0) {
5834e98e3e1Schristos 		if ((sis_verbose) && (i > old_irl))
5844e98e3e1Schristos 		    printf("IU irl: %d\n", i);
5854e98e3e1Schristos 		ext_irl = i;
5864e98e3e1Schristos 	        set_int(i, mec_intack, i);
5874e98e3e1Schristos 		break;
5884e98e3e1Schristos 	    }
5894e98e3e1Schristos 	}
5904e98e3e1Schristos     }
5914e98e3e1Schristos }
5924e98e3e1Schristos 
5934e98e3e1Schristos static void
5944b169a6bSchristos mec_irq(int32_t level)
5954e98e3e1Schristos {
5964e98e3e1Schristos     mec_ipr |= (1 << level);
5974e98e3e1Schristos     chk_irq();
5984e98e3e1Schristos }
5994e98e3e1Schristos 
6004e98e3e1Schristos static void
6014b169a6bSchristos set_sfsr(uint32_t fault, uint32_t addr, uint32_t asi, uint32_t read)
6024e98e3e1Schristos {
6034e98e3e1Schristos     if ((asi == 0xa) || (asi == 0xb)) {
6044e98e3e1Schristos 	mec_ffar = addr;
6054e98e3e1Schristos 	mec_sfsr = (fault << 3) | (!read << 15);
6064e98e3e1Schristos 	mec_sfsr |= ((mec_sfsr & 1) ^ 1) | (mec_sfsr & 1);
6074e98e3e1Schristos 	switch (asi) {
6084e98e3e1Schristos 	case 0xa:
6094e98e3e1Schristos 	    mec_sfsr |= 0x0004;
6104e98e3e1Schristos 	    break;
6114e98e3e1Schristos 	case 0xb:
6124e98e3e1Schristos 	    mec_sfsr |= 0x1004;
6134e98e3e1Schristos 	    break;
6144e98e3e1Schristos 	}
6154e98e3e1Schristos     }
6164e98e3e1Schristos }
6174e98e3e1Schristos 
6184b169a6bSchristos static int32_t
6194b169a6bSchristos mec_read(uint32_t addr, uint32_t asi, uint32_t *data)
6204e98e3e1Schristos {
6214e98e3e1Schristos 
6224e98e3e1Schristos     switch (addr & 0x0ff) {
6234e98e3e1Schristos 
6244e98e3e1Schristos     case MEC_MCR:		/* 0x00 */
6254e98e3e1Schristos 	*data = mec_mcr;
6264e98e3e1Schristos 	break;
6274e98e3e1Schristos 
6284e98e3e1Schristos     case MEC_MEMCFG:		/* 0x10 */
6294e98e3e1Schristos 	*data = mec_memcfg;
6304e98e3e1Schristos 	break;
6314e98e3e1Schristos 
6324e98e3e1Schristos     case MEC_IOCR:
6334e98e3e1Schristos 	*data = mec_iocr;	/* 0x14 */
6344e98e3e1Schristos 	break;
6354e98e3e1Schristos 
6364e98e3e1Schristos     case MEC_SSA1:		/* 0x20 */
6374e98e3e1Schristos 	*data = mec_ssa[0] | (mec_wpr[0] << 23);
6384e98e3e1Schristos 	break;
6394e98e3e1Schristos     case MEC_SEA1:		/* 0x24 */
6404e98e3e1Schristos 	*data = mec_sea[0];
6414e98e3e1Schristos 	break;
6424e98e3e1Schristos     case MEC_SSA2:		/* 0x28 */
6434e98e3e1Schristos 	*data = mec_ssa[1] | (mec_wpr[1] << 23);
6444e98e3e1Schristos 	break;
6454e98e3e1Schristos     case MEC_SEA2:		/* 0x2c */
6464e98e3e1Schristos 	*data = mec_sea[1];
6474e98e3e1Schristos 	break;
6484e98e3e1Schristos 
6494e98e3e1Schristos     case MEC_ISR:		/* 0x44 */
6504e98e3e1Schristos 	*data = mec_isr;
6514e98e3e1Schristos 	break;
6524e98e3e1Schristos 
6534e98e3e1Schristos     case MEC_IPR:		/* 0x48 */
6544e98e3e1Schristos 	*data = mec_ipr;
6554e98e3e1Schristos 	break;
6564e98e3e1Schristos 
6574e98e3e1Schristos     case MEC_IMR:		/* 0x4c */
6584e98e3e1Schristos 	*data = mec_imr;
6594e98e3e1Schristos 	break;
6604e98e3e1Schristos 
6614e98e3e1Schristos     case MEC_IFR:		/* 0x54 */
6624e98e3e1Schristos 	*data = mec_ifr;
6634e98e3e1Schristos 	break;
6644e98e3e1Schristos 
6654e98e3e1Schristos     case MEC_RTC_COUNTER:	/* 0x80 */
6664e98e3e1Schristos 	*data = rtc_counter_read();
6674e98e3e1Schristos 	break;
6684e98e3e1Schristos     case MEC_RTC_SCALER:	/* 0x84 */
6694e98e3e1Schristos 	if (rtc_enabled)
6704e98e3e1Schristos 	    *data = rtc_scaler - (now() - rtc_scaler_start);
6714e98e3e1Schristos 	else
6724e98e3e1Schristos 	    *data = rtc_scaler;
6734e98e3e1Schristos 	break;
6744e98e3e1Schristos 
6754e98e3e1Schristos     case MEC_GPT_COUNTER:	/* 0x88 */
6764e98e3e1Schristos 	*data = gpt_counter_read();
6774e98e3e1Schristos 	break;
6784e98e3e1Schristos 
6794e98e3e1Schristos     case MEC_GPT_SCALER:	/* 0x8c */
6804e98e3e1Schristos 	if (rtc_enabled)
6814e98e3e1Schristos 	    *data = gpt_scaler - (now() - gpt_scaler_start);
6824e98e3e1Schristos 	else
6834e98e3e1Schristos 	    *data = gpt_scaler;
6844e98e3e1Schristos 	break;
6854e98e3e1Schristos 
6864e98e3e1Schristos 
6874e98e3e1Schristos     case MEC_SFSR:		/* 0xA0 */
6884e98e3e1Schristos 	*data = mec_sfsr;
6894e98e3e1Schristos 	break;
6904e98e3e1Schristos 
6914e98e3e1Schristos     case MEC_FFAR:		/* 0xA4 */
6924e98e3e1Schristos 	*data = mec_ffar;
6934e98e3e1Schristos 	break;
6944e98e3e1Schristos 
6954e98e3e1Schristos     case SIM_LOAD:
6964e98e3e1Schristos 	fname[find] = 0;
6974e98e3e1Schristos 	if (find == 0)
6984e98e3e1Schristos 	    strcpy(fname, "simload");
6994e98e3e1Schristos 	find = bfd_load(fname);
7004e98e3e1Schristos  	if (find == -1)
7014e98e3e1Schristos 	    *data = 0;
7024e98e3e1Schristos 	else
7034e98e3e1Schristos 	    *data = 1;
7044e98e3e1Schristos 	find = 0;
7054e98e3e1Schristos 	break;
7064e98e3e1Schristos 
7074e98e3e1Schristos     case MEC_ERSR:		/* 0xB0 */
7084e98e3e1Schristos 	*data = mec_ersr;
7094e98e3e1Schristos 	break;
7104e98e3e1Schristos 
7114e98e3e1Schristos     case MEC_TCR:		/* 0xD0 */
7124e98e3e1Schristos 	*data = mec_tcr;
7134e98e3e1Schristos 	break;
7144e98e3e1Schristos 
7154e98e3e1Schristos     case MEC_UARTA:		/* 0xE0 */
7164e98e3e1Schristos     case MEC_UARTB:		/* 0xE4 */
7174e98e3e1Schristos 	if (asi != 0xb) {
7184e98e3e1Schristos 	    set_sfsr(MEC_ACC, addr, asi, 1);
719212397c6Schristos 	    return 1;
7204e98e3e1Schristos 	}
7214e98e3e1Schristos 	*data = read_uart(addr);
7224e98e3e1Schristos 	break;
7234e98e3e1Schristos 
7244e98e3e1Schristos     case MEC_UART_CTRL:		/* 0xE8 */
7254e98e3e1Schristos 
7264e98e3e1Schristos 	*data = read_uart(addr);
7274e98e3e1Schristos 	break;
7284e98e3e1Schristos 
729212397c6Schristos     case 0xF4:		/* simulator RAM size in bytes */
730212397c6Schristos 	*data = 4096*1024;
731212397c6Schristos 	break;
732212397c6Schristos 
733212397c6Schristos     case 0xF8:		/* simulator ROM size in bytes */
734212397c6Schristos 	*data = 1024*1024;
735212397c6Schristos 	break;
736212397c6Schristos 
7374e98e3e1Schristos     default:
7384e98e3e1Schristos 	set_sfsr(MEC_ACC, addr, asi, 1);
739212397c6Schristos 	return 1;
7404e98e3e1Schristos 	break;
7414e98e3e1Schristos     }
742212397c6Schristos     return MOK;
7434e98e3e1Schristos }
7444e98e3e1Schristos 
7454e98e3e1Schristos static int
7464b169a6bSchristos mec_write(uint32_t addr, uint32_t data)
7474e98e3e1Schristos {
7484e98e3e1Schristos     if (sis_verbose > 1)
7494e98e3e1Schristos 	printf("MEC write a: %08x, d: %08x\n",addr,data);
7504e98e3e1Schristos     switch (addr & 0x0ff) {
7514e98e3e1Schristos 
7524e98e3e1Schristos     case MEC_MCR:
7534e98e3e1Schristos 	mec_mcr = data;
7544e98e3e1Schristos 	decode_mcr();
7554e98e3e1Schristos         if (mec_mcr & 0x08000) mecparerror();
7564e98e3e1Schristos 	break;
7574e98e3e1Schristos 
7584e98e3e1Schristos     case MEC_SFR:
7594e98e3e1Schristos 	if (mec_mcr & 0x2) {
7604e98e3e1Schristos 	    sys_reset();
7614e98e3e1Schristos 	    mec_ersr = 0x4000;
7624e98e3e1Schristos     	    if (sis_verbose)
7634e98e3e1Schristos 	    	printf(" Software reset issued\n");
7644e98e3e1Schristos 	}
7654e98e3e1Schristos 	break;
7664e98e3e1Schristos 
7674e98e3e1Schristos     case MEC_IOCR:
7684e98e3e1Schristos 	mec_iocr = data;
7694e98e3e1Schristos         if (mec_iocr & 0xC0C0C0C0) mecparerror();
7704e98e3e1Schristos 	break;
7714e98e3e1Schristos 
7724e98e3e1Schristos     case MEC_SSA1:		/* 0x20 */
7734e98e3e1Schristos         if (data & 0xFE000000) mecparerror();
7744e98e3e1Schristos 	mec_ssa[0] = data & 0x7fffff;
7754e98e3e1Schristos 	mec_wpr[0] = (data >> 23) & 0x03;
7764e98e3e1Schristos 	mem_accprot = mec_wpr[0] || mec_wpr[1];
7774e98e3e1Schristos 	if (sis_verbose && mec_wpr[0])
7784e98e3e1Schristos 	    printf("Segment 1 memory protection enabled (0x02%06x - 0x02%06x)\n",
7794e98e3e1Schristos 		   mec_ssa[0] << 2, mec_sea[0] << 2);
7804e98e3e1Schristos 	break;
7814e98e3e1Schristos     case MEC_SEA1:		/* 0x24 */
7824e98e3e1Schristos         if (data & 0xFF800000) mecparerror();
7834e98e3e1Schristos 	mec_sea[0] = data & 0x7fffff;
7844e98e3e1Schristos 	break;
7854e98e3e1Schristos     case MEC_SSA2:		/* 0x28 */
7864e98e3e1Schristos         if (data & 0xFE000000) mecparerror();
7874e98e3e1Schristos 	mec_ssa[1] = data & 0x7fffff;
7884e98e3e1Schristos 	mec_wpr[1] = (data >> 23) & 0x03;
7894e98e3e1Schristos 	mem_accprot = mec_wpr[0] || mec_wpr[1];
7904e98e3e1Schristos 	if (sis_verbose && mec_wpr[1])
7914e98e3e1Schristos 	    printf("Segment 2 memory protection enabled (0x02%06x - 0x02%06x)\n",
7924e98e3e1Schristos 		   mec_ssa[1] << 2, mec_sea[1] << 2);
7934e98e3e1Schristos 	break;
7944e98e3e1Schristos     case MEC_SEA2:		/* 0x2c */
7954e98e3e1Schristos         if (data & 0xFF800000) mecparerror();
7964e98e3e1Schristos 	mec_sea[1] = data & 0x7fffff;
7974e98e3e1Schristos 	break;
7984e98e3e1Schristos 
7994e98e3e1Schristos     case MEC_UARTA:
8004e98e3e1Schristos     case MEC_UARTB:
8014e98e3e1Schristos         if (data & 0xFFFFFF00) mecparerror();
802*1f4e7eb9Schristos         ATTRIBUTE_FALLTHROUGH;
8034e98e3e1Schristos     case MEC_UART_CTRL:
8044e98e3e1Schristos         if (data & 0xFF00FF00) mecparerror();
8054e98e3e1Schristos 	write_uart(addr, data);
8064e98e3e1Schristos 	break;
8074e98e3e1Schristos 
8084e98e3e1Schristos     case MEC_GPT_RELOAD:
8094e98e3e1Schristos 	gpt_reload_set(data);
8104e98e3e1Schristos 	break;
8114e98e3e1Schristos 
8124e98e3e1Schristos     case MEC_GPT_SCALER:
8134e98e3e1Schristos         if (data & 0xFFFF0000) mecparerror();
8144e98e3e1Schristos 	gpt_scaler_set(data);
8154e98e3e1Schristos 	break;
8164e98e3e1Schristos 
8174e98e3e1Schristos     case MEC_TIMER_CTRL:
8184e98e3e1Schristos         if (data & 0xFFFFF0F0) mecparerror();
8194e98e3e1Schristos 	timer_ctrl(data);
8204e98e3e1Schristos 	break;
8214e98e3e1Schristos 
8224e98e3e1Schristos     case MEC_RTC_RELOAD:
8234e98e3e1Schristos 	rtc_reload_set(data);
8244e98e3e1Schristos 	break;
8254e98e3e1Schristos 
8264e98e3e1Schristos     case MEC_RTC_SCALER:
8274e98e3e1Schristos         if (data & 0xFFFFFF00) mecparerror();
8284e98e3e1Schristos 	rtc_scaler_set(data);
8294e98e3e1Schristos 	break;
8304e98e3e1Schristos 
8314e98e3e1Schristos     case MEC_SFSR:		/* 0xA0 */
8324e98e3e1Schristos         if (data & 0xFFFF0880) mecparerror();
8334e98e3e1Schristos 	mec_sfsr = 0x78;
8344e98e3e1Schristos 	break;
8354e98e3e1Schristos 
8364e98e3e1Schristos     case MEC_ISR:
8374e98e3e1Schristos         if (data & 0xFFFFE000) mecparerror();
8384e98e3e1Schristos 	mec_isr = data;
8394e98e3e1Schristos 	break;
8404e98e3e1Schristos 
8414e98e3e1Schristos     case MEC_IMR:		/* 0x4c */
8424e98e3e1Schristos 
8434e98e3e1Schristos         if (data & 0xFFFF8001) mecparerror();
8444e98e3e1Schristos 	mec_imr = data & 0x7ffe;
8454e98e3e1Schristos 	chk_irq();
8464e98e3e1Schristos 	break;
8474e98e3e1Schristos 
8484e98e3e1Schristos     case MEC_ICR:		/* 0x50 */
8494e98e3e1Schristos 
8504e98e3e1Schristos         if (data & 0xFFFF0001) mecparerror();
8514e98e3e1Schristos 	mec_ipr &= ~data & 0x0fffe;
8524e98e3e1Schristos 	chk_irq();
8534e98e3e1Schristos 	break;
8544e98e3e1Schristos 
8554e98e3e1Schristos     case MEC_IFR:		/* 0x54 */
8564e98e3e1Schristos 
8574e98e3e1Schristos         if (mec_tcr & 0x080000) {
8584e98e3e1Schristos             if (data & 0xFFFF0001) mecparerror();
8594e98e3e1Schristos 	    mec_ifr = data & 0xfffe;
8604e98e3e1Schristos 	    chk_irq();
8614e98e3e1Schristos 	}
8624e98e3e1Schristos 	break;
8634e98e3e1Schristos     case SIM_LOAD:
8644e98e3e1Schristos 	fname[find++] = (char) data;
8654e98e3e1Schristos 	break;
8664e98e3e1Schristos 
8674e98e3e1Schristos 
8684e98e3e1Schristos     case MEC_MEMCFG:		/* 0x10 */
8694e98e3e1Schristos         if (data & 0xC0E08000) mecparerror();
8704e98e3e1Schristos 	mec_memcfg = data;
8714e98e3e1Schristos 	decode_memcfg();
8724e98e3e1Schristos 	if (mec_memcfg & 0xc0e08000)
8734e98e3e1Schristos 	    mecparerror();
8744e98e3e1Schristos 	break;
8754e98e3e1Schristos 
8764e98e3e1Schristos     case MEC_WCR:		/* 0x18 */
8774e98e3e1Schristos 	mec_wcr = data;
8784e98e3e1Schristos 	decode_wcr();
8794e98e3e1Schristos 	break;
8804e98e3e1Schristos 
8814e98e3e1Schristos     case MEC_ERSR:		/* 0xB0 */
8824e98e3e1Schristos 	if (mec_tcr & 0x100000)
8834e98e3e1Schristos 	  if (data & 0xFFFFEFC0) mecparerror();
8844e98e3e1Schristos 	    mec_ersr = data & 0x103f;
8854e98e3e1Schristos 	break;
8864e98e3e1Schristos 
8874e98e3e1Schristos     case MEC_TCR:		/* 0xD0 */
8884e98e3e1Schristos         if (data & 0xFFE1FFC0) mecparerror();
8894e98e3e1Schristos 	mec_tcr = data & 0x1e003f;
8904e98e3e1Schristos 	break;
8914e98e3e1Schristos 
8924e98e3e1Schristos     case MEC_WDOG:		/* 0x60 */
8934e98e3e1Schristos 	wdog_scaler = (data >> 16) & 0x0ff;
8944e98e3e1Schristos 	wdog_counter = data & 0x0ffff;
8954e98e3e1Schristos 	wdog_rst_delay = data >> 24;
8964e98e3e1Schristos 	wdog_rston = 0;
8974e98e3e1Schristos 	if (wdog_status == stopped)
8984e98e3e1Schristos 	    wdog_start();
8994e98e3e1Schristos 	wdog_status = enabled;
9004e98e3e1Schristos 	break;
9014e98e3e1Schristos 
9024e98e3e1Schristos     case MEC_TRAPD:		/* 0x64 */
9034e98e3e1Schristos 	if (wdog_status == init) {
9044e98e3e1Schristos 	    wdog_status = disabled;
9054e98e3e1Schristos 	    if (sis_verbose)
9064e98e3e1Schristos 		printf("Watchdog disabled\n");
9074e98e3e1Schristos 	}
9084e98e3e1Schristos 	break;
9094e98e3e1Schristos 
9104e98e3e1Schristos     case MEC_PWDR:
9114e98e3e1Schristos 	if (mec_mcr & 1)
9124e98e3e1Schristos 	    wait_for_irq();
9134e98e3e1Schristos 	break;
9144e98e3e1Schristos 
9154e98e3e1Schristos     default:
9164e98e3e1Schristos 	set_sfsr(MEC_ACC, addr, 0xb, 0);
917212397c6Schristos 	return 1;
9184e98e3e1Schristos 	break;
9194e98e3e1Schristos     }
920212397c6Schristos     return MOK;
9214e98e3e1Schristos }
9224e98e3e1Schristos 
9234e98e3e1Schristos 
9244e98e3e1Schristos /* MEC UARTS */
9254e98e3e1Schristos 
9264e98e3e1Schristos static int      ifd1 = -1, ifd2 = -1, ofd1 = -1, ofd2 = -1;
9274e98e3e1Schristos 
9284e98e3e1Schristos void
9294b169a6bSchristos init_stdio(void)
9304e98e3e1Schristos {
9314e98e3e1Schristos     if (dumbio)
9324e98e3e1Schristos         return; /* do nothing */
9334b169a6bSchristos #ifdef HAVE_TERMIOS_H
9344e98e3e1Schristos     if (!ifd1)
9354e98e3e1Schristos 	tcsetattr(0, TCSANOW, &ioc1);
9364e98e3e1Schristos     if (!ifd2)
9374e98e3e1Schristos 	tcsetattr(0, TCSANOW, &ioc2);
9384b169a6bSchristos #endif
9394e98e3e1Schristos }
9404e98e3e1Schristos 
9414e98e3e1Schristos void
9424b169a6bSchristos restore_stdio(void)
9434e98e3e1Schristos {
9444e98e3e1Schristos     if (dumbio)
9454e98e3e1Schristos         return; /* do nothing */
9464b169a6bSchristos #ifdef HAVE_TERMIOS_H
9474e98e3e1Schristos     if (!ifd1)
9484e98e3e1Schristos 	tcsetattr(0, TCSANOW, &iocold1);
9494e98e3e1Schristos     if (!ifd2)
9504e98e3e1Schristos 	tcsetattr(0, TCSANOW, &iocold2);
9514b169a6bSchristos #endif
9524e98e3e1Schristos }
9534e98e3e1Schristos 
9544e98e3e1Schristos #define DO_STDIO_READ( _fd_, _buf_, _len_ )          \
9554e98e3e1Schristos              ( dumbio                                \
9564e98e3e1Schristos                ? (0) /* no bytes read, no delay */   \
9574e98e3e1Schristos                : read( _fd_, _buf_, _len_ ) )
9584e98e3e1Schristos 
9594e98e3e1Schristos 
9604e98e3e1Schristos static void
9614b169a6bSchristos port_init(void)
9624e98e3e1Schristos {
9634e98e3e1Schristos 
9644e98e3e1Schristos     if (uben) {
9654e98e3e1Schristos     f2in = stdin;
9664e98e3e1Schristos     f1in = NULL;
9674e98e3e1Schristos     f2out = stdout;
9684e98e3e1Schristos     f1out = NULL;
9694e98e3e1Schristos     } else {
9704e98e3e1Schristos     f1in = stdin;
9714e98e3e1Schristos     f2in = NULL;
9724e98e3e1Schristos     f1out = stdout;
9734e98e3e1Schristos     f2out = NULL;
9744e98e3e1Schristos     }
9754b169a6bSchristos     if (uart_dev1[0] != 0) {
9764e98e3e1Schristos 	if ((fd1 = open(uart_dev1, O_RDWR | O_NONBLOCK)) < 0) {
9774e98e3e1Schristos 	    printf("Warning, couldn't open output device %s\n", uart_dev1);
9784e98e3e1Schristos 	} else {
9794e98e3e1Schristos 	    if (sis_verbose)
9804e98e3e1Schristos 		printf("serial port A on %s\n", uart_dev1);
9814e98e3e1Schristos 	    f1in = f1out = fdopen(fd1, "r+");
9824e98e3e1Schristos 	    setbuf(f1out, NULL);
9834e98e3e1Schristos 	    f1open = 1;
9844e98e3e1Schristos 	}
9854b169a6bSchristos     }
9864e98e3e1Schristos     if (f1in) ifd1 = fileno(f1in);
9874e98e3e1Schristos     if (ifd1 == 0) {
9884e98e3e1Schristos 	if (sis_verbose)
9894e98e3e1Schristos 	    printf("serial port A on stdin/stdout\n");
9904e98e3e1Schristos         if (!dumbio) {
9914b169a6bSchristos #ifdef HAVE_TERMIOS_H
9924e98e3e1Schristos             tcgetattr(ifd1, &ioc1);
9934e98e3e1Schristos             iocold1 = ioc1;
9944e98e3e1Schristos             ioc1.c_lflag &= ~(ICANON | ECHO);
9954e98e3e1Schristos             ioc1.c_cc[VMIN] = 0;
9964e98e3e1Schristos             ioc1.c_cc[VTIME] = 0;
9974b169a6bSchristos #endif
9984e98e3e1Schristos         }
9994e98e3e1Schristos 	f1open = 1;
10004e98e3e1Schristos     }
10014e98e3e1Schristos 
10024e98e3e1Schristos     if (f1out) {
10034e98e3e1Schristos 	ofd1 = fileno(f1out);
10044e98e3e1Schristos     	if (!dumbio && ofd1 == 1) setbuf(f1out, NULL);
10054e98e3e1Schristos     }
10064e98e3e1Schristos 
10074b169a6bSchristos     if (uart_dev2[0] != 0) {
10084e98e3e1Schristos 	if ((fd2 = open(uart_dev2, O_RDWR | O_NONBLOCK)) < 0) {
10094e98e3e1Schristos 	    printf("Warning, couldn't open output device %s\n", uart_dev2);
10104e98e3e1Schristos 	} else {
10114e98e3e1Schristos 	    if (sis_verbose)
10124e98e3e1Schristos 		printf("serial port B on %s\n", uart_dev2);
10134e98e3e1Schristos 	    f2in = f2out = fdopen(fd2, "r+");
10144e98e3e1Schristos 	    setbuf(f2out, NULL);
10154e98e3e1Schristos 	    f2open = 1;
10164e98e3e1Schristos 	}
10174b169a6bSchristos     }
10184e98e3e1Schristos     if (f2in)  ifd2 = fileno(f2in);
10194e98e3e1Schristos     if (ifd2 == 0) {
10204e98e3e1Schristos 	if (sis_verbose)
10214e98e3e1Schristos 	    printf("serial port B on stdin/stdout\n");
10224e98e3e1Schristos         if (!dumbio) {
10234b169a6bSchristos #ifdef HAVE_TERMIOS_H
10244e98e3e1Schristos             tcgetattr(ifd2, &ioc2);
10254e98e3e1Schristos             iocold2 = ioc2;
10264e98e3e1Schristos             ioc2.c_lflag &= ~(ICANON | ECHO);
10274e98e3e1Schristos             ioc2.c_cc[VMIN] = 0;
10284e98e3e1Schristos             ioc2.c_cc[VTIME] = 0;
10294b169a6bSchristos #endif
10304e98e3e1Schristos         }
10314e98e3e1Schristos 	f2open = 1;
10324e98e3e1Schristos     }
10334e98e3e1Schristos 
10344e98e3e1Schristos     if (f2out) {
10354e98e3e1Schristos 	ofd2 = fileno(f2out);
10364e98e3e1Schristos         if (!dumbio && ofd2 == 1) setbuf(f2out, NULL);
10374e98e3e1Schristos     }
10384e98e3e1Schristos 
10394e98e3e1Schristos     wnuma = wnumb = 0;
10404e98e3e1Schristos 
10414e98e3e1Schristos }
10424e98e3e1Schristos 
10434b169a6bSchristos static uint32_t
10444b169a6bSchristos read_uart(uint32_t addr)
10454e98e3e1Schristos {
10464e98e3e1Schristos     switch (addr & 0xff) {
10474e98e3e1Schristos 
10484e98e3e1Schristos     case 0xE0:			/* UART 1 */
10494e98e3e1Schristos #ifndef _WIN32
10504e98e3e1Schristos #ifdef FAST_UART
10514e98e3e1Schristos 
10524e98e3e1Schristos 	if (aind < anum) {
10534e98e3e1Schristos 	    if ((aind + 1) < anum)
10544e98e3e1Schristos 		mec_irq(4);
10554b169a6bSchristos 	    return (0x700 | (uint32_t) aq[aind++]);
10564e98e3e1Schristos 	} else {
10574e98e3e1Schristos 	    if (f1open) {
10584e98e3e1Schristos 	        anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
10594e98e3e1Schristos 	    }
10604e98e3e1Schristos 	    if (anum > 0) {
10614e98e3e1Schristos 		aind = 0;
10624e98e3e1Schristos 		if ((aind + 1) < anum)
10634e98e3e1Schristos 		    mec_irq(4);
10644b169a6bSchristos 		return (0x700 | (uint32_t) aq[aind++]);
10654e98e3e1Schristos 	    } else {
10664b169a6bSchristos 		return (0x600 | (uint32_t) aq[aind]);
10674e98e3e1Schristos 	    }
10684e98e3e1Schristos 
10694e98e3e1Schristos 	}
10704e98e3e1Schristos #else
1071*1f4e7eb9Schristos 	unsigned tmp = uarta_data;
10724e98e3e1Schristos 	uarta_data &= ~UART_DR;
10734e98e3e1Schristos 	uart_stat_reg &= ~UARTA_DR;
10744e98e3e1Schristos 	return tmp;
10754e98e3e1Schristos #endif
10764e98e3e1Schristos #else
1077212397c6Schristos 	return 0;
10784e98e3e1Schristos #endif
10794e98e3e1Schristos 	break;
10804e98e3e1Schristos 
10814e98e3e1Schristos     case 0xE4:			/* UART 2 */
10824e98e3e1Schristos #ifndef _WIN32
10834e98e3e1Schristos #ifdef FAST_UART
10844e98e3e1Schristos 	if (bind < bnum) {
10854e98e3e1Schristos 	    if ((bind + 1) < bnum)
10864e98e3e1Schristos 		mec_irq(5);
10874b169a6bSchristos 	    return (0x700 | (uint32_t) bq[bind++]);
10884e98e3e1Schristos 	} else {
10894e98e3e1Schristos 	    if (f2open) {
10904e98e3e1Schristos 		bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
10914e98e3e1Schristos 	    }
10924e98e3e1Schristos 	    if (bnum > 0) {
10934e98e3e1Schristos 		bind = 0;
10944e98e3e1Schristos 		if ((bind + 1) < bnum)
10954e98e3e1Schristos 		    mec_irq(5);
10964b169a6bSchristos 		return (0x700 | (uint32_t) bq[bind++]);
10974e98e3e1Schristos 	    } else {
10984b169a6bSchristos 		return (0x600 | (uint32_t) bq[bind]);
10994e98e3e1Schristos 	    }
11004e98e3e1Schristos 
11014e98e3e1Schristos 	}
11024e98e3e1Schristos #else
1103*1f4e7eb9Schristos 	unsigned tmp = uartb_data;
11044e98e3e1Schristos 	uartb_data &= ~UART_DR;
11054e98e3e1Schristos 	uart_stat_reg &= ~UARTB_DR;
11064e98e3e1Schristos 	return tmp;
11074e98e3e1Schristos #endif
11084e98e3e1Schristos #else
1109212397c6Schristos 	return 0;
11104e98e3e1Schristos #endif
11114e98e3e1Schristos 	break;
11124e98e3e1Schristos 
11134e98e3e1Schristos     case 0xE8:			/* UART status register	 */
11144e98e3e1Schristos #ifndef _WIN32
11154e98e3e1Schristos #ifdef FAST_UART
11164e98e3e1Schristos 
11174e98e3e1Schristos 	Ucontrol = 0;
11184e98e3e1Schristos 	if (aind < anum) {
11194e98e3e1Schristos 	    Ucontrol |= 0x00000001;
11204e98e3e1Schristos 	} else {
11214e98e3e1Schristos 	    if (f1open) {
11224e98e3e1Schristos 	        anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
11234e98e3e1Schristos             }
11244e98e3e1Schristos 	    if (anum > 0) {
11254e98e3e1Schristos 		Ucontrol |= 0x00000001;
11264e98e3e1Schristos 		aind = 0;
11274e98e3e1Schristos 		mec_irq(4);
11284e98e3e1Schristos 	    }
11294e98e3e1Schristos 	}
11304e98e3e1Schristos 	if (bind < bnum) {
11314e98e3e1Schristos 	    Ucontrol |= 0x00010000;
11324e98e3e1Schristos 	} else {
11334e98e3e1Schristos 	    if (f2open) {
11344e98e3e1Schristos 		bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
11354e98e3e1Schristos 	    }
11364e98e3e1Schristos 	    if (bnum > 0) {
11374e98e3e1Schristos 		Ucontrol |= 0x00010000;
11384e98e3e1Schristos 		bind = 0;
11394e98e3e1Schristos 		mec_irq(5);
11404e98e3e1Schristos 	    }
11414e98e3e1Schristos 	}
11424e98e3e1Schristos 
11434e98e3e1Schristos 	Ucontrol |= 0x00060006;
1144212397c6Schristos 	return Ucontrol;
11454e98e3e1Schristos #else
1146212397c6Schristos 	return uart_stat_reg;
11474e98e3e1Schristos #endif
11484e98e3e1Schristos #else
1149212397c6Schristos 	return 0x00060006;
11504e98e3e1Schristos #endif
11514e98e3e1Schristos 	break;
11524e98e3e1Schristos     default:
11534e98e3e1Schristos 	if (sis_verbose)
11544e98e3e1Schristos 	    printf("Read from unimplemented MEC register (%x)\n", addr);
11554e98e3e1Schristos 
11564e98e3e1Schristos     }
1157212397c6Schristos     return 0;
11584e98e3e1Schristos }
11594e98e3e1Schristos 
11604e98e3e1Schristos static void
11614b169a6bSchristos write_uart(uint32_t addr, uint32_t data)
11624e98e3e1Schristos {
11634e98e3e1Schristos     unsigned char   c;
11644e98e3e1Schristos 
11654e98e3e1Schristos     c = (unsigned char) data;
11664e98e3e1Schristos     switch (addr & 0xff) {
11674e98e3e1Schristos 
11684e98e3e1Schristos     case 0xE0:			/* UART A */
11694e98e3e1Schristos #ifdef FAST_UART
11704e98e3e1Schristos 	if (f1open) {
11714e98e3e1Schristos 	    if (wnuma < UARTBUF)
11724e98e3e1Schristos 	        wbufa[wnuma++] = c;
11734e98e3e1Schristos 	    else {
11744e98e3e1Schristos 	        while (wnuma)
11754e98e3e1Schristos 		    wnuma -= fwrite(wbufa, 1, wnuma, f1out);
11764e98e3e1Schristos 	        wbufa[wnuma++] = c;
11774e98e3e1Schristos 	    }
11784e98e3e1Schristos 	}
11794e98e3e1Schristos 	mec_irq(4);
11804e98e3e1Schristos #else
11814e98e3e1Schristos 	if (uart_stat_reg & UARTA_SRE) {
11824e98e3e1Schristos 	    uarta_sreg = c;
11834e98e3e1Schristos 	    uart_stat_reg &= ~UARTA_SRE;
11844e98e3e1Schristos 	    event(uarta_tx, 0, UART_TX_TIME);
11854e98e3e1Schristos 	} else {
11864e98e3e1Schristos 	    uarta_hreg = c;
11874e98e3e1Schristos 	    uart_stat_reg &= ~UARTA_HRE;
11884e98e3e1Schristos 	}
11894e98e3e1Schristos #endif
11904e98e3e1Schristos 	break;
11914e98e3e1Schristos 
11924e98e3e1Schristos     case 0xE4:			/* UART B */
11934e98e3e1Schristos #ifdef FAST_UART
11944e98e3e1Schristos 	if (f2open) {
11954e98e3e1Schristos 	    if (wnumb < UARTBUF)
11964e98e3e1Schristos 		wbufb[wnumb++] = c;
11974e98e3e1Schristos 	    else {
11984e98e3e1Schristos 		while (wnumb)
11994e98e3e1Schristos 		    wnumb -= fwrite(wbufb, 1, wnumb, f2out);
12004e98e3e1Schristos 		wbufb[wnumb++] = c;
12014e98e3e1Schristos 	    }
12024e98e3e1Schristos 	}
12034e98e3e1Schristos 	mec_irq(5);
12044e98e3e1Schristos #else
12054e98e3e1Schristos 	if (uart_stat_reg & UARTB_SRE) {
12064e98e3e1Schristos 	    uartb_sreg = c;
12074e98e3e1Schristos 	    uart_stat_reg &= ~UARTB_SRE;
12084e98e3e1Schristos 	    event(uartb_tx, 0, UART_TX_TIME);
12094e98e3e1Schristos 	} else {
12104e98e3e1Schristos 	    uartb_hreg = c;
12114e98e3e1Schristos 	    uart_stat_reg &= ~UARTB_HRE;
12124e98e3e1Schristos 	}
12134e98e3e1Schristos #endif
12144e98e3e1Schristos 	break;
12154e98e3e1Schristos     case 0xE8:			/* UART status register */
12164e98e3e1Schristos #ifndef FAST_UART
12174e98e3e1Schristos 	if (data & UARTA_CLR) {
12184e98e3e1Schristos 	    uart_stat_reg &= 0xFFFF0000;
12194e98e3e1Schristos 	    uart_stat_reg |= UARTA_SRE | UARTA_HRE;
12204e98e3e1Schristos 	}
12214e98e3e1Schristos 	if (data & UARTB_CLR) {
12224e98e3e1Schristos 	    uart_stat_reg &= 0x0000FFFF;
12234e98e3e1Schristos 	    uart_stat_reg |= UARTB_SRE | UARTB_HRE;
12244e98e3e1Schristos 	}
12254e98e3e1Schristos #endif
12264e98e3e1Schristos 	break;
12274e98e3e1Schristos     default:
12284e98e3e1Schristos 	if (sis_verbose)
12294e98e3e1Schristos 	    printf("Write to unimplemented MEC register (%x)\n", addr);
12304e98e3e1Schristos 
12314e98e3e1Schristos     }
12324e98e3e1Schristos }
12334e98e3e1Schristos 
12344e98e3e1Schristos static void
12354b169a6bSchristos flush_uart(void)
12364e98e3e1Schristos {
12374e98e3e1Schristos     while (wnuma && f1open)
12384e98e3e1Schristos 	wnuma -= fwrite(wbufa, 1, wnuma, f1out);
12394e98e3e1Schristos     while (wnumb && f2open)
12404e98e3e1Schristos 	wnumb -= fwrite(wbufb, 1, wnumb, f2out);
12414e98e3e1Schristos }
12424e98e3e1Schristos 
12434b169a6bSchristos ATTRIBUTE_UNUSED
12444e98e3e1Schristos static void
12454b169a6bSchristos uarta_tx(int32_t arg ATTRIBUTE_UNUSED)
12464e98e3e1Schristos {
12474e98e3e1Schristos 
12484e98e3e1Schristos     while (f1open && fwrite(&uarta_sreg, 1, 1, f1out) != 1);
12494e98e3e1Schristos     if (uart_stat_reg & UARTA_HRE) {
12504e98e3e1Schristos 	uart_stat_reg |= UARTA_SRE;
12514e98e3e1Schristos     } else {
12524e98e3e1Schristos 	uarta_sreg = uarta_hreg;
12534e98e3e1Schristos 	uart_stat_reg |= UARTA_HRE;
12544e98e3e1Schristos 	event(uarta_tx, 0, UART_TX_TIME);
12554e98e3e1Schristos     }
12564e98e3e1Schristos     mec_irq(4);
12574e98e3e1Schristos }
12584e98e3e1Schristos 
12594b169a6bSchristos ATTRIBUTE_UNUSED
12604e98e3e1Schristos static void
12614b169a6bSchristos uartb_tx(int32_t arg ATTRIBUTE_UNUSED)
12624e98e3e1Schristos {
12634e98e3e1Schristos     while (f2open && fwrite(&uartb_sreg, 1, 1, f2out) != 1);
12644e98e3e1Schristos     if (uart_stat_reg & UARTB_HRE) {
12654e98e3e1Schristos 	uart_stat_reg |= UARTB_SRE;
12664e98e3e1Schristos     } else {
12674e98e3e1Schristos 	uartb_sreg = uartb_hreg;
12684e98e3e1Schristos 	uart_stat_reg |= UARTB_HRE;
12694e98e3e1Schristos 	event(uartb_tx, 0, UART_TX_TIME);
12704e98e3e1Schristos     }
12714e98e3e1Schristos     mec_irq(5);
12724e98e3e1Schristos }
12734e98e3e1Schristos 
12744b169a6bSchristos ATTRIBUTE_UNUSED
12754e98e3e1Schristos static void
12764b169a6bSchristos uart_rx(int32_t arg ATTRIBUTE_UNUSED)
12774e98e3e1Schristos {
12784b169a6bSchristos     int32_t           rsize;
12794e98e3e1Schristos     char            rxd;
12804e98e3e1Schristos 
12814e98e3e1Schristos 
12824e98e3e1Schristos     rsize = 0;
12834e98e3e1Schristos     if (f1open)
12844e98e3e1Schristos         rsize = DO_STDIO_READ(ifd1, &rxd, 1);
12854e98e3e1Schristos     if (rsize > 0) {
12864e98e3e1Schristos 	uarta_data = UART_DR | rxd;
12874e98e3e1Schristos 	if (uart_stat_reg & UARTA_HRE)
12884e98e3e1Schristos 	    uarta_data |= UART_THE;
12894e98e3e1Schristos 	if (uart_stat_reg & UARTA_SRE)
12904e98e3e1Schristos 	    uarta_data |= UART_TSE;
12914e98e3e1Schristos 	if (uart_stat_reg & UARTA_DR) {
12924e98e3e1Schristos 	    uart_stat_reg |= UARTA_OR;
12934e98e3e1Schristos 	    mec_irq(7);		/* UART error interrupt */
12944e98e3e1Schristos 	}
12954e98e3e1Schristos 	uart_stat_reg |= UARTA_DR;
12964e98e3e1Schristos 	mec_irq(4);
12974e98e3e1Schristos     }
12984e98e3e1Schristos     rsize = 0;
12994e98e3e1Schristos     if (f2open)
13004e98e3e1Schristos         rsize = DO_STDIO_READ(ifd2, &rxd, 1);
13014e98e3e1Schristos     if (rsize) {
13024e98e3e1Schristos 	uartb_data = UART_DR | rxd;
13034e98e3e1Schristos 	if (uart_stat_reg & UARTB_HRE)
13044e98e3e1Schristos 	    uartb_data |= UART_THE;
13054e98e3e1Schristos 	if (uart_stat_reg & UARTB_SRE)
13064e98e3e1Schristos 	    uartb_data |= UART_TSE;
13074e98e3e1Schristos 	if (uart_stat_reg & UARTB_DR) {
13084e98e3e1Schristos 	    uart_stat_reg |= UARTB_OR;
13094e98e3e1Schristos 	    mec_irq(7);		/* UART error interrupt */
13104e98e3e1Schristos 	}
13114e98e3e1Schristos 	uart_stat_reg |= UARTB_DR;
13124e98e3e1Schristos 	mec_irq(5);
13134e98e3e1Schristos     }
13144e98e3e1Schristos     event(uart_rx, 0, UART_RX_TIME);
13154e98e3e1Schristos }
13164e98e3e1Schristos 
13174e98e3e1Schristos static void
13184b169a6bSchristos uart_intr(int32_t arg ATTRIBUTE_UNUSED)
13194e98e3e1Schristos {
13204e98e3e1Schristos     read_uart(0xE8);		/* Check for UART interrupts every 1000 clk */
13214e98e3e1Schristos     flush_uart();		/* Flush UART ports      */
13224e98e3e1Schristos     event(uart_intr, 0, UART_FLUSH_TIME);
13234e98e3e1Schristos }
13244e98e3e1Schristos 
13254e98e3e1Schristos 
13264e98e3e1Schristos static void
13274b169a6bSchristos uart_irq_start(void)
13284e98e3e1Schristos {
13294e98e3e1Schristos #ifdef FAST_UART
13304e98e3e1Schristos     event(uart_intr, 0, UART_FLUSH_TIME);
13314e98e3e1Schristos #else
13324e98e3e1Schristos #ifndef _WIN32
13334e98e3e1Schristos     event(uart_rx, 0, UART_RX_TIME);
13344e98e3e1Schristos #endif
13354e98e3e1Schristos #endif
13364e98e3e1Schristos }
13374e98e3e1Schristos 
13384e98e3e1Schristos /* Watch-dog */
13394e98e3e1Schristos 
13404e98e3e1Schristos static void
13414b169a6bSchristos wdog_intr(int32_t arg ATTRIBUTE_UNUSED)
13424e98e3e1Schristos {
13434e98e3e1Schristos     if (wdog_status == disabled) {
13444e98e3e1Schristos 	wdog_status = stopped;
13454e98e3e1Schristos     } else {
13464e98e3e1Schristos 
13474e98e3e1Schristos 	if (wdog_counter) {
13484e98e3e1Schristos 	    wdog_counter--;
13494e98e3e1Schristos 	    event(wdog_intr, 0, wdog_scaler + 1);
13504e98e3e1Schristos 	} else {
13514e98e3e1Schristos 	    if (wdog_rston) {
13524e98e3e1Schristos 		printf("Watchdog reset!\n");
13534e98e3e1Schristos 		sys_reset();
13544e98e3e1Schristos 		mec_ersr = 0xC000;
13554e98e3e1Schristos 	    } else {
13564e98e3e1Schristos 		mec_irq(15);
13574e98e3e1Schristos 		wdog_rston = 1;
13584e98e3e1Schristos 		wdog_counter = wdog_rst_delay;
13594e98e3e1Schristos 		event(wdog_intr, 0, wdog_scaler + 1);
13604e98e3e1Schristos 	    }
13614e98e3e1Schristos 	}
13624e98e3e1Schristos     }
13634e98e3e1Schristos }
13644e98e3e1Schristos 
13654e98e3e1Schristos static void
13664b169a6bSchristos wdog_start(void)
13674e98e3e1Schristos {
13684e98e3e1Schristos     event(wdog_intr, 0, wdog_scaler + 1);
13694e98e3e1Schristos     if (sis_verbose)
13704e98e3e1Schristos 	printf("Watchdog started, scaler = %d, counter = %d\n",
13714e98e3e1Schristos 	       wdog_scaler, wdog_counter);
13724e98e3e1Schristos }
13734e98e3e1Schristos 
13744e98e3e1Schristos 
13754e98e3e1Schristos /* MEC timers */
13764e98e3e1Schristos 
13774e98e3e1Schristos 
13784e98e3e1Schristos static void
13794b169a6bSchristos rtc_intr(int32_t arg ATTRIBUTE_UNUSED)
13804e98e3e1Schristos {
13814e98e3e1Schristos     if (rtc_counter == 0) {
13824e98e3e1Schristos 
13834e98e3e1Schristos 	mec_irq(13);
13844e98e3e1Schristos 	if (rtc_cr)
13854e98e3e1Schristos 	    rtc_counter = rtc_reload;
13864e98e3e1Schristos 	else
13874e98e3e1Schristos 	    rtc_se = 0;
13884e98e3e1Schristos     } else
13894e98e3e1Schristos 	rtc_counter -= 1;
13904e98e3e1Schristos     if (rtc_se) {
13914e98e3e1Schristos 	event(rtc_intr, 0, rtc_scaler + 1);
13924e98e3e1Schristos 	rtc_scaler_start = now();
13934e98e3e1Schristos 	rtc_enabled = 1;
13944e98e3e1Schristos     } else {
13954e98e3e1Schristos 	if (sis_verbose)
13964e98e3e1Schristos 	    printf("RTC stopped\n\r");
13974e98e3e1Schristos 	rtc_enabled = 0;
13984e98e3e1Schristos     }
13994e98e3e1Schristos }
14004e98e3e1Schristos 
14014e98e3e1Schristos static void
14024b169a6bSchristos rtc_start(void)
14034e98e3e1Schristos {
14044e98e3e1Schristos     if (sis_verbose)
14054e98e3e1Schristos 	printf("RTC started (period %d)\n\r", rtc_scaler + 1);
14064e98e3e1Schristos     event(rtc_intr, 0, rtc_scaler + 1);
14074e98e3e1Schristos     rtc_scaler_start = now();
14084e98e3e1Schristos     rtc_enabled = 1;
14094e98e3e1Schristos }
14104e98e3e1Schristos 
14114b169a6bSchristos static uint32_t
14124b169a6bSchristos rtc_counter_read(void)
14134e98e3e1Schristos {
1414212397c6Schristos     return rtc_counter;
14154e98e3e1Schristos }
14164e98e3e1Schristos 
14174e98e3e1Schristos static void
14184b169a6bSchristos rtc_scaler_set(uint32_t val)
14194e98e3e1Schristos {
14204e98e3e1Schristos     rtc_scaler = val & 0x0ff;	/* eight-bit scaler only */
14214e98e3e1Schristos }
14224e98e3e1Schristos 
14234e98e3e1Schristos static void
14244b169a6bSchristos rtc_reload_set(uint32_t val)
14254e98e3e1Schristos {
14264e98e3e1Schristos     rtc_reload = val;
14274e98e3e1Schristos }
14284e98e3e1Schristos 
14294e98e3e1Schristos static void
14304b169a6bSchristos gpt_intr(int32_t arg ATTRIBUTE_UNUSED)
14314e98e3e1Schristos {
14324e98e3e1Schristos     if (gpt_counter == 0) {
14334e98e3e1Schristos 	mec_irq(12);
14344e98e3e1Schristos 	if (gpt_cr)
14354e98e3e1Schristos 	    gpt_counter = gpt_reload;
14364e98e3e1Schristos 	else
14374e98e3e1Schristos 	    gpt_se = 0;
14384e98e3e1Schristos     } else
14394e98e3e1Schristos 	gpt_counter -= 1;
14404e98e3e1Schristos     if (gpt_se) {
14414e98e3e1Schristos 	event(gpt_intr, 0, gpt_scaler + 1);
14424e98e3e1Schristos 	gpt_scaler_start = now();
14434e98e3e1Schristos 	gpt_enabled = 1;
14444e98e3e1Schristos     } else {
14454e98e3e1Schristos 	if (sis_verbose)
14464e98e3e1Schristos 	    printf("GPT stopped\n\r");
14474e98e3e1Schristos 	gpt_enabled = 0;
14484e98e3e1Schristos     }
14494e98e3e1Schristos }
14504e98e3e1Schristos 
14514e98e3e1Schristos static void
14524b169a6bSchristos gpt_start(void)
14534e98e3e1Schristos {
14544e98e3e1Schristos     if (sis_verbose)
14554e98e3e1Schristos 	printf("GPT started (period %d)\n\r", gpt_scaler + 1);
14564e98e3e1Schristos     event(gpt_intr, 0, gpt_scaler + 1);
14574e98e3e1Schristos     gpt_scaler_start = now();
14584e98e3e1Schristos     gpt_enabled = 1;
14594e98e3e1Schristos }
14604e98e3e1Schristos 
14614b169a6bSchristos static uint32_t
14624b169a6bSchristos gpt_counter_read(void)
14634e98e3e1Schristos {
1464212397c6Schristos     return gpt_counter;
14654e98e3e1Schristos }
14664e98e3e1Schristos 
14674e98e3e1Schristos static void
14684b169a6bSchristos gpt_scaler_set(uint32_t val)
14694e98e3e1Schristos {
14704e98e3e1Schristos     gpt_scaler = val & 0x0ffff;	/* 16-bit scaler */
14714e98e3e1Schristos }
14724e98e3e1Schristos 
14734e98e3e1Schristos static void
14744b169a6bSchristos gpt_reload_set(uint32_t val)
14754e98e3e1Schristos {
14764e98e3e1Schristos     gpt_reload = val;
14774e98e3e1Schristos }
14784e98e3e1Schristos 
14794e98e3e1Schristos static void
14804b169a6bSchristos timer_ctrl(uint32_t val)
14814e98e3e1Schristos {
14824e98e3e1Schristos 
14834e98e3e1Schristos     rtc_cr = ((val & TCR_TCRCR) != 0);
14844e98e3e1Schristos     if (val & TCR_TCRCL) {
14854e98e3e1Schristos 	rtc_counter = rtc_reload;
14864e98e3e1Schristos     }
14874e98e3e1Schristos     if (val & TCR_TCRSL) {
14884e98e3e1Schristos     }
14894e98e3e1Schristos     rtc_se = ((val & TCR_TCRSE) != 0);
14904e98e3e1Schristos     if (rtc_se && (rtc_enabled == 0))
14914e98e3e1Schristos 	rtc_start();
14924e98e3e1Schristos 
14934e98e3e1Schristos     gpt_cr = (val & TCR_GACR);
14944e98e3e1Schristos     if (val & TCR_GACL) {
14954e98e3e1Schristos 	gpt_counter = gpt_reload;
14964e98e3e1Schristos     }
14974e98e3e1Schristos     if (val & TCR_GACL) {
14984e98e3e1Schristos     }
14994e98e3e1Schristos     gpt_se = (val & TCR_GASE) >> 2;
15004e98e3e1Schristos     if (gpt_se && (gpt_enabled == 0))
15014e98e3e1Schristos 	gpt_start();
15024e98e3e1Schristos }
15034e98e3e1Schristos 
1504212397c6Schristos /* Store data in host byte order.  MEM points to the beginning of the
1505212397c6Schristos    emulated memory; WADDR contains the index the emulated memory,
15064e98e3e1Schristos    DATA points to words in host byte order to be stored.  SZ contains log(2)
15074e98e3e1Schristos    of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word),
1508212397c6Schristos    2 (one word), or 3 (two words); WS should return the number of
1509212397c6Schristos    wait-states.  */
15104e98e3e1Schristos 
15114e98e3e1Schristos static void
15124b169a6bSchristos store_bytes (unsigned char *mem, uint32_t waddr, uint32_t *data, int32_t sz,
15134b169a6bSchristos 	     int32_t *ws)
15144e98e3e1Schristos {
15154e98e3e1Schristos     switch (sz) {
15164e98e3e1Schristos 	case 0:
1517212397c6Schristos 	    waddr ^= EBT;
1518212397c6Schristos 	    mem[waddr] = *data & 0x0ff;
1519212397c6Schristos 	    *ws = mem_ramw_ws + 3;
15204e98e3e1Schristos 	    break;
15214e98e3e1Schristos 	case 1:
1522212397c6Schristos #ifdef HOST_LITTLE_ENDIAN
1523212397c6Schristos 	    waddr ^= 2;
1524212397c6Schristos #endif
1525212397c6Schristos 	    memcpy (&mem[waddr], data, 2);
1526212397c6Schristos 	    *ws = mem_ramw_ws + 3;
15274e98e3e1Schristos 	    break;
1528212397c6Schristos 	case 2:
1529212397c6Schristos 	    memcpy (&mem[waddr], data, 4);
1530212397c6Schristos 	    *ws = mem_ramw_ws;
15314e98e3e1Schristos 	    break;
1532212397c6Schristos 	case 3:
1533212397c6Schristos 	    memcpy (&mem[waddr], data, 8);
1534212397c6Schristos 	    *ws = 2 * mem_ramw_ws + STD_WS;
1535212397c6Schristos 	    break;
15364e98e3e1Schristos     }
15374e98e3e1Schristos }
15384e98e3e1Schristos 
15394e98e3e1Schristos 
15404e98e3e1Schristos /* Memory emulation */
15414e98e3e1Schristos 
15424e98e3e1Schristos int
15434b169a6bSchristos memory_iread (uint32_t addr, uint32_t *data, uint32_t *ws)
1544212397c6Schristos {
15454b169a6bSchristos     uint32_t          asi;
1546212397c6Schristos     if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
1547212397c6Schristos 	memcpy (data, &ramb[addr & mem_rammask & ~3], 4);
1548212397c6Schristos 	*ws = mem_ramr_ws;
1549212397c6Schristos 	return 0;
1550212397c6Schristos     } else if (addr < mem_romsz) {
1551212397c6Schristos 	memcpy (data, &romb[addr & ~3], 4);
1552212397c6Schristos 	*ws = mem_romr_ws;
1553212397c6Schristos 	return 0;
1554212397c6Schristos     }
1555212397c6Schristos 
1556212397c6Schristos     if (sis_verbose)
1557212397c6Schristos 	printf ("Memory exception at %x (illegal address)\n", addr);
1558212397c6Schristos     if (sregs.psr & 0x080)
1559212397c6Schristos         asi = 9;
1560212397c6Schristos     else
1561212397c6Schristos         asi = 8;
1562212397c6Schristos     set_sfsr (UIMP_ACC, addr, asi, 1);
1563212397c6Schristos     *ws = MEM_EX_WS;
1564212397c6Schristos     return 1;
1565212397c6Schristos }
1566212397c6Schristos 
1567212397c6Schristos int
15684b169a6bSchristos memory_read(int32_t asi, uint32_t addr, void *data, int32_t sz, int32_t *ws)
15694e98e3e1Schristos {
15704b169a6bSchristos     int32_t           mexc;
15714e98e3e1Schristos 
15724e98e3e1Schristos #ifdef ERRINJ
15734e98e3e1Schristos     if (errmec) {
15744e98e3e1Schristos 	if (sis_verbose)
15754e98e3e1Schristos 	    printf("Inserted MEC error %d\n",errmec);
15764e98e3e1Schristos 	set_sfsr(errmec, addr, asi, 1);
15774e98e3e1Schristos 	if (errmec == 5) mecparerror();
15784e98e3e1Schristos 	if (errmec == 6) iucomperr();
15794e98e3e1Schristos 	errmec = 0;
1580212397c6Schristos 	return 1;
15814e98e3e1Schristos     }
15824e98e3e1Schristos #endif
15834e98e3e1Schristos 
15844e98e3e1Schristos     if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
1585212397c6Schristos 	memcpy (data, &ramb[addr & mem_rammask & ~3], 4);
15864e98e3e1Schristos 	*ws = mem_ramr_ws;
1587212397c6Schristos 	return 0;
15884e98e3e1Schristos     } else if ((addr >= MEC_START) && (addr < MEC_END)) {
15894e98e3e1Schristos 	mexc = mec_read(addr, asi, data);
15904e98e3e1Schristos 	if (mexc) {
15914e98e3e1Schristos 	    set_sfsr(MEC_ACC, addr, asi, 1);
15924e98e3e1Schristos 	    *ws = MEM_EX_WS;
15934e98e3e1Schristos 	} else {
15944e98e3e1Schristos 	    *ws = 0;
15954e98e3e1Schristos 	}
1596212397c6Schristos 	return mexc;
15974e98e3e1Schristos 
15984e98e3e1Schristos #ifdef ERA
15994e98e3e1Schristos 
16004e98e3e1Schristos     } else if (era) {
16014e98e3e1Schristos     	if ((addr < 0x100000) ||
16024e98e3e1Schristos 	    ((addr>= 0x80000000) && (addr < 0x80100000))) {
1603212397c6Schristos 	    memcpy (data, &romb[addr & ROM_MASK & ~3], 4);
16044e98e3e1Schristos 	    *ws = 4;
1605212397c6Schristos 	    return 0;
16064e98e3e1Schristos 	} else if ((addr >= 0x10000000) &&
16074e98e3e1Schristos 		   (addr < (0x10000000 + (512 << (mec_iocr & 0x0f)))) &&
16084e98e3e1Schristos 		   (mec_iocr & 0x10))  {
16094b169a6bSchristos 	    memcpy (data, &erareg, 4);
1610212397c6Schristos 	    return 0;
16114e98e3e1Schristos 	}
16124e98e3e1Schristos 
16134e98e3e1Schristos     } else  if (addr < mem_romsz) {
1614212397c6Schristos 	memcpy (data, &romb[addr & ~3], 4);
16154e98e3e1Schristos 	*ws = mem_romr_ws;
1616212397c6Schristos 	return 0;
16174e98e3e1Schristos #else
16184e98e3e1Schristos     } else if (addr < mem_romsz) {
1619212397c6Schristos 	memcpy (data, &romb[addr & ~3], 4);
16204e98e3e1Schristos 	*ws = mem_romr_ws;
1621212397c6Schristos 	return 0;
16224e98e3e1Schristos #endif
16234e98e3e1Schristos 
16244e98e3e1Schristos     }
16254e98e3e1Schristos 
1626212397c6Schristos     if (sis_verbose)
16274e98e3e1Schristos 	printf ("Memory exception at %x (illegal address)\n", addr);
16284e98e3e1Schristos     set_sfsr(UIMP_ACC, addr, asi, 1);
16294e98e3e1Schristos     *ws = MEM_EX_WS;
1630212397c6Schristos     return 1;
16314e98e3e1Schristos }
16324e98e3e1Schristos 
16334e98e3e1Schristos int
16344b169a6bSchristos memory_write(int32_t asi, uint32_t addr, uint32_t *data, int32_t sz, int32_t *ws)
16354e98e3e1Schristos {
16364b169a6bSchristos     uint32_t          waddr;
16374b169a6bSchristos     int32_t           mexc;
16384e98e3e1Schristos     int             i;
16394e98e3e1Schristos     int             wphit[2];
16404e98e3e1Schristos 
16414e98e3e1Schristos #ifdef ERRINJ
16424e98e3e1Schristos     if (errmec) {
16434e98e3e1Schristos 	if (sis_verbose)
16444e98e3e1Schristos 	    printf("Inserted MEC error %d\n",errmec);
16454e98e3e1Schristos 	set_sfsr(errmec, addr, asi, 0);
16464e98e3e1Schristos 	if (errmec == 5) mecparerror();
16474e98e3e1Schristos 	if (errmec == 6) iucomperr();
16484e98e3e1Schristos 	errmec = 0;
1649212397c6Schristos 	return 1;
16504e98e3e1Schristos     }
16514e98e3e1Schristos #endif
16524e98e3e1Schristos 
16534e98e3e1Schristos     if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
16544e98e3e1Schristos 	if (mem_accprot) {
16554e98e3e1Schristos 
16564e98e3e1Schristos 	    waddr = (addr & 0x7fffff) >> 2;
16574e98e3e1Schristos 	    for (i = 0; i < 2; i++)
16584e98e3e1Schristos 		wphit[i] =
16594e98e3e1Schristos 		    (((asi == 0xa) && (mec_wpr[i] & 1)) ||
16604e98e3e1Schristos 		     ((asi == 0xb) && (mec_wpr[i] & 2))) &&
16614e98e3e1Schristos 		    ((waddr >= mec_ssa[i]) && ((waddr | (sz == 3)) < mec_sea[i]));
16624e98e3e1Schristos 
16634e98e3e1Schristos 	    if (((mem_blockprot) && (wphit[0] || wphit[1])) ||
16644e98e3e1Schristos 		((!mem_blockprot) &&
16654e98e3e1Schristos 		 !((mec_wpr[0] && wphit[0]) || (mec_wpr[1] && wphit[1]))
16664e98e3e1Schristos 		 )) {
16674e98e3e1Schristos 		if (sis_verbose)
16684e98e3e1Schristos 		    printf("Memory access protection error at 0x%08x\n", addr);
16694e98e3e1Schristos 		set_sfsr(PROT_EXC, addr, asi, 0);
16704e98e3e1Schristos 		*ws = MEM_EX_WS;
1671212397c6Schristos 		return 1;
16724e98e3e1Schristos 	    }
16734e98e3e1Schristos 	}
1674212397c6Schristos 	waddr = addr & mem_rammask;
1675212397c6Schristos 	store_bytes (ramb, waddr, data, sz, ws);
1676212397c6Schristos 	return 0;
16774e98e3e1Schristos     } else if ((addr >= MEC_START) && (addr < MEC_END)) {
16784e98e3e1Schristos 	if ((sz != 2) || (asi != 0xb)) {
16794e98e3e1Schristos 	    set_sfsr(MEC_ACC, addr, asi, 0);
16804e98e3e1Schristos 	    *ws = MEM_EX_WS;
1681212397c6Schristos 	    return 1;
16824e98e3e1Schristos 	}
16834e98e3e1Schristos 	mexc = mec_write(addr, *data);
16844e98e3e1Schristos 	if (mexc) {
16854e98e3e1Schristos 	    set_sfsr(MEC_ACC, addr, asi, 0);
16864e98e3e1Schristos 	    *ws = MEM_EX_WS;
16874e98e3e1Schristos 	} else {
16884e98e3e1Schristos 	    *ws = 0;
16894e98e3e1Schristos 	}
1690212397c6Schristos 	return mexc;
16914e98e3e1Schristos 
16924e98e3e1Schristos #ifdef ERA
16934e98e3e1Schristos 
16944e98e3e1Schristos     } else if (era) {
16954e98e3e1Schristos     	if ((erareg & 2) &&
16964e98e3e1Schristos 	((addr < 0x100000) || ((addr >= 0x80000000) && (addr < 0x80100000)))) {
16974e98e3e1Schristos 	    addr &= ROM_MASK;
16984e98e3e1Schristos 	    *ws = sz == 3 ? 8 : 4;
1699212397c6Schristos 	    store_bytes (romb, addr, data, sz, ws);
1700212397c6Schristos             return 0;
17014e98e3e1Schristos 	} else if ((addr >= 0x10000000) &&
17024e98e3e1Schristos 		   (addr < (0x10000000 + (512 << (mec_iocr & 0x0f)))) &&
17034e98e3e1Schristos 		   (mec_iocr & 0x10))  {
17044e98e3e1Schristos 	    erareg = *data & 0x0e;
1705212397c6Schristos 	    return 0;
17064e98e3e1Schristos 	}
17074e98e3e1Schristos 
17084e98e3e1Schristos     } else if ((addr < mem_romsz) && (mec_memcfg & 0x10000) && (wrp) &&
17094e98e3e1Schristos                (((mec_memcfg & 0x20000) && (sz > 1)) ||
17104e98e3e1Schristos 		(!(mec_memcfg & 0x20000) && (sz == 0)))) {
17114e98e3e1Schristos 
17124e98e3e1Schristos 	*ws = mem_romw_ws + 1;
17134e98e3e1Schristos 	if (sz == 3)
17144e98e3e1Schristos 	    *ws += mem_romw_ws + STD_WS;
1715212397c6Schristos 	store_bytes (romb, addr, data, sz, ws);
1716212397c6Schristos         return 0;
17174e98e3e1Schristos 
17184e98e3e1Schristos #else
17194e98e3e1Schristos     } else if ((addr < mem_romsz) && (mec_memcfg & 0x10000) && (wrp) &&
17204e98e3e1Schristos                (((mec_memcfg & 0x20000) && (sz > 1)) ||
17214e98e3e1Schristos 		(!(mec_memcfg & 0x20000) && (sz == 0)))) {
17224e98e3e1Schristos 
17234e98e3e1Schristos 	*ws = mem_romw_ws + 1;
17244e98e3e1Schristos 	if (sz == 3)
17254e98e3e1Schristos             *ws += mem_romw_ws + STD_WS;
1726212397c6Schristos 	store_bytes (romb, addr, data, sz, ws);
1727212397c6Schristos         return 0;
17284e98e3e1Schristos 
17294e98e3e1Schristos #endif
17304e98e3e1Schristos 
17314e98e3e1Schristos     }
17324e98e3e1Schristos 
17334e98e3e1Schristos     *ws = MEM_EX_WS;
17344e98e3e1Schristos     set_sfsr(UIMP_ACC, addr, asi, 0);
1735212397c6Schristos     return 1;
17364e98e3e1Schristos }
17374e98e3e1Schristos 
17384b169a6bSchristos static void  *
17394b169a6bSchristos get_mem_ptr(uint32_t addr, uint32_t size)
17404e98e3e1Schristos {
17414e98e3e1Schristos     if ((addr + size) < ROM_SZ) {
1742212397c6Schristos 	return &romb[addr];
17434e98e3e1Schristos     } else if ((addr >= mem_ramstart) && ((addr + size) < mem_ramend)) {
1744212397c6Schristos 	return &ramb[addr & mem_rammask];
17454e98e3e1Schristos     }
17464e98e3e1Schristos 
17474e98e3e1Schristos #ifdef ERA
17484e98e3e1Schristos       else if ((era) && ((addr <0x100000) ||
17494e98e3e1Schristos 	((addr >= (unsigned) 0x80000000) && ((addr + size) < (unsigned) 0x80100000)))) {
1750212397c6Schristos 	return &romb[addr & ROM_MASK];
17514e98e3e1Schristos     }
17524e98e3e1Schristos #endif
17534e98e3e1Schristos 
17544b169a6bSchristos     return (void *) -1;
17554e98e3e1Schristos }
17564e98e3e1Schristos 
17574e98e3e1Schristos int
17584b169a6bSchristos sis_memory_write(uint32_t addr, const void *data, uint32_t length)
17594e98e3e1Schristos {
17604b169a6bSchristos     void           *mem;
17614e98e3e1Schristos 
17624b169a6bSchristos     if ((mem = get_mem_ptr(addr, length)) == ((void *) -1))
1763212397c6Schristos 	return 0;
17644e98e3e1Schristos 
17654e98e3e1Schristos     memcpy(mem, data, length);
1766212397c6Schristos     return length;
17674e98e3e1Schristos }
17684e98e3e1Schristos 
17694e98e3e1Schristos int
17704b169a6bSchristos sis_memory_read(uint32_t addr, void *data, uint32_t length)
17714e98e3e1Schristos {
17724e98e3e1Schristos     char           *mem;
17734e98e3e1Schristos 
17744b169a6bSchristos     if ((mem = get_mem_ptr(addr, length)) == ((void *) -1))
1775212397c6Schristos 	return 0;
17764e98e3e1Schristos 
17774e98e3e1Schristos     memcpy(data, mem, length);
1778212397c6Schristos     return length;
1779212397c6Schristos }
1780212397c6Schristos 
1781212397c6Schristos extern struct pstate sregs;
1782212397c6Schristos 
1783212397c6Schristos void
1784212397c6Schristos boot_init (void)
1785212397c6Schristos {
1786212397c6Schristos     mec_write(MEC_WCR, 0);	/* zero waitstates */
1787212397c6Schristos     mec_write(MEC_TRAPD, 0);	/* turn off watch-dog */
1788212397c6Schristos     mec_write(MEC_RTC_SCALER, sregs.freq - 1); /* generate 1 MHz RTC tick */
1789212397c6Schristos     mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
1790212397c6Schristos     sregs.wim = 2;
1791212397c6Schristos     sregs.psr = 0x110010e0;
1792212397c6Schristos     sregs.r[30] = RAM_END;
1793212397c6Schristos     sregs.r[14] = sregs.r[30] - 96 * 4;
1794212397c6Schristos     mec_mcr |= 1;		/* power-down enabled */
17954e98e3e1Schristos }
1796