From 27ee4f39156863330dd2c369b47699ad774306aa Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Sat, 22 Sep 2018 19:40:43 +0200 Subject: -sun4: Added a sun4c MMU device. Currently wraps the functionality of S4-buffer, S4-cache, and S4-MMU, will eventually be split. [Ryan Holtz] -sun4: Significant optimization, from 150% -> 330% unthrottled on an i7-5930K. [Ryan Holtz] --- scripts/src/cpu.lua | 1 + scripts/src/machine.lua | 12 + scripts/target/mame/arcade.lua | 1 + scripts/target/mame/mess.lua | 1 + src/devices/bus/nubus/quadralink.cpp | 32 +- src/devices/bus/sbus/bwtwo.cpp | 40 +- src/devices/bus/sbus/bwtwo.h | 7 +- src/devices/cpu/sparc/mb86901.cpp | 448 +++++++++++----------- src/devices/cpu/sparc/sparc.h | 50 ++- src/devices/cpu/sparc/sparc_intf.h | 30 ++ src/devices/cpu/sparc/sparcdefs.h | 2 +- src/devices/machine/ncr5390.cpp | 67 ++++ src/devices/machine/ncr5390.h | 9 + src/devices/machine/sun4c_mmu.cpp | 497 ++++++++++++++++++++++++ src/devices/machine/sun4c_mmu.h | 149 ++++++++ src/devices/machine/z80scc.cpp | 8 +- src/devices/machine/z80scc.h | 18 +- src/mame/drivers/apple2gs.cpp | 16 +- src/mame/drivers/sun4.cpp | 712 ++++++++--------------------------- src/mame/machine/iteagle_fpga.cpp | 18 +- 20 files changed, 1243 insertions(+), 875 deletions(-) create mode 100644 src/devices/cpu/sparc/sparc_intf.h create mode 100644 src/devices/machine/sun4c_mmu.cpp create mode 100644 src/devices/machine/sun4c_mmu.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 6a8519a644b..846e1bad71c 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -2713,6 +2713,7 @@ if (CPUS["MB86901"]~=null) then MAME_DIR .. "src/devices/cpu/sparc/mb86901.cpp", MAME_DIR .. "src/devices/cpu/sparc/sparcv8ops.ipp", MAME_DIR .. "src/devices/cpu/sparc/sparcdefs.h", + MAME_DIR .. "src/devices/cpu/sparc/sparc_intf.h", MAME_DIR .. "src/devices/cpu/sparc/sparc.h", } end diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index cd141b26cb3..b161f1ddbcf 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -3747,3 +3747,15 @@ if (MACHINES["IOPTIMER"]~=null) then MAME_DIR .. "src/devices/machine/ioptimer.h", } end + +--------------------------------------------------- +-- +--@src/devices/machine/sun4c_mmu.h,MACHINES["SUN4C_MMU"] = true +--------------------------------------------------- + +if (MACHINES["SUN4C_MMU"]~=null) then + files { + MAME_DIR .. "src/devices/machine/sun4c_mmu.cpp", + MAME_DIR .. "src/devices/machine/sun4c_mmu.h", + } +end diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index f27b41c32a2..705c4c92aa9 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -574,6 +574,7 @@ MACHINES["SMC91C9X"] = true MACHINES["SEGA_SCU"] = true MACHINES["SMPC"] = true MACHINES["STVCD"] = true +--MACHINES["SUN4C_MMU"] = true MACHINES["TC0091LVC"] = true MACHINES["TE7750"] = true MACHINES["TICKET"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 29e19eee5ea..95e8e3fabfc 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -576,6 +576,7 @@ MACHINES["SMIOC"] = true MACHINES["SEGA_SCU"] = true MACHINES["SMPC"] = true MACHINES["STVCD"] = true +MACHINES["SUN4C_MMU"] = true MACHINES["TC0091LVC"] = true --MACHINES["TE7750"] = true MACHINES["TIMEKPR"] = true diff --git a/src/devices/bus/nubus/quadralink.cpp b/src/devices/bus/nubus/quadralink.cpp index f38a0f3b57b..a2d138874e6 100644 --- a/src/devices/bus/nubus/quadralink.cpp +++ b/src/devices/bus/nubus/quadralink.cpp @@ -126,35 +126,35 @@ WRITE32_MEMBER( nubus_quadralink_device::dev_w ) switch (offset) { case 0x0000: // SCC 2 A control - m_scc2->ca_w(space, 0, data & 0xff); + m_scc2->ca_w(0, data & 0xff); break; case 0x0002: // SCC 2 A data - m_scc2->da_w(space, 0, data & 0xff); + m_scc2->da_w(0, data & 0xff); break; case 0x0004: // SCC 2 B control - m_scc2->cb_w(space, 0, data & 0xff); + m_scc2->cb_w(0, data & 0xff); break; case 0x0006: // SCC 2 B data - m_scc2->db_w(space, 0, data & 0xff); + m_scc2->db_w(0, data & 0xff); break; case 0x10000: // SCC 1 A control - m_scc1->ca_w(space, 0, data & 0xff); + m_scc1->ca_w(0, data & 0xff); break; case 0x10002: // SCC 1 A data - m_scc1->da_w(space, 0, data & 0xff); + m_scc1->da_w(0, data & 0xff); break; case 0x10004: // SCC 1 B control - m_scc1->cb_w(space, 0, data & 0xff); + m_scc1->cb_w(0, data & 0xff); break; case 0x10006: // SCC 1 B data - m_scc1->db_w(space, 0, data & 0xff); + m_scc1->db_w(0, data & 0xff); break; } } @@ -165,28 +165,28 @@ READ32_MEMBER( nubus_quadralink_device::dev_r ) switch (offset) { case 0x0000: - return m_scc2->ca_r(space, 0); + return m_scc2->ca_r(0); case 0x0002: - return m_scc2->da_r(space, 0); + return m_scc2->da_r(0); case 0x0004: - return m_scc2->cb_r(space, 0); + return m_scc2->cb_r(0); case 0x0006: - return m_scc2->db_r(space, 0); + return m_scc2->db_r(0); case 0x10000: - return m_scc1->ca_r(space, 0); + return m_scc1->ca_r(0); case 0x10002: - return m_scc1->da_r(space, 0); + return m_scc1->da_r(0); case 0x10004: - return m_scc1->cb_r(space, 0); + return m_scc1->cb_r(0); case 0x10006: - return m_scc1->db_r(space, 0); + return m_scc1->db_r(0); } return 0xffffffff; } diff --git a/src/devices/bus/sbus/bwtwo.cpp b/src/devices/bus/sbus/bwtwo.cpp index ab9fd194a88..553e040ec1a 100644 --- a/src/devices/bus/sbus/bwtwo.cpp +++ b/src/devices/bus/sbus/bwtwo.cpp @@ -54,7 +54,15 @@ sbus_bwtwo_device::sbus_bwtwo_device(const machine_config &mconfig, const char * void sbus_bwtwo_device::device_start() { - m_vram = std::make_unique(0x100000/4); + m_vram = std::make_unique(0x100000); + + for (int i = 0; i < 0x100; i++) + { + for (int bit = 7; bit >= 0; bit--) + { + m_mono_lut[i][7 - bit] = BIT(i, bit) ? 0 : ~0; + } + } } void sbus_bwtwo_device::install_device() @@ -64,25 +72,15 @@ void sbus_bwtwo_device::install_device() uint32_t sbus_bwtwo_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - static const uint32_t palette[2] = { 0xffffff, 0 }; - uint8_t *vram = (uint8_t *)&m_vram[0]; - for (int y = 0; y < 900; y++) { uint32_t *scanline = &bitmap.pix32(y); - uint8_t *line = vram + y * (1152/8); + uint8_t *line = &m_vram[y * 1152/8]; for (int x = 0; x < 1152/8; x++) { - const uint8_t pixels = line[BYTE4_XOR_BE(x)]; - - *scanline++ = palette[BIT(pixels, 7)]; - *scanline++ = palette[BIT(pixels, 6)]; - *scanline++ = palette[BIT(pixels, 5)]; - *scanline++ = palette[BIT(pixels, 4)]; - *scanline++ = palette[BIT(pixels, 3)]; - *scanline++ = palette[BIT(pixels, 2)]; - *scanline++ = palette[BIT(pixels, 1)]; - *scanline++ = palette[BIT(pixels, 0)]; + memcpy(scanline, m_mono_lut[*line], sizeof(uint32_t) * 8); + line++; + scanline += 8; } } @@ -100,17 +98,17 @@ WRITE8_MEMBER(sbus_bwtwo_device::regs_w) logerror("%s: regs_w (unimplemented): %08x = %02x\n", machine().describe_context(), 0x400000 + offset, data); } -READ32_MEMBER(sbus_bwtwo_device::vram_r) +READ32_MEMBER(sbus_bwtwo_device::rom_r) { - return m_vram[offset]; + return ((uint32_t*)m_rom->base())[offset]; } -READ32_MEMBER(sbus_bwtwo_device::rom_r) +READ8_MEMBER(sbus_bwtwo_device::vram_r) { - return ((uint32_t*)m_rom->base())[offset]; + return m_vram[offset]; } -WRITE32_MEMBER(sbus_bwtwo_device::vram_w) +WRITE8_MEMBER(sbus_bwtwo_device::vram_w) { - COMBINE_DATA(&m_vram[offset]); + m_vram[offset] = data; } diff --git a/src/devices/bus/sbus/bwtwo.h b/src/devices/bus/sbus/bwtwo.h index 0d4a96f2f39..fb3408db7d4 100644 --- a/src/devices/bus/sbus/bwtwo.h +++ b/src/devices/bus/sbus/bwtwo.h @@ -32,8 +32,8 @@ protected: DECLARE_READ8_MEMBER(regs_r); DECLARE_WRITE8_MEMBER(regs_w); DECLARE_READ32_MEMBER(rom_r); - DECLARE_READ32_MEMBER(vram_r); - DECLARE_WRITE32_MEMBER(vram_w); + DECLARE_READ8_MEMBER(vram_r); + DECLARE_WRITE8_MEMBER(vram_w); private: uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); @@ -41,8 +41,9 @@ private: void mem_map(address_map &map) override; required_memory_region m_rom; - std::unique_ptr m_vram; + std::unique_ptr m_vram; required_device m_screen; + uint32_t m_mono_lut[256][8]; }; diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp index 76ef7ac56e4..751e39610e3 100644 --- a/src/devices/cpu/sparc/mb86901.cpp +++ b/src/devices/cpu/sparc/mb86901.cpp @@ -8,6 +8,13 @@ // the integer instructions in a SPARC v7 // compatible instruction set. // +// Notes: +// - The CPU core implementation has been simplified +// somewhat compared to the spec. In particular, bus +// holding on read/write accesses is disabled, as there +// is currently no use made of it, and it is unlikely to +// ever be. +// // To-Do: // - Ops: FBFcc, LDF, STF // - Test: SPARCv8 ops are untested @@ -41,16 +48,9 @@ const int mb86901_device::NWINDOWS = 7; mb86901_device::mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, MB86901, tag, owner, clock) + , m_mmu(*this, finder_base::DUMMY_TAG) { m_default_config = address_space_config("program", ENDIANNESS_BIG, 32, 32); - - char buf[32]; - for (uint32_t i = 0; i < AS_COUNT; i++) - { - snprintf(buf, ARRAY_LENGTH(buf), "asi%d", i); - m_asi_names[i] = buf; - m_asi_config[i] = address_space_config(m_asi_names[i].c_str(), ENDIANNESS_BIG, 32, 32); - } } @@ -153,6 +153,29 @@ void mb86901_device::device_start() memset(m_privileged_asr, 1, 32 * sizeof(bool)); m_privileged_asr[0] = false; + memset(m_alu_setcc, 0, 64 * sizeof(bool)); + m_alu_setcc[OP3_ADDCC] = true; + m_alu_setcc[OP3_ANDCC] = true; + m_alu_setcc[OP3_ORCC] = true; + m_alu_setcc[OP3_XORCC] = true; + m_alu_setcc[OP3_SUBCC] = true; + m_alu_setcc[OP3_ANDNCC] = true; + m_alu_setcc[OP3_ORNCC] = true; + m_alu_setcc[OP3_XNORCC] = true; + m_alu_setcc[OP3_ADDXCC] = true; + m_alu_setcc[OP3_SUBXCC] = true; + m_alu_setcc[OP3_TADDCC] = true; + m_alu_setcc[OP3_TSUBCC] = true; + m_alu_setcc[OP3_TADDCCTV] = true; + m_alu_setcc[OP3_TSUBCCTV] = true; + m_alu_setcc[OP3_MULSCC] = true; +#if SPARCV8 + m_alu_setcc[OP3_UMULCC] = true; + m_alu_setcc[OP3_SMULCC] = true; + m_alu_setcc[OP3_UDIVCC] = true; + m_alu_setcc[OP3_SDIVCC] = true; +#endif + memset(m_alu_op3_assigned, 0, 64 * sizeof(bool)); m_alu_op3_assigned[OP3_ADD] = true; m_alu_op3_assigned[OP3_AND] = true; @@ -210,11 +233,6 @@ void mb86901_device::device_start() m_alu_op3_assigned[OP3_UDIVCC] = true; m_alu_op3_assigned[OP3_SDIVCC] = true; #endif - for (uint32_t i = 0; i < AS_COUNT; i++) - { - m_space[i] = &space(AS_START + i); - m_access_cache[i] = m_space[i]->cache<2, 0, ENDIANNESS_BIG>(); - } memset(m_ldst_op3_assigned, 0, 64 * sizeof(bool)); m_ldst_op3_assigned[OP3_LD] = true; @@ -379,6 +397,10 @@ void mb86901_device::device_stop() { } +void mb86901_device::device_resolve_objects() +{ + m_mmu->set_host(this); +} void mb86901_device::device_reset() { @@ -405,6 +427,8 @@ void mb86901_device::device_reset() m_bp_irl = 0; m_irq_state = 0; + m_stashed_icount = -1; + MAE = false; HOLD_BUS = false; m_annul = false; @@ -420,7 +444,8 @@ void mb86901_device::device_reset() PSR = PSR_S_MASK | PSR_PS_MASK; m_s = true; - m_fetch_space = 9; + m_insn_space = 9; + m_data_space = 11; for (int i = 0; i < 8; i++) { @@ -448,10 +473,6 @@ device_memory_interface::space_config_vector mb86901_device::memory_space_config { space_config_vector config_vector; config_vector.push_back(std::make_pair(AS_PROGRAM, &m_default_config)); - for (uint32_t i = 0; i < 32; i++) - { - config_vector.push_back(std::make_pair(AS_START + i, &m_asi_config[i])); - } return config_vector; } @@ -463,21 +484,10 @@ device_memory_interface::space_config_vector mb86901_device::memory_space_config // a 32-bit word in a big-endian system. //------------------------------------------------- -uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size) +uint32_t mb86901_device::read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask) { assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - if (size == 1) - { - return m_access_cache[asi]->read_byte(address) << ((3 - (address & 3)) * 8); - } - else if (size == 2) - { - return m_access_cache[asi]->read_word(address) << ((2 - (address & 2)) * 8); - } - else - { - return m_access_cache[asi]->read_dword(address); - } + return m_mmu->read_asi(asi, address >> 2, mem_mask); } @@ -490,21 +500,10 @@ uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size // size handlers //------------------------------------------------- -void mb86901_device::write_sized_word(uint8_t asi, uint32_t address, uint32_t data, int size) +void mb86901_device::write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask) { assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - if (size == 1) - { - m_access_cache[asi]->write_byte(address, data >> ((3 - (address & 3)) * 8)); - } - else if (size == 2) - { - m_access_cache[asi]->write_word(address, data >> ((2 - (address & 2)) * 8)); - } - else - { - m_access_cache[asi]->write_dword(address, data); - } + m_mmu->write_asi(asi, address >> 2, data, mem_mask); } @@ -911,10 +910,11 @@ void mb86901_device::execute_logical(uint32_t op) ); */ - uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; + const uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; + const uint32_t op3 = OP3; uint32_t result = 0; - switch (OP3) + switch (op3) { case OP3_AND: case OP3_ANDCC: @@ -945,11 +945,13 @@ void mb86901_device::execute_logical(uint32_t op) if (RD != 0) RDREG = result; - if (ANDCC || ANDNCC || ORCC || ORNCC || XORCC || XNORCC) + if (m_alu_setcc[op3]) { CLEAR_ICC; - PSR |= (BIT31(result)) ? PSR_N_MASK : 0; - PSR |= (result == 0) ? PSR_Z_MASK : 0; + if (result & 0x80000000) + PSR |= PSR_N_MASK; + else if (result == 0) + PSR |= PSR_Z_MASK; } PC = nPC; @@ -1205,7 +1207,16 @@ void mb86901_device::execute_wrsr(uint32_t op) m_et = PSR & PSR_ET_MASK; m_pil = (PSR & PSR_PIL_MASK) >> PSR_PIL_SHIFT; m_s = PSR & PSR_S_MASK; - m_fetch_space = m_s ? 9 : 8; + if (m_s) + { + m_insn_space = 9; + m_data_space = 11; + } + else + { + m_insn_space = 8; + m_data_space = 10; + } PC = nPC; nPC = nPC + 4; @@ -1304,6 +1315,8 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 3; m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; return; } else if ((WIM & (1 << new_cwp)) != 0) @@ -1313,6 +1326,8 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 6; m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; return; } else if (address & 3) @@ -1322,6 +1337,8 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 7; m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; return; } @@ -1337,13 +1354,15 @@ void mb86901_device::execute_rett(uint32_t op) { PSR |= PSR_S_MASK; m_s = true; - m_fetch_space = 9; + m_insn_space = 9; + m_data_space = 11; } else { PSR &= ~PSR_S_MASK; m_s = false; - m_fetch_space = 8; + m_insn_space = 8; + m_data_space = 10; } update_gpr_pointers(); @@ -1405,7 +1424,6 @@ void mb86901_device::execute_saverestore(uint32_t op) result = rs1 + operand2; PSR &= ~PSR_CWP_MASK; PSR |= new_cwp; - //BREAK_PSR; } else if (RESTORE) { @@ -1420,7 +1438,6 @@ void mb86901_device::execute_saverestore(uint32_t op) result = rs1 + operand2; PSR &= ~PSR_CWP_MASK; PSR |= new_cwp; - //BREAK_PSR; } update_gpr_pointers(); @@ -1475,7 +1492,7 @@ void mb86901_device::execute_jmpl(uint32_t op) // mostly ALU ops //------------------------------------------------- -void mb86901_device::execute_group2(uint32_t op) +inline void mb86901_device::execute_group2(uint32_t op) { switch (OP3) { @@ -1550,6 +1567,7 @@ void mb86901_device::execute_group2(uint32_t op) m_trap = 1; m_fp_disabled = 1; } + complete_fp_execution(op); return; case OP3_JMPL: @@ -1592,14 +1610,14 @@ void mb86901_device::execute_group2(uint32_t op) case OP3_CPOP1: case OP3_CPOP2: - printf("fpop @ %08x: %08x\n", PC, op); + logerror("fpop @ %08x: %08x\n", PC, op); m_trap = 1; m_cp_disabled = 1; return; #endif default: - printf("illegal instruction at %08x: %08x\n", PC, op); + logerror("illegal instruction at %08x: %08x\n", PC, op); m_trap = 1; m_illegal_instruction = 1; break; @@ -1768,7 +1786,7 @@ void mb86901_device::execute_store(uint32_t op) if (STD || ST || STH || STB || STF || STDF || STFSR || STDFQ || STCSR || STC || STDC || STDCQ) { address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + addr_space = m_data_space; } else if (STDA || STA || STHA || STBA) { @@ -1925,7 +1943,9 @@ void mb86901_device::execute_store(uint32_t op) } } - write_sized_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 4 : ((STH || STHA) ? 2 : 1)); + static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; + static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; + m_mmu->write_asi(addr_space, address >> 2, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 0xffffffff : ((STH || STHA) ? mask16[address & 2] : mask8[address & 3])); if (MAE) { m_trap = 1; @@ -1957,7 +1977,7 @@ void mb86901_device::execute_store(uint32_t op) data1 = 0; } - write_sized_word(addr_space, address + 4, data1, 4); + m_mmu->write_asi(addr_space, (address + 4) >> 2, data1, 0xffffffff); if (MAE) { m_trap = 1; @@ -2076,14 +2096,14 @@ void mb86901_device::execute_load(uint32_t op) ); */ - uint32_t address = 0; - uint8_t addr_space = 0; + static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; + static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; + switch (OP3) { case OP3_LDD: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 7) { @@ -2091,7 +2111,7 @@ void mb86901_device::execute_load(uint32_t op) m_mem_address_not_aligned = 1; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { @@ -2103,7 +2123,7 @@ void mb86901_device::execute_load(uint32_t op) if (RD != 0) RDREG = data; - const uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2116,8 +2136,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LD: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 3) { @@ -2126,7 +2145,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2141,8 +2160,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDSH: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 1) { @@ -2151,7 +2169,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2169,8 +2187,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDUH: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 1) { @@ -2179,7 +2196,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2197,10 +2214,9 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDSB: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2220,10 +2236,9 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDUB: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2243,8 +2258,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDDFPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) { @@ -2276,7 +2290,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2287,7 +2301,7 @@ void mb86901_device::execute_load(uint32_t op) FREG(RD & 0x1e) = data; - const uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2300,8 +2314,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDFPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) { @@ -2325,7 +2338,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2339,8 +2352,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDFSR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) { @@ -2364,7 +2376,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2378,8 +2390,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDDCPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { @@ -2403,7 +2414,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - read_sized_word(addr_space, address, 4); + m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2413,7 +2424,7 @@ void mb86901_device::execute_load(uint32_t op) // implementation-dependent actions - read_sized_word(addr_space, address + 4, 4); + m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2426,8 +2437,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDCPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { @@ -2451,7 +2461,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - read_sized_word(addr_space, address, 4); + m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { @@ -2465,8 +2475,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDCSR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { @@ -2490,7 +2499,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - read_sized_word(addr_space, address, 4); + m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { @@ -2516,11 +2525,9 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + + const uint32_t address = RS1REG + RS2REG; + const uint32_t addr_space = ASI; if (address & 7) { @@ -2529,7 +2536,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(addr_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2541,7 +2548,7 @@ void mb86901_device::execute_load(uint32_t op) if (RD != 0) RDREG = data; - uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + uint32_t word1 = m_mmu->read_asi(addr_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2566,11 +2573,8 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + + const uint32_t address = RS1REG + RS2REG; if (address & 3) { @@ -2579,7 +2583,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, 0xffffffff); if (m_mae) { @@ -2606,11 +2610,8 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + + const uint32_t address = RS1REG + RS2REG; if (address & 1) { @@ -2619,7 +2620,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2649,12 +2650,8 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + const uint32_t address = RS1REG + RS2REG; if (address & 1) { m_trap = 1; @@ -2662,7 +2659,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2692,13 +2689,9 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t address = RS1REG + RS2REG; + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2730,13 +2723,9 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t address = RS1REG + RS2REG; + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2868,7 +2857,8 @@ void mb86901_device::execute_ldstub(uint32_t op) m_pb_block_ldst_byte = 1; - data = read_sized_word(addr_space, address, 1); + static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; + data = m_mmu->read_asi(addr_space, address >> 2, mask8[address & 3]); if (MAE) { @@ -2877,24 +2867,7 @@ void mb86901_device::execute_ldstub(uint32_t op) return; } - //uint8_t byte_mask; - if ((address & 3) == 0) - { - //byte_mask = 8; - } - else if ((address & 3) == 1) - { - //byte_mask = 4; - } - else if ((address & 3) == 2) - { - //byte_mask = 2; - } - else if ((address & 3) == 3) - { - //byte_mask = 1; - } - write_sized_word(addr_space, address, 0xffffffff, 1); + m_mmu->write_asi(addr_space, address >> 2, 0xffffffff, mask8[address & 3]); m_pb_block_ldst_byte = 0; @@ -2935,7 +2908,7 @@ void mb86901_device::execute_ldstub(uint32_t op) // (load/store) //------------------------------------------------- -void mb86901_device::execute_group3(uint32_t op) +inline void mb86901_device::execute_group3(uint32_t op) { static const int ldst_cycles[64] = { 1, 1, 1, 2, 2, 2, 2, 3, @@ -3003,13 +2976,13 @@ void mb86901_device::execute_group3(uint32_t op) #endif default: - printf("illegal instruction at %08x: %08x\n", PC, op); + logerror("illegal instruction at %08x: %08x\n", PC, op); m_trap = 1; m_illegal_instruction = 1; break; } - if (MAE || HOLD_BUS) + if (MAE /*|| HOLD_BUS*/) m_icount--; else m_icount -= ldst_cycles[OP3]; @@ -3186,6 +3159,8 @@ void mb86901_device::select_trap() { m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; } else if (m_data_store_error) m_tt = 0x2b; @@ -3355,7 +3330,8 @@ void mb86901_device::execute_trap() PSR |= PSR_S_MASK; m_s = true; - m_fetch_space = 9; + m_insn_space = 9; + m_data_space = 11; int cwp = PSR & PSR_CWP_MASK; int new_cwp = ((cwp + NWINDOWS) - 1) % NWINDOWS; @@ -3425,13 +3401,14 @@ if (trap = 0) then ( inline void mb86901_device::dispatch_instruction(uint32_t op) { - switch (OP_NS) + const uint8_t op_type = OP; + switch (op_type) { - case OP_TYPE0_NS: // Bicc, SETHI, FBfcc + case OP_TYPE0: // Bicc, SETHI, FBfcc switch (OP2) { case OP2_UNIMP: // unimp - printf("unimp @ %x\n", PC); + logerror("unimp @ %x\n", PC); break; case OP2_BICC: // branch on integer condition codes execute_bicc(op); @@ -3446,7 +3423,7 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) case OP2_FBFCC: // branch on floating-point condition codes if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present) { - //printf("fbfcc at %08x: %08x\n", PC, op); + logerror("fbfcc at %08x: %08x\n", PC, op); m_trap = 1; m_fp_disabled = 1; return; @@ -3456,7 +3433,7 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) case OP2_CBCCC: // branch on coprocessor condition codes, SPARCv8 if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { - printf("cbccc @ %08x: %08x\n", PC, op); + logerror("cbccc @ %08x: %08x\n", PC, op); m_trap = 1; m_cp_disabled = 1; return; @@ -3464,14 +3441,14 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) return; #endif default: - printf("illegal instruction at %08x: %08x\n", PC, op); + logerror("illegal instruction at %08x: %08x\n", PC, op); m_trap = 1; m_illegal_instruction = 1; return; } break; - case OP_CALL_NS: // call + case OP_CALL: { uint32_t pc = PC; uint32_t callpc = PC + DISP30; @@ -3482,11 +3459,11 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) break; } - case OP_ALU_NS: + case OP_ALU: execute_group2(op); break; - case OP_LDST_NS: + case OP_LDST: execute_group3(op); break; } @@ -3506,7 +3483,7 @@ void mb86901_device::complete_fp_execution(uint32_t /*op*/) // mode (versus error or reset modes) //------------------------------------------------- -void mb86901_device::execute_step() +inline void mb86901_device::execute_step() { /* The SPARC Instruction Manual: Version 8, page 156, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 153) @@ -3565,7 +3542,8 @@ void mb86901_device::execute_step() m_execute_mode = 0; m_error_mode = 0; m_reset_mode = 1; - //printf("Entering reset mode\n"); + m_stashed_icount = m_icount; + m_icount = 0; return; } else if (m_et && (m_bp_irl == 15 || m_bp_irl > m_pil)) @@ -3577,51 +3555,35 @@ void mb86901_device::execute_step() if (m_trap) { execute_trap(); - //BREAK_PSR; - debugger_instruction_hook(PC); } - if (m_execute_mode) - { - // write-state-register delay not yet implemented + // write-state-register delay not yet implemented - const uint32_t op = read_sized_word(m_fetch_space, PC, 4); + const uint32_t op = m_mmu->read_asi(m_insn_space, PC >> 2, 0xffffffff); #if LOG_FCODES - //if (m_log_fcodes) - { - log_fcodes(); - } + //if (m_log_fcodes) + { + log_fcodes(); + } #endif - if (MAE && !m_annul) + if (MAE && !m_annul) + { + m_trap = 1; + m_instruction_access_exception = 1; + } + else + { + if (!m_annul) { - m_trap = 1; - m_instruction_access_exception = 1; + dispatch_instruction(op); } else { - if (!m_annul) - { - dispatch_instruction(op); - - if (FPOP1 || FPOP2) - { - complete_fp_execution(op); - } - - //if (m_trap == 0 && !(OP == OP_CALL || (OP == OP_TYPE0 && (OP2 == OP2_BICC || OP2 == OP2_FBFCC || OP2 == OP2_CBCCC)) || (OP == OP_ALU && (JMPL || TICC || RETT)))) - //{ - //PC = nPC; - //nPC = nPC + 4; - //} - } - else - { - m_annul = 0; - PC = nPC; - nPC = nPC + 4; - } + m_annul = 0; + PC = nPC; + nPC = nPC + 4; } } } @@ -3651,7 +3613,8 @@ void mb86901_device::reset_step() m_execute_mode = 1; m_trap = 1; m_reset_trap = 1; - //printf("m_bp_reset_in is false, resetting\n"); + m_stashed_icount = m_icount; + m_icount = 0; } } @@ -3678,44 +3641,39 @@ void mb86901_device::error_step() m_error_mode = 0; m_reset_mode = 1; m_pb_error = 0; + m_stashed_icount = m_icount; + m_icount = 0; } } - -//------------------------------------------------- -// execute_run - execute a timeslice's worth of -// opcodes -//------------------------------------------------- - -void mb86901_device::execute_run() +template +void mb86901_device::run_loop() { - bool debug = machine().debug_flags & DEBUG_FLAG_ENABLED; - - while (m_icount > 0) + do { - if (HOLD_BUS) + /*if (HOLD_BUS) { m_icount--; continue; - } + }*/ - //BREAK_PSR; - debugger_instruction_hook(PC); + if (CHECK_DEBUG) + debugger_instruction_hook(PC); - if (m_reset_mode) + if (MODE == MODE_RESET) { reset_step(); } - else if (m_error_mode) + else if (MODE == MODE_ERROR) { error_step(); } - else if (m_execute_mode) + else if (MODE == MODE_EXECUTE) { execute_step(); } - if (debug) + if (CHECK_DEBUG) { for (int i = 0; i < 8; i++) { @@ -3725,7 +3683,45 @@ void mb86901_device::execute_run() } } --m_icount; - } + } while (m_icount >= 0); +} + +//------------------------------------------------- +// execute_run - execute a timeslice's worth of +// opcodes +//------------------------------------------------- + +void mb86901_device::execute_run() +{ + bool debug = machine().debug_flags & DEBUG_FLAG_ENABLED; + + do + { + if (debug) + { + if (m_reset_mode) + run_loop(); + else if (m_error_mode) + run_loop(); + else + run_loop(); + } + else + { + if (m_reset_mode) + run_loop(); + else if (m_error_mode) + run_loop(); + else + run_loop(); + } + + if (m_stashed_icount >= 0) + { + m_icount = m_stashed_icount; + m_stashed_icount = -1; + } + } while (m_icount >= 0); } diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h index 41264b6ed2b..1bbcccc44fe 100644 --- a/src/devices/cpu/sparc/sparc.h +++ b/src/devices/cpu/sparc/sparc.h @@ -10,6 +10,7 @@ #pragma once #include "sparcdasm.h" +#include "sparc_intf.h" #define SPARCV8 (1) #define LOG_FCODES (0) @@ -22,28 +23,18 @@ #define MCFG_SPARC_ADD_ASI_DESC(desc) \ downcast(*device).add_asi_desc([](sparc_disassembler *dasm) { dasm->add_asi_desc(desc); }); -class mb86901_device : public cpu_device, protected sparc_disassembler::config +class mb86901_device : public cpu_device, public sparc_mmu_host_interface, protected sparc_disassembler::config { public: mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - enum - { - AS_COUNT = 32, - - AS_START = 128, - AS_END = AS_START + (AS_COUNT - 1) - }; - - template void set_asi_addrmap(int asi, T &&obj) - { - set_addrmap(asi + AS_START, std::forward(obj)); - } + template void set_mmu(T &&tag) { m_mmu.set_tag(std::forward(tag)); } // device-level overrides virtual void device_start() override; virtual void device_reset() override; virtual void device_stop() override; + virtual void device_resolve_objects() override; // device_execute_interface overrides virtual uint32_t execute_min_cycles() const override; @@ -63,7 +54,7 @@ public: uint8_t get_asi() { return 0; } uint32_t pc() { return m_pc; } - void set_mae() { m_mae = 1; } + void set_mae() override { m_mae = 1; } void add_asi_desc(std::function f) { m_asi_desc_adder = f; } @@ -92,7 +83,7 @@ protected: void execute_mul(uint32_t op); void execute_div(uint32_t op); #endif - void execute_group2(uint32_t op); + inline void execute_group2(uint32_t op); void execute_load(uint32_t op); void execute_store(uint32_t op); @@ -100,7 +91,7 @@ protected: #if SPARCV8 void execute_swap(uint32_t op); #endif - void execute_group3(uint32_t op); + inline void execute_group3(uint32_t op); bool evaluate_condition(uint32_t op); void execute_bicc(uint32_t op); @@ -111,26 +102,33 @@ protected: void complete_instruction_execution(uint32_t op); inline void dispatch_instruction(uint32_t op); void complete_fp_execution(uint32_t /*op*/); - void execute_step(); + inline void execute_step(); void reset_step(); void error_step(); + enum running_mode + { + MODE_RESET, + MODE_ERROR, + MODE_EXECUTE + }; + + template void run_loop(); #if LOG_FCODES void indent(); void disassemble_ss1_fcode(uint32_t r5, uint32_t opcode, uint32_t handler_base, uint32_t entry_point, uint32_t stack); void log_fcodes(); #endif + required_device m_mmu; + // address spaces - std::string m_asi_names[AS_COUNT]; - address_space_config m_asi_config[AS_COUNT]; - memory_access_cache<2, 0, ENDIANNESS_BIG> *m_access_cache[AS_COUNT]; address_space_config m_default_config; // memory access - uint32_t read_sized_word(uint8_t asi, uint32_t address, int size); - void write_sized_word(uint8_t asi, uint32_t address, uint32_t data, int size); + uint32_t read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask); + void write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask); // helpers for the disassembler virtual uint64_t get_reg_r(unsigned index) const override; @@ -209,6 +207,7 @@ protected: bool m_alu_op3_assigned[64]; bool m_ldst_op3_assigned[64]; + bool m_alu_setcc[64]; // register windowing helpers uint32_t* m_regs[32]; @@ -220,14 +219,13 @@ protected: bool m_annul; bool m_hold_bus; int m_icount; - int m_fetch_space; + int m_stashed_icount; + int m_insn_space; + int m_data_space; // debugger helpers uint32_t m_dbgregs[24]; - // address spaces - address_space *m_space[32]; - #if LOG_FCODES uint32_t m_ss1_next_pc; uint32_t m_ss1_next_opcode; diff --git a/src/devices/cpu/sparc/sparc_intf.h b/src/devices/cpu/sparc/sparc_intf.h new file mode 100644 index 00000000000..a203abd92ea --- /dev/null +++ b/src/devices/cpu/sparc/sparc_intf.h @@ -0,0 +1,30 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + sparc_intf.h - Sun SPARC MMU interfaces + +***************************************************************************/ + +#ifndef MAME_CPU_SPARC_SPARC_INTF_H +#define MAME_CPU_SPARC_SPARC_INTF_H + +#pragma once + +class sparc_mmu_host_interface +{ +public: + virtual ~sparc_mmu_host_interface() { } + virtual void set_mae() = 0; +}; + +class sparc_mmu_interface +{ +public: + virtual ~sparc_mmu_interface() { } + virtual void set_host(sparc_mmu_host_interface *host) = 0; + virtual uint32_t read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) = 0; + virtual void write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) = 0; +}; + +#endif // MAME_CPU_SPARC_SPARC_INTF_H \ No newline at end of file diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h index 0ae566ad5a7..050f1aa1f74 100644 --- a/src/devices/cpu/sparc/sparcdefs.h +++ b/src/devices/cpu/sparc/sparcdefs.h @@ -105,7 +105,7 @@ #define SHCNT32 (op & 31) #define SHCNT64 (op & 63) #define IAMODE (op & 0x7) -#define USEIMM ((op >> 13) & 1) +#define USEIMM (op & (1 << 13)) #define USEEXT ((op >> 12) & 1) diff --git a/src/devices/machine/ncr5390.cpp b/src/devices/machine/ncr5390.cpp index 8d9f4b9641b..135bcdb9705 100644 --- a/src/devices/machine/ncr5390.cpp +++ b/src/devices/machine/ncr5390.cpp @@ -33,6 +33,42 @@ void ncr5390_device::map(address_map &map) map(0x9, 0x9).w(FUNC(ncr5390_device::clock_w)); } +READ8_MEMBER(ncr5390_device::read) +{ + switch (offset) + { + case 0: return tcounter_lo_r(space, 0); + case 1: return tcounter_hi_r(space, 0); + case 2: return fifo_r(space, 0); + case 3: return command_r(space, 0); + case 4: return status_r(space, 0); + case 5: return istatus_r(space, 0); + case 6: return seq_step_r(space, 0); + case 7: return fifo_flags_r(space, 0); + case 8: return conf_r(space, 0); + default: return 0; + } +} + +WRITE8_MEMBER(ncr5390_device::write) +{ + switch (offset) + { + case 0: tcount_lo_w(space, 0, data); break; + case 1: tcount_hi_w(space, 0, data); break; + case 2: fifo_w(space, 0, data); break; + case 3: command_w(space, 0, data); break; + case 4: bus_id_w(space, 0, data); break; + case 5: timeout_w(space, 0, data); break; + case 6: sync_period_w(space, 0, data); break; + case 7: sync_offset_w(space, 0, data); break; + case 8: conf_w(space, 0, data); break; + case 9: clock_w(space, 0, data); break; + case 10: test_w(space, 0, data); break; + default: break; + } +} + void ncr53c90a_device::map(address_map &map) { ncr5390_device::map(map); @@ -40,6 +76,20 @@ void ncr53c90a_device::map(address_map &map) map(0xb, 0xb).rw(FUNC(ncr53c90a_device::conf2_r), FUNC(ncr53c90a_device::conf2_w)); } +READ8_MEMBER(ncr53c90a_device::read) +{ + if (offset == 11) + return conf2_r(space, 0); + return ncr5390_device::read(space, offset); +} + +WRITE8_MEMBER(ncr53c90a_device::write) +{ + if (offset == 11) + return conf2_w(space, 0, data); + ncr5390_device::write(space, offset, data); +} + void ncr53c94_device::map(address_map &map) { ncr53c90a_device::map(map); @@ -48,6 +98,23 @@ void ncr53c94_device::map(address_map &map) map(0xf, 0xf).w(FUNC(ncr53c94_device::fifo_align_w)); } +READ8_MEMBER(ncr53c94_device::read) +{ + if (offset == 12) + return conf3_r(space, 0); + return ncr53c90a_device::read(space, offset); +} + +WRITE8_MEMBER(ncr53c94_device::write) +{ + if (offset == 11) + conf3_w(space, 0, data); + else if (offset == 15) + fifo_align_w(space, 0, data); + else + ncr53c90a_device::write(space, offset, data); +} + ncr5390_device::ncr5390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : nscsi_device(mconfig, type, tag, owner, clock) , tm(nullptr), config(0), status(0), istatus(0), clock_conv(0), sync_offset(0), sync_period(0), bus_id(0) diff --git a/src/devices/machine/ncr5390.h b/src/devices/machine/ncr5390.h index 9a2bed1bc28..d39b352ddb7 100644 --- a/src/devices/machine/ncr5390.h +++ b/src/devices/machine/ncr5390.h @@ -48,6 +48,9 @@ public: DECLARE_WRITE8_MEMBER(test_w); DECLARE_WRITE8_MEMBER(clock_w); + virtual DECLARE_READ8_MEMBER(read); + virtual DECLARE_WRITE8_MEMBER(write); + virtual void scsi_ctrl_changed() override; uint8_t dma_r(); @@ -264,6 +267,9 @@ public: DECLARE_READ8_MEMBER(conf2_r) { return config2; }; DECLARE_WRITE8_MEMBER(conf2_w) { config2 = data; }; + DECLARE_READ8_MEMBER(read) override; + DECLARE_WRITE8_MEMBER(write) override; + protected: ncr53c90a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -292,6 +298,9 @@ public: DECLARE_WRITE8_MEMBER(conf3_w) { config3 = data; }; DECLARE_WRITE8_MEMBER(fifo_align_w) { fifo_align = data; }; + DECLARE_READ8_MEMBER(read) override; + DECLARE_WRITE8_MEMBER(write) override; + protected: virtual void device_start() override; void reset_soft(); diff --git a/src/devices/machine/sun4c_mmu.cpp b/src/devices/machine/sun4c_mmu.cpp new file mode 100644 index 00000000000..68290f1fac9 --- /dev/null +++ b/src/devices/machine/sun4c_mmu.cpp @@ -0,0 +1,497 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + sun4c_mmu.cpp - Sun 4c MMU emulation + +***************************************************************************/ + +#include "emu.h" +#include "sun4c_mmu.h" +#include "cpu/sparc/sparc.h" + +DEFINE_DEVICE_TYPE(SUN4C_MMU, sun4c_mmu_device, "sun4c_mmu", "Sun 4C MMU") + +sun4c_mmu_device::sun4c_mmu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SUN4C_MMU, tag, owner, clock) + , m_cpu(*this, finder_base::DUMMY_TAG) + , m_ram(*this, finder_base::DUMMY_TAG) + , m_rom(*this, finder_base::DUMMY_TAG) + , m_scc(*this, finder_base::DUMMY_TAG) + , m_host(nullptr) + , m_type1_r(*this) + , m_type1_w(*this) + , m_rom_ptr(nullptr) + , m_ram_ptr(nullptr) + , m_ram_size(0) + , m_ram_size_words(0) + , m_context(0) + , m_context_masked(0) + , m_system_enable(0) + , m_fetch_bootrom(true) + , m_curr_segmap(nullptr) + , m_curr_segmap_masked(nullptr) +{ +} + +void sun4c_mmu_device::device_start() +{ + m_type1_r.resolve_safe(0xffffffff); + m_type1_w.resolve_safe(); + + // allocate timer for system reset + m_reset_timer = timer_alloc(TIMER_RESET); + m_reset_timer->adjust(attotime::never); +} + +void sun4c_mmu_device::device_reset() +{ + m_rom_ptr = (uint32_t *)m_rom->base(); + m_ram_ptr = (uint32_t *)m_ram->pointer(); + m_ram_size = m_ram->size(); + m_ram_size_words = m_ram_size >> 2; + + m_context = 0; + m_context_masked = 0; + m_curr_segmap = m_segmap[0]; + m_curr_segmap_masked = m_segmap_masked[0]; + m_system_enable = 0; + m_fetch_bootrom = true; + + memset(m_buserr, 0, sizeof(uint32_t) * 4); + memset(m_segmap, 0, sizeof(uint8_t) * 16 * 4096); + memset(m_pagemap, 0, sizeof(page_entry_t) * 16384); + memset(m_cachetags, 0, sizeof(uint32_t) * 16384); + memset(m_cachedata, 0, sizeof(uint32_t) * 16384); +} + +void sun4c_mmu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_RESET) + { + m_reset_timer->adjust(attotime::never); + m_cpu->set_input_line(SPARC_RESET, CLEAR_LINE); + //printf("Clearing reset line\n"); + } +} + +uint32_t sun4c_mmu_device::read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) +{ + //logerror("read_asi %d: %08x & %08x\n", asi, offset << 2, mem_mask); + switch (asi) + { + case 2: + return system_r(offset, mem_mask); + case 3: + return segment_map_r(offset, mem_mask); + case 4: + return page_map_r(offset, mem_mask); + case 8: + return insn_data_r(offset, mem_mask); + case 9: + return insn_data_r(offset, mem_mask); + case 10: + return insn_data_r(offset, mem_mask); + case 11: + return insn_data_r(offset, mem_mask); + case 12: + case 13: + case 14: + cache_flush_r(); + return 0; + default: + return ~0; + } +} + +void sun4c_mmu_device::write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + //logerror("write_asi %d: %08x = %08x & %08x\n", asi, offset << 2, data, mem_mask); + switch (asi) + { + case 2: + system_w(offset, data, mem_mask); + return; + case 3: + segment_map_w(offset, data, mem_mask); + return; + case 4: + page_map_w(offset, data, mem_mask); + return; + case 8: + insn_data_w(offset, data, mem_mask); + return; + case 9: + insn_data_w(offset, data, mem_mask); + return; + case 10: + insn_data_w(offset, data, mem_mask); + return; + case 11: + insn_data_w(offset, data, mem_mask); + return; + case 12: + case 13: + case 14: + cache_flush_w(); + return; + default: + return; + } +} + +uint32_t sun4c_mmu_device::cache_flush_r() +{ + // Do nothing for now + return 0; +} + +void sun4c_mmu_device::cache_flush_w() +{ + // Do nothing for now +} + +uint32_t sun4c_mmu_device::system_r(const uint32_t offset, const uint32_t mem_mask) +{ + //logerror("%s: system_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); + switch (offset >> 26) + { + case 3: // context reg + if (mem_mask == 0x00ff0000) return m_context<<16; + return m_context<<24; + + case 4: // system enable reg + return m_system_enable<<24; + + case 6: // bus error register + { + //printf("sun4c_mmu: read buserror %08x, PC=%x (mask %08x)\n", 0x60000000 | (offset << 2), m_cpu->pc(), mem_mask); + const uint32_t retval = m_buserr[offset & 0xf]; + m_buserr[offset & 0xf] = 0; // clear on reading + return retval; + } + + case 8: // (d-)cache tags + //logerror("sun4_mmu: read dcache tags @ %x, PC = %x\n", offset, m_cpu->pc()); + return m_cachetags[(offset >> 3) & 0x3fff]; + + case 9: // (d-)cache data + //logerror("sun4c_mmu: read dcache data @ %x, PC = %x\n", offset, m_cpu->pc()); + return m_cachedata[offset & 0x3fff]; + + case 0xf: // UART bypass + //printf("sun4c_mmu: read UART bypass @ %x mask %08x\n", offset<<2, mem_mask); + switch (offset & 3) + { + case 0: if (mem_mask == 0xff000000) return m_scc->cb_r(0)<<24; else return m_scc->db_r(0)<<8; break; + case 1: if (mem_mask == 0xff000000) return m_scc->ca_r(0)<<24; else return m_scc->da_r(0)<<8; break; + } + return 0xffffffff; + + case 0: // IDPROM - SPARCstation-1 does not have an ID prom and a timeout should occur. + default: + logerror("%s: sun4c_mmu: ASI 2 space unhandled read @ %x\n", machine().describe_context(), offset<<2); + return 0; + } +} + +void sun4c_mmu_device::system_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +{ + //logerror("%s: system_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); + switch (offset >> 26) + { + case 3: // context reg + //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset); + m_context = data >> 24; + m_context_masked = m_context & m_ctx_mask; + m_curr_segmap = m_segmap[m_context_masked]; + m_curr_segmap_masked = m_segmap_masked[m_context_masked]; + return; + + case 4: // system enable reg + { + m_system_enable = data >> 24; + m_fetch_bootrom = !(m_system_enable & ENA_NOTBOOT); + + if (m_system_enable & ENA_RESET) + { + m_reset_timer->adjust(attotime::from_usec(1)); + m_cpu->set_input_line(SPARC_RESET, ASSERT_LINE); + //logerror("%s: Asserting reset line\n", machine().describe_context()); + } + //printf("%08x to system enable, mask %08x\n", data, mem_mask); + if (m_system_enable & ENA_RESET) + { + m_system_enable = 0; + m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + } + return; + } + + case 6: // bus error + //logerror("%08x to bus error @ %x, mask %08x\n", data, offset, mem_mask); + m_buserr[offset & 0xf] = data; + return; + + case 8: // cache tags + //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_cpu->pc()); + m_cachetags[(offset>>3)&0x3fff] = data & 0x03f8fffc; + return; + + case 9: // cache data + //logerror("sun4c: %08x to cache data @ %x, PC = %x\n", data, offset, m_cpu->pc()); + m_cachedata[offset&0x3fff] = data; + return; + + case 0xf: // UART bypass + //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask); + switch (offset & 3) + { + case 0: if (mem_mask == 0xff000000) m_scc->cb_w(0, data>>24); else m_scc->db_w(0, data>>8); break; + case 1: if (mem_mask == 0xff000000) m_scc->ca_w(0, data>>24); else { m_scc->da_w(0, data>>8); printf("%c", data>>8); } break; + } + return; + + case 0: // IDPROM + default: + logerror("sun4c: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x, shift %x)\n", data, offset<<2, mem_mask, m_cpu->pc(), offset>>26); + return; + } +} + +uint32_t sun4c_mmu_device::segment_map_r(const uint32_t offset, const uint32_t mem_mask) +{ + //logerror("%s: segment_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); + if (mem_mask == 0xffff0000) + return m_curr_segmap[(offset>>16) & 0xfff]<<16; + else if (mem_mask == 0xff000000) + return m_curr_segmap[(offset>>16) & 0xfff]<<24; + else + logerror("sun4: read segment map w/ unknown mask %08x\n", mem_mask); + return 0; +} + +void sun4c_mmu_device::segment_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +{ + //logerror("segment_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); + + uint8_t segdata = 0; + if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0xff; + else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0xff; + else logerror("sun4c: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_cpu->pc()); + + const uint32_t seg = (offset>>16) & 0xfff; + m_curr_segmap[seg] = segdata; + m_curr_segmap_masked[seg] = (segdata & m_pmeg_mask) << 6; +} + +uint32_t sun4c_mmu_device::page_map_r(const uint32_t offset, const uint32_t mem_mask) +{ + //logerror("%s: page_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); + const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f); + return m_pagemap[page].to_uint(); +} + +void sun4c_mmu_device::page_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +{ + //logerror("%s: page_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); + const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f); + m_pagemap[page].merge_uint(data, mem_mask); + m_page_valid[page] = m_pagemap[page].valid; +} + +void sun4c_mmu_device::type0_timeout_r(const uint32_t offset) +{ + m_buserr[0] = 0x20; // read timeout + m_buserr[1] = 0x04000000 + (offset << 2); + m_host->set_mae(); +} + +void sun4c_mmu_device::type0_timeout_w(const uint32_t offset) +{ + m_buserr[0] = 0x8020; // write timeout + m_buserr[1] = 0x04000000 + (offset << 2); + m_host->set_mae(); +} + +uint32_t sun4c_mmu_device::page_entry_t::to_uint() +{ + return valid | writable | supervisor | uncached | (type << 26) | accessed | modified | (page >> 10); +} + +void sun4c_mmu_device::page_entry_t::merge_uint(uint32_t data, uint32_t mem_mask) +{ + const uint32_t new_value = (to_uint() & ~mem_mask) | (data & mem_mask); + valid = new_value & PM_VALID; + writable = new_value & PM_WRITEMASK; + supervisor = new_value & PM_SYSMASK; + uncached = new_value & PM_CACHE; + type = (new_value & PM_TYPEMASK) >> 26; + accessed = new_value & PM_ACCESSED; + modified = new_value & PM_MODIFIED; + page = (new_value & 0xffff) << 10; +} + +template uint32_t sun4c_mmu_device::insn_data_r(const uint32_t, const uint32_t); +template uint32_t sun4c_mmu_device::insn_data_r(const uint32_t, const uint32_t); +template uint32_t sun4c_mmu_device::insn_data_r(const uint32_t, const uint32_t); +template uint32_t sun4c_mmu_device::insn_data_r(const uint32_t, const uint32_t); + +template +uint32_t sun4c_mmu_device::insn_data_r(const uint32_t offset, const uint32_t mem_mask) +{ + // supervisor program fetches in boot state are special + if (m_fetch_bootrom && MODE == SUPER_INSN) + { + return m_rom_ptr[offset & 0x1ffff]; + } + + // it's translation time + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; + const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); + + if (m_page_valid[entry_index]) + { + page_entry_t &entry = m_pagemap[entry_index]; + entry.accessed = PM_ACCESSED; + + const uint32_t tmp = entry.page | (offset & 0x3ff); + + //printf("sun4c: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_cpu->pc()); + + switch (entry.type) + { + case 0: // type 0 space + //return m_type0space->read32(space, tmp, mem_mask); + if (tmp < 0x1000000 >> 2) + { + return m_ram_ptr[tmp]; + } + else if (tmp >= 0x4000000 >> 2 && tmp < 0x10000000 >> 2) + { + type0_timeout_r(tmp); + } + return ~0; + + case 1: // type 1 space + return m_type1_r(tmp, mem_mask); + + default: + //logerror("sun4c_mmu: access to memory type not defined in sun4c\n"); + m_host->set_mae(); + m_buserr[0] = 0x20; + m_buserr[1] = offset << 2; + return 0; + } + } + else + { + if (!machine().side_effects_disabled()) + { + //logerror("sun4c: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), offset <<2, m_cpu->pc()); + m_host->set_mae(); + m_buserr[0] |= 0x80; // invalid PTE + m_buserr[0] &= ~0x8000; // read + m_buserr[1] = offset << 2; + if (mem_mask != ~0 && mem_mask != 0xffff0000 && mem_mask != 0xff000000) + { + if (mem_mask == 0x0000ffff || mem_mask == 0x0000ff00) + { + m_buserr[1] |= 2; + } + else if (mem_mask == 0x00ff0000) + { + m_buserr[1] |= 1; + } + else if (mem_mask == 0x000000ff) + { + m_buserr[1] |= 3; + } + } + } + return 0; + } +} + +template void sun4c_mmu_device::insn_data_w(const uint32_t, const uint32_t, const uint32_t); +template void sun4c_mmu_device::insn_data_w(const uint32_t, const uint32_t, const uint32_t); +template void sun4c_mmu_device::insn_data_w(const uint32_t, const uint32_t, const uint32_t); +template void sun4c_mmu_device::insn_data_w(const uint32_t, const uint32_t, const uint32_t); + +template +void sun4c_mmu_device::insn_data_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +{ + // it's translation time + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; + const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); + + if (m_page_valid[entry_index]) + { + page_entry_t &entry = m_pagemap[entry_index]; + if ((!entry.writable) || (entry.supervisor && MODE != SUPER_DATA && MODE != SUPER_INSN)) + { + //logerror("sun4c: write protect MMU error (PC=%x)\n", m_cpu->pc()); + m_buserr[0] |= 0x8040; // write, protection error + m_buserr[1] = offset << 2; + m_host->set_mae(); + return; + } + + entry.accessed = PM_ACCESSED; + entry.modified = PM_MODIFIED; + + const uint32_t tmp = entry.page | (offset & 0x3ff); + + //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, ASI %d, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), asi, m_cpu->pc()); + + switch (entry.type) + { + case 0: // type 0 + if (tmp < 0x1000000 >> 2) + { + COMBINE_DATA((m_ram_ptr + tmp)); + } + else if (tmp >= 0x4000000 >> 2 && tmp < 0x10000000 >> 2) + { + type0_timeout_w(tmp); + } + return; + + case 1: // type 1 + //printf("write device space @ %x = %08x\n", tmp << 2, data); + m_type1_w(tmp, data, mem_mask); + return; + + default: + //logerror("sun4c_mmu: access to memory type not defined\n"); + m_host->set_mae(); + m_buserr[0] = 0x8020; + m_buserr[1] = offset << 2; + return; + } + } + else + { + //logerror("sun4c: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), data, offset <<2, m_cpu->pc()); + m_host->set_mae(); + m_buserr[0] |= 0x8080; // write cycle, invalid PTE + m_buserr[1] = offset << 2; + if (mem_mask != ~0 && mem_mask != 0xffff0000 && mem_mask != 0xff000000) + { + if (mem_mask == 0x0000ffff || mem_mask == 0x0000ff00) + { + m_buserr[1] |= 2; + } + else if (mem_mask == 0x00ff0000) + { + m_buserr[1] |= 1; + } + else if (mem_mask == 0x000000ff) + { + m_buserr[1] |= 3; + } + } + } +} + diff --git a/src/devices/machine/sun4c_mmu.h b/src/devices/machine/sun4c_mmu.h new file mode 100644 index 00000000000..0beafb73c29 --- /dev/null +++ b/src/devices/machine/sun4c_mmu.h @@ -0,0 +1,149 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + sun4c_mmu.h - Sun 4c MMU emulation + +***************************************************************************/ + +#ifndef MAME_MACHINE_SUN4C_MMU_H +#define MAME_MACHINE_SUN4C_MMU_H + +#pragma once + +#include "cpu/sparc/sparc_intf.h" +#include "machine/ram.h" +#include "machine/z80scc.h" + +class sun4c_mmu_device : public device_t, public sparc_mmu_interface +{ +public: + sun4c_mmu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint8_t ctx_mask, uint8_t pmeg_mask) + : sun4c_mmu_device(mconfig, tag, owner, clock) + { + m_ctx_mask = ctx_mask; + m_pmeg_mask = pmeg_mask; + } + + sun4c_mmu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template void set_cpu(T &&cpu_tag) { m_cpu.set_tag(std::forward(cpu_tag)); } + template void set_ram(T &&ram_tag) { m_ram.set_tag(std::forward(ram_tag)); } + template void set_rom(T &&rom_tag) { m_rom.set_tag(std::forward(rom_tag)); } + template void set_scc(T &&scc_tag) { m_scc.set_tag(std::forward(scc_tag)); } + + enum insn_data_mode + { + USER_INSN, + SUPER_INSN, + USER_DATA, + SUPER_DATA + }; + + template uint32_t insn_data_r(const uint32_t offset, const uint32_t mem_mask); + template void insn_data_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); + + auto type1_r() { return m_type1_r.bind(); } + auto type1_w() { return m_type1_w.bind(); } + + // sparc_mmu_device overrides + uint32_t read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) override; + void write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) override; + void set_host(sparc_mmu_host_interface *host) override { logerror("Setting host\n"); m_host = host; } + +protected: + static const device_timer_id TIMER_RESET = 0; + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + uint32_t cache_flush_r(); + void cache_flush_w(); + uint32_t system_r(const uint32_t offset, const uint32_t mem_mask); + void system_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); + uint32_t segment_map_r(const uint32_t offset, const uint32_t mem_mask); + void segment_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); + uint32_t page_map_r(const uint32_t offset, const uint32_t mem_mask); + void page_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); + void type0_timeout_r(const uint32_t offset); + void type0_timeout_w(const uint32_t offset); + + enum + { + // system enable constants + ENA_NOTBOOT = 0x80, + ENA_SDVMA = 0x20, + ENA_CACHE = 0x10, + ENA_RESET = 0x04, + ENA_DIAG = 0x01, + + // page table entry constants + PM_VALID = 0x80000000, // page is valid + PM_WRITEMASK = 0x40000000, // writable? + PM_SYSMASK = 0x20000000, // system use only? + PM_CACHE = 0x10000000, // cachable? + PM_TYPEMASK = 0x0c000000, // type mask + PM_ACCESSED = 0x02000000, // accessed flag + PM_MODIFIED = 0x01000000 // modified flag + }; + + struct page_entry_t + { + uint32_t valid; + uint32_t writable; + uint32_t supervisor; + uint32_t uncached; + uint32_t accessed; + uint32_t modified; + uint32_t page; + uint8_t type; + uint8_t pad[3]; + + uint32_t to_uint(); + void merge_uint(uint32_t data, uint32_t mem_mask); + }; + + required_device m_cpu; + required_device m_ram; + required_memory_region m_rom; + required_device m_scc; + + sparc_mmu_host_interface *m_host; + + // Bus access callbacks + devcb_read32 m_type1_r; + devcb_write32 m_type1_w; + + // Actual SRAM + uint8_t m_segmap[16][4096]; + page_entry_t m_pagemap[16384]; + uint32_t m_cachetags[16384]; + uint32_t m_cachedata[16384]; + + uint32_t *m_rom_ptr; + uint32_t *m_ram_ptr; + uint32_t m_ram_size; + uint32_t m_ram_size_words; + uint32_t m_context; + uint32_t m_context_masked; + uint8_t m_system_enable; + bool m_fetch_bootrom; + uint32_t m_buserr[4]; + + // Pre-computed data for optimization purposes + uint32_t m_segmap_masked[16][4096]; + uint8_t *m_curr_segmap; + uint32_t *m_curr_segmap_masked; + bool m_page_valid[16384]; + + // Internal MAME device state + uint8_t m_ctx_mask; // SS2 is sun4c but has 16 contexts; most have 8 + uint8_t m_pmeg_mask; // SS2 is sun4c but has 16384 PTEs; most have 8192 + emu_timer *m_reset_timer; +}; + + +DECLARE_DEVICE_TYPE(SUN4C_MMU, sun4c_mmu_device) + +#endif // MAME_MACHINE_SUN4C_MMU_H \ No newline at end of file diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp index dd967d6af27..711d58b8b49 100644 --- a/src/devices/machine/z80scc.cpp +++ b/src/devices/machine/z80scc.cpp @@ -2590,10 +2590,10 @@ void z80scc_channel::m_tx_fifo_rp_step() } } -READ8_MEMBER (z80scc_device::da_r) { return m_chanA->data_read(); } -WRITE8_MEMBER (z80scc_device::da_w) { m_chanA->data_write(data); } -READ8_MEMBER (z80scc_device::db_r) { return m_chanB->data_read(); } -WRITE8_MEMBER (z80scc_device::db_w) { m_chanB->data_write(data); } +uint8_t z80scc_device::da_r(offs_t offset) { return m_chanA->data_read(); } +void z80scc_device::da_w(offs_t offset, uint8_t data) { m_chanA->data_write(data); } +uint8_t z80scc_device::db_r(offs_t offset) { return m_chanB->data_read(); } +void z80scc_device::db_w(offs_t offset, uint8_t data) { m_chanB->data_write(data); } //------------------------------------------------- // data_write - write data register diff --git a/src/devices/machine/z80scc.h b/src/devices/machine/z80scc.h index 259536290da..e2cad9e660b 100644 --- a/src/devices/machine/z80scc.h +++ b/src/devices/machine/z80scc.h @@ -363,15 +363,15 @@ public: DECLARE_WRITE8_MEMBER( ba_cd_inv_w ); /* Definitions moved to z80scc.c for enhancements */ - DECLARE_READ8_MEMBER( da_r ); // { return m_chanA->data_read(); } - DECLARE_WRITE8_MEMBER( da_w ); // { m_chanA->data_write(data); } - DECLARE_READ8_MEMBER( db_r ); // { return m_chanB->data_read(); } - DECLARE_WRITE8_MEMBER( db_w ); // { m_chanB->data_write(data); } - - DECLARE_READ8_MEMBER( ca_r ) { return m_chanA->control_read(); } - DECLARE_WRITE8_MEMBER( ca_w ) { m_chanA->control_write(data); } - DECLARE_READ8_MEMBER( cb_r ) { return m_chanB->control_read(); } - DECLARE_WRITE8_MEMBER( cb_w ) { m_chanB->control_write(data); } + uint8_t da_r(offs_t offset); + void da_w(offs_t offset, uint8_t data); + uint8_t db_r(offs_t offset); + void db_w(offs_t offset, uint8_t data); + + uint8_t ca_r(offs_t offset) { return m_chanA->control_read(); } + void ca_w(offs_t offset, uint8_t data) { m_chanA->control_write(data); } + uint8_t cb_r(offs_t offset) { return m_chanB->control_read(); } + void cb_w(offs_t offset, uint8_t data) { m_chanB->control_write(data); } DECLARE_READ8_MEMBER( zbus_r ); DECLARE_WRITE8_MEMBER( zbus_w ); diff --git a/src/mame/drivers/apple2gs.cpp b/src/mame/drivers/apple2gs.cpp index 237e5b74ebc..237965808c5 100644 --- a/src/mame/drivers/apple2gs.cpp +++ b/src/mame/drivers/apple2gs.cpp @@ -2227,16 +2227,16 @@ READ8_MEMBER(apple2gs_state::c000_r) return m_speed; case 0x38: // SCCBREG - return m_scc->cb_r(space, 0); + return m_scc->cb_r(0); case 0x39: // SCCAREG - return m_scc->ca_r(space, 0); + return m_scc->ca_r(0); case 0x3a: // SCCBDATA - return m_scc->db_r(space, 0); + return m_scc->db_r(0); case 0x3b: // SCCADATA - return m_scc->da_r(space, 0); + return m_scc->da_r(0); case 0x3c: // SOUNDCTL return m_sndglu_ctrl; @@ -2549,19 +2549,19 @@ WRITE8_MEMBER(apple2gs_state::c000_w) break; case 0x38: // SCCBREG - m_scc->cb_w(space, 0, data); + m_scc->cb_w(0, data); break; case 0x39: // SCCAREG - m_scc->ca_w(space, 0, data); + m_scc->ca_w(0, data); break; case 0x3a: // SCCBDATA - m_scc->db_w(space, 0, data); + m_scc->db_w(0, data); break; case 0x3b: // SCCADATA - m_scc->da_w(space, 0, data); + m_scc->da_w(0, data); break; case 0x3c: // SOUNDCTL diff --git a/src/mame/drivers/sun4.cpp b/src/mame/drivers/sun4.cpp index 8127d3258e3..8855cfa70a6 100644 --- a/src/mame/drivers/sun4.cpp +++ b/src/mame/drivers/sun4.cpp @@ -425,6 +425,7 @@ #include "machine/nscsi_hd.h" #include "machine/nvram.h" #include "machine/ram.h" +#include "machine/sun4c_mmu.h" #include "machine/timekpr.h" #include "machine/upd765.h" #include "machine/z80scc.h" @@ -449,23 +450,6 @@ #define FDC_TAG "fdc" #define LANCE_TAG "lance" -#define ENA_NOTBOOT (0x80) -#define ENA_SDVMA (0x20) -#define ENA_CACHE (0x10) -#define ENA_RESET (0x04) -#define ENA_DIAG (0x01) - -// page table entry constants -#define PM_VALID (0x80000000) // page is valid -#define PM_WRITEMASK (0x40000000) // writable? -#define PM_SYSMASK (0x20000000) // system use only? -#define PM_CACHE (0x10000000) // cachable? -#define PM_TYPEMASK (0x0c000000) // type mask -#define PM_ACCESSED (0x02000000) // accessed flag -#define PM_MODIFIED (0x01000000) // modified flag - -#define PAGE_SIZE (0x00000400) - // DMA controller constants #define DMA_DEV_ID (0x80000000) #define DMA_L (0x00008000) // use ILACC @@ -547,6 +531,7 @@ public: sun4_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") + , m_mmu(*this, "mmu") , m_timekpr(*this, TIMEKEEPER_TAG) , m_scc1(*this, SCC1_TAG) , m_scc2(*this, SCC2_TAG) @@ -561,13 +546,13 @@ public: , m_ram(*this, RAM_TAG) , m_rom(*this, "user1") , m_rom_ptr(nullptr) - , m_system_enable(0) { } void sun4c(machine_config &config); void sun4_40(machine_config &config); void sun4_60(machine_config &config); + void sun4_75(machine_config &config); void sun4(machine_config &config); void init_sun4(); @@ -591,6 +576,25 @@ private: SUPER_DATA }; + enum + { + // system enable constants + ENA_NOTBOOT = 0x80, + ENA_SDVMA = 0x20, + ENA_CACHE = 0x10, + ENA_RESET = 0x04, + ENA_DIAG = 0x01, + + // page table entry constants + PM_VALID = 0x80000000, // page is valid + PM_WRITEMASK = 0x40000000, // writable? + PM_SYSMASK = 0x20000000, // system use only? + PM_CACHE = 0x10000000, // cachable? + PM_TYPEMASK = 0x0c000000, // type mask + PM_ACCESSED = 0x02000000, // accessed flag + PM_MODIFIED = 0x01000000 // modified flag + }; + DECLARE_READ32_MEMBER( sun4_cache_flush_r ); DECLARE_WRITE32_MEMBER( sun4_cache_flush_w ); DECLARE_READ32_MEMBER( sun4_system_r ); @@ -602,16 +606,8 @@ private: template DECLARE_READ32_MEMBER( sun4_insn_data_r ); DECLARE_WRITE32_MEMBER( sun4_insn_data_w ); - DECLARE_READ32_MEMBER( sun4c_cache_flush_r ); - DECLARE_WRITE32_MEMBER( sun4c_cache_flush_w ); - DECLARE_READ32_MEMBER( sun4c_system_r ); - DECLARE_WRITE32_MEMBER( sun4c_system_w ); - DECLARE_READ32_MEMBER( sun4c_segment_map_r ); - DECLARE_WRITE32_MEMBER( sun4c_segment_map_w ); - DECLARE_READ32_MEMBER( sun4c_page_map_r ); - DECLARE_WRITE32_MEMBER( sun4c_page_map_w ); - template DECLARE_READ32_MEMBER( sun4c_insn_data_r ); - template DECLARE_WRITE32_MEMBER( sun4c_insn_data_w ); + DECLARE_READ32_MEMBER( sun4c_debugger_r ); + DECLARE_WRITE32_MEMBER( sun4c_debugger_w ); DECLARE_READ32_MEMBER( sun4_mmu_r ); DECLARE_WRITE32_MEMBER( sun4_mmu_w ); @@ -656,14 +652,7 @@ private: void sun4_data_map(address_map &map); void sun4_supervisor_data_map(address_map &map); - void sun4c_system_map(address_map &map); - void sun4c_segment_map(address_map &map); - void sun4c_page_map(address_map &map); - void sun4c_insn_map(address_map &map); - void sun4c_supervisor_insn_map(address_map &map); - void sun4c_data_map(address_map &map); - void sun4c_supervisor_data_map(address_map &map); - void sun4c_cache_flush_map(address_map &map); + void sun4c_debugger_map(address_map &map); void type0space_map(address_map &map); void type1space_map(address_map &map); @@ -677,6 +666,7 @@ private: }; required_device m_maincpu; + required_device m_mmu; required_device m_timekpr; @@ -696,21 +686,6 @@ private: required_device m_ram; required_memory_region m_rom; - uint32_t *m_rom_ptr; - uint32_t m_context; - uint32_t m_context_masked; - uint8_t m_system_enable; - bool m_fetch_bootrom; - uint8_t m_auxio; - uint32_t m_buserr[4]; - uint32_t m_counter[4]; - uint32_t m_dma[4]; - bool m_dma_irq; - bool m_dma_tc_read; - uint32_t m_dma_pack_register; - int m_scsi_irq; - int m_fdc_irq; - struct page_entry_t { uint32_t valid; @@ -723,16 +698,14 @@ private: uint8_t type; uint8_t pad[3]; - template uint32_t to_uint() { - return valid | writable | supervisor | uncached | (type << 26) | accessed | modified | (ARCH_4C ? (page >> 10) : (page >> 11)); + return valid | writable | supervisor | uncached | (type << 26) | accessed | modified | (page >> 11); } - template void merge_uint(uint32_t data, uint32_t mem_mask) { - const uint32_t new_value = (to_uint() & ~mem_mask) | (data & mem_mask); + const uint32_t new_value = (to_uint() & ~mem_mask) | (data & mem_mask); valid = new_value & PM_VALID; writable = new_value & PM_WRITEMASK; supervisor = new_value & PM_SYSMASK; @@ -740,23 +713,39 @@ private: type = (new_value & PM_TYPEMASK) >> 26; accessed = new_value & PM_ACCESSED; modified = new_value & PM_MODIFIED; - page = ARCH_4C ? ((new_value & 0xffff) << 10) : ((new_value & 0x7ffff) << 11); + page = (new_value & 0x7ffff) << 11; } }; - uint32_t *m_ram_ptr; uint8_t m_segmap[16][4096]; - uint8_t *m_curr_segmap; - uint32_t m_segmap_masked[16][4096]; - uint32_t *m_curr_segmap_masked; page_entry_t m_pagemap[16384]; - bool m_page_valid[16384]; - uint32_t m_cachetags[0x4000]; - uint32_t m_cachedata[0x4000]; + uint32_t m_cachetags[16384]; + uint32_t m_cachedata[16384]; + + uint32_t *m_rom_ptr; + uint32_t *m_ram_ptr; uint32_t m_ram_size; uint32_t m_ram_size_words; - uint8_t m_ctx_mask; // SS2 is sun4c but has 16 contexts; most have 8 - uint8_t m_pmeg_mask; // SS2 is sun4c but has 16384 PTEs; most have 8192 + uint32_t m_context; + uint32_t m_context_masked; + uint8_t m_system_enable; + bool m_fetch_bootrom; + uint32_t m_buserr[4]; + + uint32_t m_segmap_masked[16][4096]; + uint8_t *m_curr_segmap; + uint32_t *m_curr_segmap_masked; + bool m_page_valid[16384]; + + uint8_t m_auxio; + uint32_t m_counter[4]; + uint32_t m_dma[4]; + bool m_dma_irq; + bool m_dma_tc_read; + uint32_t m_dma_pack_register; + int m_scsi_irq; + int m_fdc_irq; + uint8_t m_irq_reg; // IRQ control uint8_t m_scc1_int, m_scc2_int; uint8_t m_diag; @@ -776,353 +765,6 @@ private: void fcodes_command(int ref, const std::vector ¶ms); }; -READ32_MEMBER( sun4_state::sun4c_cache_flush_r ) -{ - // Do nothing for now - return 0; -} - -WRITE32_MEMBER( sun4_state::sun4c_cache_flush_w ) -{ - // Do nothing for now -} - -READ32_MEMBER( sun4_state::sun4c_system_r ) -{ - //logerror("%s: system_space_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); - switch (offset >> 26) - { - case 3: // context reg - if (mem_mask == 0x00ff0000) return m_context<<16; - return m_context<<24; - - case 4: // system enable reg - return m_system_enable<<24; - - case 6: // bus error register - { - //printf("sun4c: read buserror %08x, PC=%x (mask %08x)\n", 0x60000000 | (offset << 2), m_maincpu->pc(), mem_mask); - const uint32_t retval = m_buserr[offset & 0xf]; - m_buserr[offset & 0xf] = 0; // clear on reading - return retval; - } - - case 8: // (d-)cache tags - //logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc()); - return m_cachetags[(offset>>3)&0x3fff]; - - case 9: // (d-)cache data - //logerror("sun4c: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc()); - return m_cachedata[offset&0x3fff]; - - case 0xf: // UART bypass - //printf("read UART bypass @ %x mask %08x\n", offset<<2, mem_mask); - switch (offset & 3) - { - case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(space, offset)<<24; else return m_scc2->db_r(space, offset)<<8; break; - case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(space, offset)<<24; else return m_scc2->da_r(space, offset)<<8; break; - } - return 0xffffffff; - - case 0: // IDPROM - TODO: SPARCstation-1 does not have an ID prom and a timeout should occur. - default: - logerror("sun4c: ASI 2 space unhandled read @ %x (PC=%x)\n", offset<<2, m_maincpu->pc()); - return 0; - } -} - -WRITE32_MEMBER( sun4_state::sun4c_system_w ) -{ - //logerror("%s: system_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); - switch (offset >> 26) - { - case 3: // context reg - //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset); - m_context = data>>24; - m_context_masked = m_context & m_ctx_mask; - m_curr_segmap = m_segmap[m_context_masked]; - m_curr_segmap_masked = m_segmap_masked[m_context_masked]; - return; - - case 4: // system enable reg - { - const uint8_t old_enable = m_system_enable; - m_system_enable = data>>24; - m_fetch_bootrom = !(m_system_enable & ENA_NOTBOOT); - - if (m_system_enable & ENA_RESET) - { - m_reset_timer->adjust(attotime::from_usec(1)); - m_maincpu->set_input_line(SPARC_RESET, ASSERT_LINE); - logerror("%s: Asserting reset line\n", machine().describe_context()); - } - //printf("%08x to system enable, mask %08x\n", data, mem_mask); - if (m_system_enable & ENA_RESET) - { - m_system_enable = 0; - m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - } - - if ((old_enable ^ m_system_enable) & ENA_NOTBOOT) - { - //printf("%c", (m_system_enable & ENA_NOTBOOT) ? 'A' : 'B'); - /*if (m_system_enable & ENA_NOTBOOT) - { - m_maincpu->space(mb86901_device::AS_START + 9).install_readwrite_handler(0x00000000, 0xffffffff, 0, 0, 0 - , read32_delegate(FUNC(sun4_state::sun4c_insn_data_r), this) - , write32_delegate(FUNC(sun4_state::sun4c_insn_data_w), this)); - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x00000000, 0xffffffff, 0, 0, 0 - , read32_delegate(FUNC(sun4_state::sun4c_insn_data_r), this) - , write32_delegate(FUNC(sun4_state::sun4c_insn_data_w), this)); - } - else - { - m_maincpu->space(mb86901_device::AS_START + 9).install_rom(0x00000000, 0x7ffff, 0xfff80000, m_rom_ptr); - m_maincpu->space(AS_PROGRAM).install_rom(0x00000000, 0x7ffff, 0xfff80000, m_rom_ptr); - }*/ - } - return; - } - - case 6: // bus error - logerror("%08x to bus error @ %x, mask %08x\n", data, offset, mem_mask); - m_buserr[offset & 0xf] = data; - return; - - case 8: // cache tags - //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc()); - m_cachetags[(offset>>3)&0x3fff] = data & 0x03f8fffc; - return; - - case 9: // cache data - //logerror("sun4c: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc()); - m_cachedata[offset&0x3fff] = data; - return; - - case 0xf: // UART bypass - //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask); - switch (offset & 3) - { - case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(space, offset, data>>24); else m_scc2->db_w(space, offset, data>>8); break; - case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(space, offset, data>>24); else { m_scc2->da_w(space, offset, data>>8); printf("%c", data>>8); } break; - } - return; - - case 0: // IDPROM - default: - logerror("sun4c: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x, shift %x)\n", data, offset<<2, mem_mask, m_maincpu->pc(), offset>>26); - return; - } -} - -READ32_MEMBER( sun4_state::sun4c_segment_map_r ) -{ - //logerror("%s: segment_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); - //printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context_masked, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc()); - if (mem_mask == 0xffff0000) - return m_curr_segmap[(offset>>16) & 0xfff]<<16; - else if (mem_mask == 0xff000000) - return m_curr_segmap[(offset>>16) & 0xfff]<<24; - else - logerror("sun4: read segment map w/ unknown mask %08x\n", mem_mask); - return 0; -} - -WRITE32_MEMBER( sun4_state::sun4c_segment_map_w ) -{ - logerror("segment_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); - uint8_t segdata = 0; - //printf("segment write, mask %08x, PC=%x\n", mem_mask, m_maincpu->pc()); - if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0xff; - else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0xff; - else logerror("sun4c: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_maincpu->pc()); - - //printf("sun4c: %08x to segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, m_context_masked, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc()); - const uint32_t seg = (offset>>16) & 0xfff; - m_curr_segmap[seg] = segdata; - m_curr_segmap_masked[seg] = (segdata & m_pmeg_mask) << 6; -} - -READ32_MEMBER( sun4_state::sun4c_page_map_r ) -{ - //logerror("%s: page_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); - const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f); - //printf("sun4: read page map @ %x (entry %d, seg %d, PMEG %d, mem_mask %08x, PC=%x)\n", offset << 2, page, (offset >> 16) & 0xfff, m_curr_segmap_masked[(offset >> 16) & 0xfff] >> 6, mem_mask, m_maincpu->pc()); - return m_pagemap[page].to_uint(); -} - -WRITE32_MEMBER( sun4_state::sun4c_page_map_w ) -{ - //logerror("%s: page_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); - const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f); - //printf("sun4c: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc()); - m_pagemap[page].merge_uint(data, mem_mask); - m_page_valid[page] = m_pagemap[page].valid; -} - -template -READ32_MEMBER( sun4_state::sun4c_insn_data_r ) -{ - // supervisor program fetches in boot state are special - if (m_fetch_bootrom && MODE == SUPER_INSN) - { - return m_rom_ptr[offset & 0x1ffff]; - } - - // it's translation time - const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; - const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); - - if (m_page_valid[entry_index]) - { - page_entry_t &entry = m_pagemap[entry_index]; - entry.accessed = PM_ACCESSED; - - const uint32_t tmp = entry.page | (offset & 0x3ff); - - //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); - - switch (entry.type) - { - case 0: // type 0 space - //return m_type0space->read32(space, tmp, mem_mask); - if (tmp < 0x1000000>>2) - { - return m_ram_ptr[tmp]; - } - else if (tmp >= 0x4000000>>2 && tmp < 0x10000000>>2) - { - timeout_r(space, tmp, mem_mask); - } - return ~0; - - case 1: // type 1 space - // magic EPROM bypass - if ((tmp >= (0x6000000>>2)) && (tmp <= (0x6ffffff>>2))) - { - return m_rom_ptr[offset & 0x1ffff]; - } - //printf("Read type 1 @ VA %08x, phys %08x\n", offset<<2, tmp<<2); - return m_type1space->read32(space, tmp, mem_mask); - - default: - logerror("sun4c: access to memory type not defined in sun4c\n"); - m_maincpu->set_mae(); - m_buserr[0] = 0x20; - m_buserr[1] = offset << 2; - return 0; - } - } - else - { - if (!machine().side_effects_disabled()) - { - logerror("sun4c: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), offset <<2, m_maincpu->pc()); - m_maincpu->set_mae(); - m_buserr[0] |= 0x80; // invalid PTE - m_buserr[0] &= ~0x8000; // read - m_buserr[1] = offset<<2; - if (mem_mask != ~0 && mem_mask != 0xffff0000 && mem_mask != 0xff000000) - { - if (mem_mask == 0x0000ffff || mem_mask == 0x0000ff00) - { - m_buserr[1] |= 2; - } - else if (mem_mask == 0x00ff0000) - { - m_buserr[1] |= 1; - } - else if (mem_mask == 0x000000ff) - { - m_buserr[1] |= 3; - } - } - } - return 0; - } -} - -template -WRITE32_MEMBER( sun4_state::sun4c_insn_data_w ) -{ - // it's translation time - const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; - const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); - - if (m_page_valid[entry_index]) - { - page_entry_t &entry = m_pagemap[entry_index]; - if ((!entry.writable) || (entry.supervisor && MODE != SUPER_DATA && MODE != SUPER_INSN)) - { - logerror("sun4c: write protect MMU error (PC=%x)\n", m_maincpu->pc()); - m_buserr[0] |= 0x8040; // write, protection error - m_buserr[1] = offset<<2; - m_maincpu->set_mae(); - return; - } - - entry.accessed = PM_ACCESSED; - entry.modified = PM_MODIFIED; - - const uint32_t tmp = entry.page | (offset & 0x3ff); - - //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, ASI %d, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), asi, m_maincpu->pc()); - - switch (entry.type) - { - case 0: // type 0 - //m_type0space->write32(space, tmp, data, mem_mask); - if (tmp < 0x1000000>>2) - { - COMBINE_DATA((m_ram_ptr + tmp)); - } - else if (tmp >= 0x4000000>>2 && tmp < 0x10000000>>2) - { - timeout_w(space, tmp, data, mem_mask); - } - return; - - case 1: // type 1 - //printf("write device space @ %x\n", tmp<<1); - m_type1space->write32(space, tmp, data, mem_mask); - return; - - default: - logerror("sun4c: access to memory type not defined\n"); - m_maincpu->set_mae(); - m_buserr[0] = 0x8020; - m_buserr[1] = offset << 2; - return; - } - } - else - { - logerror("sun4c: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), data, offset <<2, m_maincpu->pc()); - m_maincpu->set_mae(); - m_buserr[0] |= 0x8080; // write cycle, invalid PTE - m_buserr[1] = offset<<2; - if (mem_mask != ~0 && mem_mask != 0xffff0000 && mem_mask != 0xff000000) - { - if (mem_mask == 0x0000ffff || mem_mask == 0x0000ff00) - { - m_buserr[1] |= 2; - } - else if (mem_mask == 0x00ff0000) - { - m_buserr[1] |= 1; - } - else if (mem_mask == 0x000000ff) - { - m_buserr[1] |= 3; - } - } - } -} - - -// ----------------------------------------------------------------- - READ32_MEMBER( sun4_state::sun4_system_r ) { switch (offset >> 26) @@ -1150,8 +792,8 @@ READ32_MEMBER( sun4_state::sun4_system_r ) //printf("read UART bypass @ %x mask %08x (PC=%x)\n", offset<<2, mem_mask, m_maincpu->pc()); switch (offset & 3) { - case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(space, offset)<<24; else return m_scc2->db_r(space, offset)<<8; break; - case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(space, offset)<<24; else return m_scc2->da_r(space, offset)<<8; break; + case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(offset)<<24; else return m_scc2->db_r(offset)<<8; break; + case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(offset)<<24; else return m_scc2->da_r(offset)<<8; break; } return 0xffffffff; @@ -1221,8 +863,8 @@ WRITE32_MEMBER( sun4_state::sun4_system_w ) //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask); switch (offset & 3) { - case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(space, offset, data>>24); else m_scc2->db_w(space, offset, data>>8); break; - case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(space, offset, data>>24); else { m_scc2->da_w(space, offset, data>>8); printf("%c", data>>8); } break; + case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(offset, data>>24); else m_scc2->db_w(offset, data>>8); break; + case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(offset, data>>24); else { m_scc2->da_w(offset, data>>8); printf("%c", data>>8); } break; } return; @@ -1262,17 +904,27 @@ READ32_MEMBER( sun4_state::sun4_page_map_r ) { uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 11) & 0x1f); //printf("sun4: read page map @ %x (entry %d, seg %d, PMEG %d, mem_mask %08x, PC=%x)\n", offset << 2, page, (offset >> 16) & 0xfff, m_segmap[m_context][(offset >> 16) & 0xfff] & m_pmeg_mask, mem_mask, m_maincpu->pc()); - return m_pagemap[page].to_uint(); + return m_pagemap[page].to_uint(); } WRITE32_MEMBER( sun4_state::sun4_page_map_w ) { const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 11) & 0x1f); //printf("sun4: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc()); - m_pagemap[page].merge_uint(data, mem_mask); + m_pagemap[page].merge_uint(data, mem_mask); m_page_valid[page] = m_pagemap[page].valid; } +READ32_MEMBER( sun4_state::sun4c_debugger_r ) +{ + return m_mmu->insn_data_r(offset, mem_mask); +} + +WRITE32_MEMBER( sun4_state::sun4c_debugger_w ) +{ + m_mmu->insn_data_w(offset, data, mem_mask); +} + template READ32_MEMBER( sun4_state::sun4_insn_data_r ) { @@ -1293,7 +945,7 @@ READ32_MEMBER( sun4_state::sun4_insn_data_r ) const uint32_t tmp = entry.page | (offset & 0x7ff); - //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); + //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); switch (entry.type) { @@ -1318,7 +970,7 @@ READ32_MEMBER( sun4_state::sun4_insn_data_r ) { if (!machine().side_effects_disabled()) { - logerror("sun4: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), offset <<2, m_maincpu->pc()); + logerror("sun4: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), offset <<2, m_maincpu->pc()); m_maincpu->set_mae(); m_buserr[0] |= 0x80; // invalid PTE m_buserr[0] &= ~0x8000; // read @@ -1356,7 +1008,7 @@ WRITE32_MEMBER( sun4_state::sun4_insn_data_w ) uint32_t tmp = entry.page | (offset & 0x7ff); - //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); + //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint(), m_maincpu->pc()); switch (entry.type) { @@ -1376,7 +1028,7 @@ WRITE32_MEMBER( sun4_state::sun4_insn_data_w ) } else { - logerror("sun4: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), data, offset <<2, m_maincpu->pc()); + logerror("sun4: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint(), data, offset <<2, m_maincpu->pc()); //m_maincpu->trap(SPARC_DATA_ACCESS_EXCEPTION); //m_buserr[0] = 0x8; // invalid PTE //m_buserr[1] = offset<<2; @@ -1404,14 +1056,7 @@ void sun4_state::l2p_command(int ref, const std::vector ¶ms) pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; entry_index = pmeg | ((offset >> 11) & 0x1f); tmp = m_pagemap[entry_index].page | (offset & 0x7ff); - entry_value = m_pagemap[entry_index].to_uint(); - } - else if (m_arch == ARCH_SUN4C) - { - pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; - entry_index = pmeg | ((offset >> 10) & 0x3f); - tmp = m_pagemap[entry_index].page | (offset & 0x3ff); - entry_value = m_pagemap[entry_index].to_uint(); + entry_value = m_pagemap[entry_index].to_uint(); } if (m_page_valid[entry_index]) @@ -1480,44 +1125,9 @@ void sun4_state::sun4_data_map(address_map &map) map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r), FUNC(sun4_state::sun4_insn_data_w)); } -void sun4_state::sun4c_system_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_system_r), FUNC(sun4_state::sun4c_system_w)); -} - -void sun4_state::sun4c_segment_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_segment_map_r), FUNC(sun4_state::sun4c_segment_map_w)); -} - -void sun4_state::sun4c_page_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_page_map_r), FUNC(sun4_state::sun4c_page_map_w)); -} - -void sun4_state::sun4c_supervisor_insn_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r), FUNC(sun4_state::sun4c_insn_data_w)); -} - -void sun4_state::sun4c_supervisor_data_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r), FUNC(sun4_state::sun4c_insn_data_w)); -} - -void sun4_state::sun4c_insn_map(address_map &map) +void sun4_state::sun4c_debugger_map(address_map &map) { - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r), FUNC(sun4_state::sun4c_insn_data_w)); -} - -void sun4_state::sun4c_data_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r), FUNC(sun4_state::sun4c_insn_data_w)); -} - -void sun4_state::sun4c_cache_flush_map(address_map &map) -{ - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_cache_flush_r), FUNC(sun4_state::sun4c_cache_flush_w)); + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_debugger_r), FUNC(sun4_state::sun4c_debugger_w)); } void sun4_state::type0space_map(address_map &map) @@ -1561,12 +1171,6 @@ INPUT_PORTS_END void sun4_state::machine_reset() { - m_context = 0; - m_context_masked = 0; - m_curr_segmap = m_segmap[0]; - m_curr_segmap_masked = m_segmap_masked[0]; - m_system_enable = 0; - m_fetch_bootrom = true; m_auxio = 0xc0; m_irq_reg = 0; m_scc1_int = m_scc2_int = 0; @@ -1587,12 +1191,6 @@ void sun4_state::machine_start() m_ram_size = m_ram->size(); m_ram_size_words = m_ram_size >> 2; - //m_maincpu->space(mb86901_device::AS_START + 9).install_rom(0x00000, 0x7ffff, 0xfff80000, m_rom_ptr); - //m_maincpu->space(AS_PROGRAM).install_rom(0x00000, 0x7ffff, 0xfff80000, m_rom_ptr); - //memory_space().install_ram(start << 8, (start << 8) | 0x00ffU, m_memory); - - m_type1_cache = m_type1space->space(0).cache<2, 0, ENDIANNESS_BIG>(); // Not currently used - unsure how to make it work - if (machine().debug_flags & DEBUG_FLAG_ENABLED) { using namespace std::placeholders; @@ -1613,21 +1211,6 @@ void sun4_state::machine_start() m_reset_timer->adjust(attotime::never); } -READ32_MEMBER( sun4_state::timeout_r ) -{ - m_buserr[0] = 0x20; // read timeout - m_buserr[1] = 0x04000000 + (offset << 2); - m_maincpu->set_mae(); - return ~0; -} - -WRITE32_MEMBER( sun4_state::timeout_w ) -{ - m_buserr[0] = 0x8020; // write timeout - m_buserr[1] = 0x04000000 + (offset << 2); - m_maincpu->set_mae(); -} - READ32_MEMBER( sun4_state::ram_r ) { return m_ram_ptr[offset]; @@ -1695,6 +1278,21 @@ WRITE32_MEMBER( sun4_state::ram_w ) COMBINE_DATA(&m_ram_ptr[offset]); } +READ32_MEMBER( sun4_state::timeout_r ) +{ + m_buserr[0] = 0x20; // read timeout + m_buserr[1] = 0x04000000 + (offset << 2); + m_maincpu->set_mae(); + return 0; +} + +WRITE32_MEMBER( sun4_state::timeout_w ) +{ + m_buserr[0] = 0x8020; // write timeout + m_buserr[1] = 0x04000000 + (offset << 2); + m_maincpu->set_mae(); +} + READ8_MEMBER( sun4_state::fdc_r ) { if (machine().side_effects_disabled()) @@ -1952,8 +1550,6 @@ void sun4_state::dma_transfer_write() { //logerror("DMAing from device to RAM\n"); - address_space &space = m_maincpu->space(mb86901_device::AS_START+9); - uint8_t pack_cnt = (m_dma[DMA_CTRL] & DMA_PACK_CNT) >> DMA_PACK_CNT_SHIFT; while (m_dma[DMA_CTRL] & DMA_REQ_PEND) { @@ -1970,13 +1566,9 @@ void sun4_state::dma_transfer_write() { //logerror("Writing pack register %08x to %08x\n", m_dma_pack_register, m_dma[DMA_ADDR]); if (m_arch == ARCH_SUN4C) - { - sun4c_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); - } - else - { - sun4c_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); - } + m_mmu->insn_data_w(m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); + //else - TODO + //sun4_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); pack_cnt = 0; m_dma_pack_register = 0; @@ -1992,8 +1584,6 @@ void sun4_state::dma_transfer_read() { //logerror("DMAing from RAM to device\n"); - address_space &space = m_maincpu->space(mb86901_device::AS_START+9); - bool word_cached = false; uint32_t current_word = 0; while (m_dma[DMA_CTRL] & DMA_REQ_PEND) @@ -2001,13 +1591,9 @@ void sun4_state::dma_transfer_read() if (!word_cached) { if (m_arch == ARCH_SUN4C) - { - current_word = sun4c_insn_data_r(space, m_dma[DMA_ADDR] >> 2, ~0); - } - else - { - current_word = sun4c_insn_data_r(space, m_dma[DMA_ADDR] >> 2, ~0); - } + current_word = m_mmu->insn_data_r(m_dma[DMA_ADDR] >> 2, ~0); + //else - TODO + //current_word = sun4_insn_data_r(space, m_dma[DMA_ADDR] >> 2, ~0); word_cached = true; //logerror("Current word: %08x\n", current_word); } @@ -2029,13 +1615,9 @@ void sun4_state::dma_transfer_read() void sun4_state::dma_transfer() { if (m_dma[DMA_CTRL] & DMA_WRITE) - { dma_transfer_write(); - } else - { dma_transfer_read(); - } if (m_dma[DMA_BYTE_COUNT] == 0 && (m_dma[DMA_CTRL] & DMA_EN_CNT)) { @@ -2088,7 +1670,10 @@ WRITE32_MEMBER( sun4_state::dma_w ) const uint32_t bit_index = (3 - i) * 8; //const uint32_t value = m_dma_pack_register & (0xff << bit_index); //logerror("dma_w: draining %02x to RAM address %08x & %08x\n", value >> bit_index, m_dma[DMA_ADDR], 0xff << (24 - bit_index)); - sun4c_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); + if (m_arch == ARCH_SUN4C) + m_mmu->insn_data_w(m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); + else + sun4_insn_data_w(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); m_dma[DMA_ADDR]++; } m_dma_pack_register = 0; @@ -2159,7 +1744,7 @@ READ32_MEMBER( sun4_state::lance_dma_r ) if (m_arch == ARCH_SUN4) return sun4_insn_data_r(space, offset, mem_mask); else - return sun4c_insn_data_r(space, offset, mem_mask); + return m_mmu->insn_data_r(offset, mem_mask); } WRITE32_MEMBER( sun4_state::lance_dma_w ) @@ -2167,7 +1752,7 @@ WRITE32_MEMBER( sun4_state::lance_dma_w ) if (m_arch == ARCH_SUN4) sun4_insn_data_w(space, offset, data, mem_mask); else - sun4c_insn_data_w(space, offset, data, mem_mask); + m_mmu->insn_data_w(offset, data, mem_mask); } WRITE32_MEMBER( sun4_state::buserr_w ) @@ -2214,15 +1799,19 @@ void sun4_state::ncr53c90a(device_t *device) MACHINE_CONFIG_START(sun4_state::sun4) /* basic machine hardware */ - MCFG_DEVICE_ADD(m_maincpu, MB86901, 16670000) + MCFG_DEVICE_ADD(m_maincpu, MB86901, 16'670'000) MCFG_SPARC_ADD_ASI_DESC(sun4_asi_desc) - m_maincpu->set_asi_addrmap(2, &sun4_state::sun4_system_map); - m_maincpu->set_asi_addrmap(3, &sun4_state::sun4_segment_map); - m_maincpu->set_asi_addrmap(4, &sun4_state::sun4_page_map); - m_maincpu->set_asi_addrmap(8, &sun4_state::sun4_insn_map); - m_maincpu->set_asi_addrmap(9, &sun4_state::sun4_supervisor_insn_map); - m_maincpu->set_asi_addrmap(10, &sun4_state::sun4_data_map); - m_maincpu->set_asi_addrmap(11, &sun4_state::sun4_supervisor_data_map); + m_maincpu->set_addrmap(0, &sun4_state::sun4c_debugger_map); + + // TODO: MMU for sun4 hardware + SUN4C_MMU(config, m_mmu, 25'000'000, 7, 0x7f); + m_mmu->type1_r().set(m_type1space, FUNC(address_map_bank_device::read32)); + m_mmu->type1_w().set(m_type1space, FUNC(address_map_bank_device::write32)); + m_mmu->set_cpu(m_maincpu); + m_mmu->set_ram(m_ram); + m_mmu->set_rom("user1"); + m_mmu->set_scc(m_scc2); + m_maincpu->set_mmu(m_mmu); RAM(config, RAM_TAG).set_default_size("16M").set_default_value(0x00); @@ -2284,19 +1873,18 @@ MACHINE_CONFIG_END MACHINE_CONFIG_START(sun4_state::sun4c) /* basic machine hardware */ - MCFG_DEVICE_ADD(m_maincpu, MB86901, 16670000) + MCFG_DEVICE_ADD(m_maincpu, MB86901, 16'670'000) MCFG_SPARC_ADD_ASI_DESC(sun4c_asi_desc) - m_maincpu->set_addrmap(0, &sun4_state::sun4c_supervisor_insn_map); - m_maincpu->set_asi_addrmap(2, &sun4_state::sun4c_system_map); - m_maincpu->set_asi_addrmap(3, &sun4_state::sun4c_segment_map); - m_maincpu->set_asi_addrmap(4, &sun4_state::sun4c_page_map); - m_maincpu->set_asi_addrmap(8, &sun4_state::sun4c_insn_map); - m_maincpu->set_asi_addrmap(9, &sun4_state::sun4c_supervisor_insn_map); - m_maincpu->set_asi_addrmap(10, &sun4_state::sun4c_data_map); - m_maincpu->set_asi_addrmap(11, &sun4_state::sun4c_supervisor_data_map); - m_maincpu->set_asi_addrmap(12, &sun4_state::sun4c_cache_flush_map); - m_maincpu->set_asi_addrmap(13, &sun4_state::sun4c_cache_flush_map); - m_maincpu->set_asi_addrmap(14, &sun4_state::sun4c_cache_flush_map); + m_maincpu->set_addrmap(0, &sun4_state::sun4c_debugger_map); + + SUN4C_MMU(config, m_mmu, 16'670'000, 7, 0x7f); + m_mmu->type1_r().set(m_type1space, FUNC(address_map_bank_device::read32)); + m_mmu->type1_w().set(m_type1space, FUNC(address_map_bank_device::write32)); + m_mmu->set_cpu(m_maincpu); + m_mmu->set_ram(m_ram); + m_mmu->set_rom("user1"); + m_mmu->set_scc(m_scc2); + m_maincpu->set_mmu(m_mmu); RAM(config, RAM_TAG).set_default_size("16M").set_default_value(0x00); @@ -2355,22 +1943,30 @@ MACHINE_CONFIG_START(sun4_state::sun4c) MCFG_SLOT_OPTION_MACHINE_CONFIG("ncr53c90a", [this] (device_t *device) { ncr53c90a(device); }) MACHINE_CONFIG_END -MACHINE_CONFIG_START(sun4_state::sun4_40) +void sun4_state::sun4_40(machine_config &config) +{ sun4c(config); + m_mmu->set_clock(25'000'000); + m_maincpu->set_clock(25'000'000); + m_maincpu->set_mmu(m_mmu); + m_type1space->set_map(&sun4_state::type1space_sbus_map).set_options(ENDIANNESS_BIG, 32, 32, 0x80000000); // SBus - SBUS(config, m_sbus, 16670000, "maincpu", "type1"); - SBUS_SLOT(config, "slot1", 16'670'000, m_sbus, sbus_cards, nullptr); - SBUS_SLOT(config, "slot2", 16'670'000, m_sbus, sbus_cards, nullptr); - SBUS_SLOT(config, "slot3", 16'670'000, m_sbus, sbus_cards, "bwtwo"); -MACHINE_CONFIG_END + SBUS(config, m_sbus, 25'000'000, "maincpu", "type1"); + SBUS_SLOT(config, "slot1", 25'000'000, m_sbus, sbus_cards, nullptr); + SBUS_SLOT(config, "slot2", 25'000'000, m_sbus, sbus_cards, nullptr); + SBUS_SLOT(config, "slot3", 25'000'000, m_sbus, sbus_cards, "bwtwo"); +} -MACHINE_CONFIG_START(sun4_state::sun4_60) +void sun4_state::sun4_60(machine_config &config) +{ sun4c(config); + m_mmu->set_clock(20'000'000); m_maincpu->set_clock(20'000'000); + m_maincpu->set_mmu(m_mmu); m_type1space->set_map(&sun4_state::type1space_sbus_map).set_options(ENDIANNESS_BIG, 32, 32, 0x80000000); @@ -2379,8 +1975,24 @@ MACHINE_CONFIG_START(sun4_state::sun4_60) SBUS_SLOT(config, "slot1", 20'000'000, m_sbus, sbus_cards, nullptr); SBUS_SLOT(config, "slot2", 20'000'000, m_sbus, sbus_cards, nullptr); SBUS_SLOT(config, "slot3", 20'000'000, m_sbus, sbus_cards, nullptr); -MACHINE_CONFIG_END +} +void sun4_state::sun4_75(machine_config &config) +{ + sun4c(config); + + m_mmu->set_clock(40'000'000); + m_maincpu->set_clock(40'000'000); + m_maincpu->set_mmu(m_mmu); + + m_type1space->set_map(&sun4_state::type1space_sbus_map).set_options(ENDIANNESS_BIG, 32, 32, 0x80000000); + + // SBus + SBUS(config, m_sbus, 20'000'000, "maincpu", "type1"); + SBUS_SLOT(config, "slot1", 20'000'000, m_sbus, sbus_cards, nullptr); + SBUS_SLOT(config, "slot2", 20'000'000, m_sbus, sbus_cards, nullptr); + SBUS_SLOT(config, "slot3", 20'000'000, m_sbus, sbus_cards, nullptr); +} /* Boot PROM @@ -2628,15 +2240,11 @@ void sun4_state::init_sun4() void sun4_state::init_sun4c() { - m_ctx_mask = 0x7; - m_pmeg_mask = 0x7f; m_arch = ARCH_SUN4C; } void sun4_state::init_ss2() { - m_ctx_mask = 0xf; - m_pmeg_mask = 0xff; m_arch = ARCH_SUN4C; } @@ -2654,7 +2262,7 @@ COMP( 1991, sun4_50, sun4_300, 0, sun4c, sun4, sun4_state, init_ss2, COMP( 199?, sun4_20, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation SLC (Sun 4/20)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) COMP( 1989, sun4_60, sun4_300, 0, sun4_60, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 1 (Sun 4/60)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) COMP( 1990, sun4_65, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 1+ (Sun 4/65)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) -COMP( 1990, sun4_75, sun4_300, 0, sun4c, sun4, sun4_state, init_ss2, "Sun Microsystems", "SPARCstation 2 (Sun 4/75)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +COMP( 1990, sun4_75, sun4_300, 0, sun4_75, sun4, sun4_state, init_ss2, "Sun Microsystems", "SPARCstation 2 (Sun 4/75)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // sun4m (using the SPARC "reference MMU", probably will go to a separate driver) COMP( 1992, sun_s10, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 10 (Sun S10)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) diff --git a/src/mame/machine/iteagle_fpga.cpp b/src/mame/machine/iteagle_fpga.cpp index 7da81e6900b..7ba6967747f 100644 --- a/src/mame/machine/iteagle_fpga.cpp +++ b/src/mame/machine/iteagle_fpga.cpp @@ -293,19 +293,19 @@ READ32_MEMBER( iteagle_fpga_device::fpga_r ) m_cpu->eat_cycles(40); } if (ACCESSING_BITS_0_7) { - result |= m_scc1->cb_r(space, offset) << 0; + result |= m_scc1->cb_r(offset) << 0; if (LOG_SERIAL) m_serial0_1.read_control(1); } if (ACCESSING_BITS_8_15) { - result |= m_scc1->ca_r(space, offset) << 8; + result |= m_scc1->ca_r(offset) << 8; if (LOG_SERIAL) m_serial0_1.read_control(0); } if (ACCESSING_BITS_16_23) { - result |= m_scc1->db_r(space, offset) <<16; + result |= m_scc1->db_r(offset) <<16; if (LOG_SERIAL) m_serial0_1.read_data(1); } if (ACCESSING_BITS_24_31) { - result |= m_scc1->da_r(space, offset) << 24; + result |= m_scc1->da_r(offset) << 24; if (LOG_SERIAL) m_serial0_1.read_data(0); } if (0 && LOG_FPGA && m_prev_reg != offset) @@ -390,20 +390,20 @@ WRITE32_MEMBER( iteagle_fpga_device::fpga_w ) break; case 0x0c/4: if (ACCESSING_BITS_0_7) { - m_scc1->cb_w(space, offset, (data >> 0) & 0xff); + m_scc1->cb_w(offset, (data >> 0) & 0xff); if (LOG_SERIAL) m_serial0_1.write_control((data >> 0) & 0xff, 1); } if (ACCESSING_BITS_8_15) { - m_scc1->ca_w(space, offset, (data >> 8) & 0xff); + m_scc1->ca_w(offset, (data >> 8) & 0xff); if (LOG_SERIAL) m_serial0_1.write_control((data >> 8) & 0xff, 0); } if (ACCESSING_BITS_16_23) { // Convert 0xd to 0xa uint8_t byte = data >> 16; if (byte==0xd) - m_scc1->db_w(space, offset, 0xa); + m_scc1->db_w(offset, 0xa); else - m_scc1->db_w(space, offset, byte); + m_scc1->db_w(offset, byte); if (LOG_SERIAL) { m_serial0_1.write_data((data >> 16) & 0xff, 1); if (m_serial0_1.get_tx_str(1).back() == 0xd) { @@ -414,7 +414,7 @@ WRITE32_MEMBER( iteagle_fpga_device::fpga_w ) } } if (ACCESSING_BITS_24_31) { - m_scc1->da_w(space, offset, (data >> 24) & 0xff); + m_scc1->da_w(offset, (data >> 24) & 0xff); if (LOG_SERIAL) m_serial0_1.write_data((data >> 24) & 0xff, 0); } if (1 && LOG_FPGA) -- cgit v1.2.3