251 lines
11 KiB
C
251 lines
11 KiB
C
/* 68k_cpu.c: 68k-CPU simulator for sage-II system
|
|
|
|
Copyright (c) 2009, Holger Veit
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
Holger Veit BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of Holger Veit et al shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from Holger Veit et al.
|
|
|
|
04-Oct-09 HV Initial version
|
|
*/
|
|
|
|
#ifndef M68K_CPU_H_
|
|
#define M68K_CPU_H_ 0
|
|
|
|
#include "sim_defs.h"
|
|
|
|
/* define this o 1 for adding debugging code */
|
|
#define DBG_MSG 1
|
|
|
|
#if !defined(HAVE_INT64)
|
|
#error Fix me, I need 64 bit data types!
|
|
#endif
|
|
|
|
/* these must be set in the system-specific CPU reset */
|
|
extern UNIT* m68kcpu_unit;
|
|
extern DEVICE* m68kcpu_dev;
|
|
|
|
/* implemented in m68k_cpu.c */
|
|
extern REG m68kcpu_reg[];
|
|
|
|
/* debug flags */
|
|
#define DBG_CPU_EXC (1 << 0)
|
|
#define DBG_CPU_PC (1 << 1)
|
|
#define DBG_CPU_INT (1 << 2)
|
|
#define DBG_CPU_CTRACE (1 << 3)
|
|
#define DBG_CPU_BTRACE (1 << 4)
|
|
#define DBG_CPU_CUSTOM1 (1 << 5) /* reserved for custom debugging */
|
|
#define DBG_CPU_CUSTOM2 (1 << 6) /* reserved for custom debugging */
|
|
extern DEBTAB m68kcpu_dt[];
|
|
#if DBG_MSG==1
|
|
#define IFDEBUG(flag,func) if ((m68kcpu_dev->dctrl & flag) && sim_deb) { (void)(func); fflush(sim_deb); }
|
|
#else
|
|
#define IFDEBUG(flag,func)
|
|
#endif
|
|
|
|
#define SIM_EMAX 16 /* ? */
|
|
#define MAXMEMORY (256*256*256) /* 2^24 bytes */
|
|
#define MINMEMORY (256*256) /* reserve 64k by default */
|
|
#define MEMORYSIZE (m68kcpu_unit->capac) /* actual memory size */
|
|
#define KB 1024 /* kilobyte */
|
|
|
|
/* simulator stop codes */
|
|
#define STOP_IBKPT 1 /* pc breakpoint */
|
|
#define STOP_MEM 2 /* memory breakpoint */
|
|
#define STOP_ERROP 3 /* invalid opcode, normally exception 4 */
|
|
#define STOP_ERRIO 4 /* invalid I/O address, normally exception 2 */
|
|
#define STOP_ERRADR 5 /* invalid memory address, normally exception 3 */
|
|
#define STOP_IMPL 6 /* not yet implemented (should disappear) */
|
|
#define SIM_ISIO 7 /* internal indicator that I/O dispatch is required */
|
|
#define SIM_NOMEM 8 /* allows to signal that there is no memory at that location */
|
|
#define STOP_PCIO 9 /* code error, PC steps on I/O address */
|
|
#define STOP_PRVIO 10 /* internal indicator: privileged instruction */
|
|
#define STOP_TRACE 11 /* halt on trace */
|
|
#define STOP_HALT 12 /* STOP instruction */
|
|
#define STOP_DBF 13 /* double bus fault */
|
|
#define STOP_OFFLINE 14 /* printer offline */
|
|
|
|
#define UNIT_CPU_M_TYPE 017
|
|
#define UNIT_CPU_V_TYPE (UNIT_V_UF+0) /* CPUTYPE */
|
|
#define UNIT_CPU_TYPE (1 << UNIT_CPU_V_CPU)
|
|
#define UNIT_CPU_V_EXC (UNIT_V_UF+4) /* halt on exception 2..4 */
|
|
#define UNIT_CPU_EXC (1 << UNIT_CPU_V_EXC)
|
|
#define UNIT_CPU_V_STOP (UNIT_V_UF+5) /* halt on STOP instruction */
|
|
#define UNIT_CPU_STOP (1 << UNIT_CPU_V_STOP)
|
|
#define UNIT_CPU_V_PRVIO (UNIT_V_UF+6) /* halt on privilege violation */
|
|
#define UNIT_CPU_PRVIO (1 << UNIT_CPU_V_PRVIO)
|
|
#define UNIT_CPU_V_TRACE (UNIT_V_UF+7) /* halt on TRACE exception */
|
|
#define UNIT_CPU_TRACE (1 << UNIT_CPU_V_TRACE)
|
|
#define UNIT_CPU_V_FPU (UNIT_V_UF+8) /* has FPU */
|
|
#define UNIT_CPU_FPU (1 << UNIT_CPU_V_FPU)
|
|
#define UNIT_CPU_V_MMU (UNIT_V_UF+9) /* has MMU */
|
|
#define UNIT_CPU_MMU (1 << UNIT_CPU_V_MMU)
|
|
#define UNIT_CPU_V_MSIZE (UNIT_V_UF+10) /* set memsize */
|
|
#define UNIT_CPU_MSIZE (1 << UNIT_CPU_V_MSIZE)
|
|
|
|
#define UNIT_CPU_V_FREE (UNIT_V_UF+11) /* next free bit */
|
|
|
|
/* the various CPUs */
|
|
#define UNIT_CPUTYPE_MASK (UNIT_CPU_M_TYPE << UNIT_CPU_V_TYPE)
|
|
#define CPU_TYPE_68000 (0 << UNIT_CPU_V_TYPE)
|
|
#define CPU_TYPE_68008 (1 << UNIT_CPU_V_TYPE)
|
|
#define CPU_TYPE_68010 (2 << UNIT_CPU_V_TYPE) /* not yet! */
|
|
#define CPU_TYPE_68020 (3 << UNIT_CPU_V_TYPE) /* not yet! */
|
|
#define CPU_TYPE_68030 (4 << UNIT_CPU_V_TYPE) /* not yet! */
|
|
|
|
extern uint8 *M;
|
|
extern int16 cputype;
|
|
extern t_addr saved_PC;
|
|
#define PCX saved_PC
|
|
|
|
/* breakpoint space for data accesses (R=read, W=write) */
|
|
#define E_BKPT_SPC (0)
|
|
#define R_BKPT_SPC (1<<SIM_BKPT_V_SPC)
|
|
#define W_BKPT_SPC (2<<SIM_BKPT_V_SPC)
|
|
|
|
/* IR 7-6 bits */
|
|
#define SZ_BYTE 0
|
|
#define SZ_WORD 1
|
|
#define SZ_LONG 2
|
|
#define SZ_SPEC 3
|
|
|
|
/* functions to access memory
|
|
* xxxxPx access physical memory
|
|
* xxxxVx access virtual memory using MMU; if no MMU xxxxVX == xxxxPX
|
|
* xxxxxB = byte, xxxxxW = 16 bit word, xxxxxL = 32 bit word
|
|
*/
|
|
#define BMASK 0x000000ff
|
|
#define BLMASK BMASK
|
|
#define BHMASK 0x0000ff00
|
|
|
|
#define WMASK 0x0000ffff
|
|
#define WLMASK WMASK
|
|
#define WHMASK 0xffff0000
|
|
|
|
#define LMASK 0xffffffff
|
|
extern t_addr addrmask;
|
|
|
|
#define MEM_READ 0
|
|
#define MEM_WRITE 1
|
|
|
|
/* I/O handler block */
|
|
#define IO_READ 0
|
|
#define IO_WRITE 1
|
|
struct _iohandler {
|
|
void* ctxt;
|
|
t_addr port;
|
|
t_addr offset;
|
|
UNIT* u;
|
|
t_stat (*io)(struct _iohandler* ioh,uint32* value,uint32 rw,uint32 mask);
|
|
struct _iohandler* next;
|
|
};
|
|
typedef struct _iohandler IOHANDLER;
|
|
|
|
typedef struct {
|
|
uint32 mem_base; /* Memory Base Address */
|
|
uint32 mem_size; /* Memory Address space requirement */
|
|
uint32 io_base; /* I/O Base Address */
|
|
uint32 io_size; /* I/O Address Space requirement */
|
|
uint32 io_incr; /* I/O Address increment */
|
|
} PNP_INFO;
|
|
|
|
extern t_stat add_iohandler(UNIT* u,void* ctxt,
|
|
t_stat (*io)(IOHANDLER* ioh,uint32* value,uint32 rw,uint32 mask));
|
|
extern t_stat del_iohandler(void* ctxt);
|
|
extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc);
|
|
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
|
|
|
|
/* public memory access routines */
|
|
extern t_stat ReadPB(t_addr a, uint32* val);
|
|
extern t_stat ReadPW(t_addr a, uint32* val);
|
|
extern t_stat ReadPL(t_addr a, uint32* val);
|
|
extern t_stat WritePB(t_addr a, uint32 val);
|
|
extern t_stat WritePW(t_addr a, uint32 val);
|
|
extern t_stat WritePL(t_addr a, uint32 val);
|
|
|
|
extern t_stat ReadVB(t_addr a, uint32* val);
|
|
extern t_stat ReadVW(t_addr a, uint32* val);
|
|
extern t_stat ReadVL(t_addr a, uint32* val);
|
|
extern t_stat WriteVB(t_addr a, uint32 val);
|
|
extern t_stat WriteVW(t_addr a, uint32 val);
|
|
extern t_stat WriteVL(t_addr a, uint32 val);
|
|
extern t_stat (*TranslateAddr)(t_addr in,t_addr* out,IOHANDLER** ioh,int rw,int fc,int dma);
|
|
extern t_stat m68k_translateaddr(t_addr in,t_addr* out,IOHANDLER** ioh,int rw,int fc,int dma);
|
|
extern t_stat (*Mem)(t_addr a,uint8** mem);
|
|
extern t_stat m68k_mem(t_addr a,uint8** mem);
|
|
|
|
/* cpu_mod for alternative implementations */
|
|
extern t_stat m68k_set_cpu(UNIT *uptr, int32 value, char *cptr, void *desc);
|
|
extern t_stat m68k_show_cpu(FILE* st,UNIT *uptr, int32 value, void *desc);
|
|
extern t_stat m68k_set_size(UNIT *uptr, int32 value, char *cptr, void *desc);
|
|
extern t_stat m68k_set_fpu(UNIT *uptr, int32 value, char *cptr, void *desc);
|
|
extern t_stat m68k_set_nofpu(UNIT *uptr, int32 value, char *cptr, void *desc);
|
|
extern t_stat m68kcpu_set_flag(UNIT *uptr, int32 value, char *cptr, void *desc);
|
|
extern t_stat m68kcpu_set_noflag(UNIT *uptr, int32 value, char *cptr, void *desc);
|
|
extern t_stat m68kcpu_reset(DEVICE* dptr);
|
|
extern t_stat m68kcpu_ex(t_value* eval_array, t_addr addr, UNIT *uptr, int32 switches);
|
|
extern t_stat m68kcpu_dep(t_value value, t_addr addr, UNIT* uptr, int32 switches);
|
|
extern t_stat m68kcpu_boot(int32 unitno,DEVICE* dptr);
|
|
extern t_stat m68k_ioinit();
|
|
extern t_stat m68kcpu_peripheral_reset();
|
|
extern t_stat m68k_alloc_mem();
|
|
extern t_stat m68k_raise_vectorint(int level,int vector);
|
|
extern t_stat m68k_raise_autoint(int level);
|
|
|
|
#define XFMT "0x%08x"
|
|
#define SFMT "$%x"
|
|
extern char* m68k_getsym(t_addr val,const char* fmt, char* outbuf);
|
|
|
|
/* overloadable callbacks */
|
|
extern void (*m68kcpu_trapcallback)(DEVICE* cpudev,int trapnum);
|
|
|
|
/* standard MTAB declarations for most 68K CPUs */
|
|
#define M68KCPU_STDMOD \
|
|
{ UNIT_CPUTYPE_MASK, CPU_TYPE_68000, "", "68000", &m68k_set_cpu, &m68k_show_cpu, "68000" },\
|
|
{ UNIT_CPUTYPE_MASK, CPU_TYPE_68008, "", "68008", &m68k_set_cpu, &m68k_show_cpu, "68008" },\
|
|
{ UNIT_CPUTYPE_MASK, CPU_TYPE_68010, "", "68010", &m68k_set_cpu, &m68k_show_cpu, "68010" },\
|
|
{ UNIT_CPU_MSIZE, (1u << 16), NULL, "64K", &m68k_set_size },\
|
|
{ UNIT_CPU_MSIZE, (1u << 17), NULL, "128K", &m68k_set_size },\
|
|
{ UNIT_CPU_MSIZE, (1u << 18), NULL, "256K", &m68k_set_size },\
|
|
{ UNIT_CPU_MSIZE, (1u << 19), NULL, "512K", &m68k_set_size },\
|
|
{ UNIT_CPU_MSIZE, (1u << 20), NULL, "1M", &m68k_set_size },\
|
|
{ UNIT_CPU_MSIZE, (1u << 21), NULL, "2M", &m68k_set_size },\
|
|
{ UNIT_CPU_MSIZE, (1u << 22), NULL, "4M", &m68k_set_size },\
|
|
{ UNIT_CPU_MSIZE, (1u << 23), NULL, "8M", &m68k_set_size },\
|
|
{ UNIT_CPU_EXC, UNIT_CPU_EXC, "halt on EXC", "EXC", &m68kcpu_set_flag },\
|
|
{ UNIT_CPU_EXC, 0, "no EXC", NULL, NULL },\
|
|
{ MTAB_XTD|MTAB_VDV, UNIT_CPU_EXC, NULL, "NOEXC", &m68kcpu_set_noflag },\
|
|
{ UNIT_CPU_STOP, UNIT_CPU_STOP, "halt on STOP", "STOP", &m68kcpu_set_flag },\
|
|
{ UNIT_CPU_STOP, 0, "no STOP", NULL, NULL },\
|
|
{ MTAB_XTD|MTAB_VDV, UNIT_CPU_STOP, NULL, "NOSTOP", &m68kcpu_set_noflag },\
|
|
{ UNIT_CPU_PRVIO, UNIT_CPU_PRVIO, "halt on PRVIO", "PRVIO", &m68kcpu_set_flag },\
|
|
{ UNIT_CPU_PRVIO, 0, "no PRVIO", NULL, NULL },\
|
|
{ MTAB_XTD|MTAB_VDV, UNIT_CPU_PRVIO, NULL, "NOPRVIO", &m68kcpu_set_noflag },\
|
|
{ UNIT_CPU_TRACE, UNIT_CPU_TRACE, "halt on TRACE", "TRACE", &m68kcpu_set_flag },\
|
|
{ UNIT_CPU_TRACE, 0, "no TRACE", NULL, NULL },\
|
|
{ MTAB_XTD|MTAB_VDV, UNIT_CPU_TRACE, NULL, "NOTRACE", &m68kcpu_set_noflag }
|
|
|
|
#if 0
|
|
,{ UNIT_CPU_FPU, UNIT_CPU_FPU, "FPU", "FPU", &m68k_set_fpu },
|
|
{ UNIT_CPU_FPU, 0, "no FPU", NULL, NULL },
|
|
{ MTAB_XTD|MTAB_VDV, UNIT_CPU_FPU, NULL, "NOFPU", &m68k_set_nofpu },
|
|
#endif
|
|
|
|
#endif
|