| /* 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 |