From 6cd89205a3fc0d782b9d0afef0587945f6ba3d2b Mon Sep 17 00:00:00 2001 From: "Howard M. Harte" Date: Wed, 23 Nov 2022 20:31:15 -0800 Subject: [PATCH] AltairZ80: M68K: Add support for memory-mapped I/O. Allows the M68K CPU to take advantage of additional AltairZ80 peripherals. --- AltairZ80/altairz80_cpu.c | 31 ++++++++++++++++++++++++------- AltairZ80/m68ksim.c | 14 ++++++++++++++ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/AltairZ80/altairz80_cpu.c b/AltairZ80/altairz80_cpu.c index abbe2819..dc168f5c 100644 --- a/AltairZ80/altairz80_cpu.c +++ b/AltairZ80/altairz80_cpu.c @@ -145,6 +145,9 @@ extern uint8 MOPT[MAXBANKSIZE]; extern t_stat sim_instr_8086(void); extern void cpu8086reset(void); +extern unsigned int m68k_cpu_read_byte_raw(unsigned int address); +void m68k_cpu_write_byte_raw(unsigned int address, unsigned int value); + /* function prototypes */ static t_stat cpu_set_switcher (UNIT *uptr, int32 value, CONST char *cptr, void *desc); static t_stat cpu_reset_switcher(UNIT *uptr, int32 value, CONST char *cptr, void *desc); @@ -278,11 +281,13 @@ typedef struct { t_value op[INST_MAX_BYTES]; } insthist_t; -static uint32 hst_p = 0; /* history pointer */ -static uint32 hst_lnt = 0; /* history length */ -static insthist_t *hst = NULL; /* instruction history */ +static uint32 hst_p = 0; /* history pointer */ +static uint32 hst_lnt = 0; /* history length */ +static insthist_t *hst = NULL; /* instruction history */ -uint32 m68k_registers[M68K_REG_CPU_TYPE + 1]; /* M68K CPU registers */ +uint32 m68k_registers[M68K_REG_CPU_TYPE + 1]; /* M68K CPU registers */ +uint32 mmiobase = 0xff0000; /* M68K MMIO base address */ +uint32 mmiosize = 0x10000; /* M68K MMIO window size */ /* data structure for IN/OUT instructions */ @@ -477,10 +482,14 @@ REG cpu_reg[] = { }, /* 82 */ { HRDATAD(COMMONLOW,common_low, 1, "If set, use low memory for common area"), }, /* 83 */ - { HRDATAD(VECINT,vectorInterrupt, 2, "Vector Interrupt psuedo register"), + { HRDATAD(VECINT,vectorInterrupt, 2, "Vector Interrupt pseudo register"), }, /* 84 */ { BRDATAD (DATABUS, dataBus, 16, 8, MAX_INT_VECTORS, "Data bus pseudo register"), REG_RO + REG_CIRC }, /* 85 */ + { HRDATAD(MMIOBASE, mmiobase, 24, "Base address for 68K Memory-mapped I/O"), + }, /* 86 */ + { HRDATAD(MMIOSIZE, mmiosize, 17, "Size of 68K Memory-mapped I/O window"), + }, /* 87 */ { NULL } }; @@ -1962,6 +1971,8 @@ uint32 getCommon(void) { uint8 GetBYTEWrapper(const uint32 Addr) { if (chiptype == CHIP_TYPE_8086) return GetBYTEExtended(Addr); + else if (chiptype == CHIP_TYPE_M68K) + return m68k_cpu_read_byte_raw(Addr); else if (cpu_unit.flags & UNIT_CPU_MMU) return GetBYTE(Addr); else @@ -1972,6 +1983,8 @@ uint8 GetBYTEWrapper(const uint32 Addr) { void PutBYTEWrapper(const uint32 Addr, const uint32 Value) { if (chiptype == CHIP_TYPE_8086) PutBYTEExtended(Addr, Value); + else if (chiptype == CHIP_TYPE_M68K) + m68k_cpu_write_byte_raw(Addr, Value); else if (cpu_unit.flags & UNIT_CPU_MMU) PutBYTE(Addr, Value); else @@ -1980,14 +1993,18 @@ void PutBYTEWrapper(const uint32 Addr, const uint32 Value) { /* DMA memory access during a simulation, suggested by Tony Nicholson */ uint8 GetByteDMA(const uint32 Addr) { - if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) + if (chiptype == CHIP_TYPE_M68K) + return m68k_cpu_read_byte_raw(Addr); + else if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) return GetBYTEExtended(Addr); else return MOPT[Addr & ADDRMASK]; } void PutByteDMA(const uint32 Addr, const uint32 Value) { - if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) + if (chiptype == CHIP_TYPE_M68K) + m68k_cpu_write_byte_raw(Addr, Value); + else if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) PutBYTEExtended(Addr, Value); else MOPT[Addr & ADDRMASK] = Value & 0xff; diff --git a/AltairZ80/m68ksim.c b/AltairZ80/m68ksim.c index 24a57013..b014e251 100644 --- a/AltairZ80/m68ksim.c +++ b/AltairZ80/m68ksim.c @@ -154,10 +154,16 @@ extern int32 hdsk_read(void); extern int32 hdsk_write(void); extern int32 hdsk_flush(void); +/* Interface to SIMH I/O devices */ +extern void out(const uint32 Port, const uint32 Value); +extern uint32 in(const uint32 Port); + static uint32 m68k_fc; /* Current function code from CPU */ extern uint32 m68k_registers[M68K_REG_CPU_TYPE + 1]; extern UNIT cpu_unit; +extern uint32 mmiobase; /* M68K MMIO base address */ +extern uint32 mmiosize; /* M68K MMIO window size */ #define M68K_BOOT_LENGTH (32 * 1024) /* size of bootstrap */ #define M68K_BOOT_PC 0x000400 /* initial PC for boot */ @@ -350,6 +356,10 @@ unsigned int m68k_cpu_read_byte(unsigned int address) { case MC6850_STAT: return MC6850_status_read(); default: + if ((address >= mmiobase) && (address < mmiobase + mmiosize)) { + /* Memory-mapped I/O */ + return (in(address & 0xff) & 0xff); + } break; } if (address > M68K_MAX_RAM) { @@ -416,6 +426,10 @@ void m68k_cpu_write_byte(unsigned int address, unsigned int value) { MC6850_control_write(value & 0xff); return; default: + if ((address >= mmiobase) && (address < mmiobase + mmiosize)) { + /* Memory-mapped I/O */ + out(address & 0xff, value & 0xff); + } break; } if (address > M68K_MAX_RAM) {