diff options
author | Ryan Holtz <ryan.holtz@arrowheadgs.com> | 2018-09-21 18:24:28 +0200 |
---|---|---|
committer | Ryan Holtz <ryan.holtz@arrowheadgs.com> | 2018-09-21 18:24:35 +0200 |
commit | 45c4749b25adeefb65331f6b6673c69bad555570 (patch) | |
tree | d019d4cbcdaf0e0d5f9ac27de143f661bf565a49 | |
parent | 99936288c49f1021420935c5136fd031d9b833a0 (diff) |
-sun4, sparc: Optimized the SPARC core and the sun4 driver. [Ryan Holtz]
-rw-r--r-- | src/devices/bus/sbus/bwtwo.cpp | 17 | ||||
-rw-r--r-- | src/devices/cpu/sparc/mb86901.cpp | 1564 | ||||
-rw-r--r-- | src/devices/cpu/sparc/sparc.h | 30 | ||||
-rw-r--r-- | src/devices/cpu/sparc/sparcdefs.h | 9 | ||||
-rw-r--r-- | src/mame/drivers/sun4.cpp | 1148 |
5 files changed, 1772 insertions, 996 deletions
diff --git a/src/devices/bus/sbus/bwtwo.cpp b/src/devices/bus/sbus/bwtwo.cpp index a5e78323aab..ab9fd194a88 100644 --- a/src/devices/bus/sbus/bwtwo.cpp +++ b/src/devices/bus/sbus/bwtwo.cpp @@ -70,14 +70,19 @@ uint32_t sbus_bwtwo_device::screen_update(screen_device &screen, bitmap_rgb32 &b for (int y = 0; y < 900; y++) { uint32_t *scanline = &bitmap.pix32(y); + uint8_t *line = vram + y * (1152/8); for (int x = 0; x < 1152/8; x++) { - const uint8_t pixels = vram[(y * (1152/8)) + (BYTE4_XOR_BE(x))]; - - for (int bit = 7; bit >= 0; bit--) - { - *scanline++ = palette[BIT(pixels, bit)]; - } + 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)]; } } diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp index fad89cf9610..76ef7ac56e4 100644 --- a/src/devices/cpu/sparc/mb86901.cpp +++ b/src/devices/cpu/sparc/mb86901.cpp @@ -41,8 +41,16 @@ 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_program_config("program", ENDIANNESS_BIG, 32, 32) { + 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); + } } @@ -202,7 +210,11 @@ void mb86901_device::device_start() m_alu_op3_assigned[OP3_UDIVCC] = true; m_alu_op3_assigned[OP3_SDIVCC] = true; #endif - m_program = &space(AS_PROGRAM); + 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; @@ -354,7 +366,6 @@ void mb86901_device::device_start() save_item(NAME(m_ps)); save_item(NAME(m_et)); save_item(NAME(m_cwp)); - save_item(NAME(m_asi)); save_item(NAME(m_mae)); save_item(NAME(m_annul)); save_item(NAME(m_hold_bus)); @@ -394,7 +405,6 @@ void mb86901_device::device_reset() m_bp_irl = 0; m_irq_state = 0; - m_asi = 0; MAE = false; HOLD_BUS = false; m_annul = false; @@ -409,6 +419,8 @@ void mb86901_device::device_reset() Y = 0; PSR = PSR_S_MASK | PSR_PS_MASK; + m_s = true; + m_fetch_space = 9; for (int i = 0; i < 8; i++) { @@ -434,9 +446,13 @@ void mb86901_device::device_reset() device_memory_interface::space_config_vector mb86901_device::memory_space_config() const { - return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_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; } @@ -449,18 +465,18 @@ device_memory_interface::space_config_vector mb86901_device::memory_space_config uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size) { - m_asi = asi; + assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. if (size == 1) { - return m_program->read_byte(address) << ((3 - (address & 3)) * 8); + return m_access_cache[asi]->read_byte(address) << ((3 - (address & 3)) * 8); } else if (size == 2) { - return m_program->read_word(address) << ((2 - (address & 2)) * 8); + return m_access_cache[asi]->read_word(address) << ((2 - (address & 2)) * 8); } else { - return m_program->read_dword(address); + return m_access_cache[asi]->read_dword(address); } } @@ -476,18 +492,18 @@ uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size void mb86901_device::write_sized_word(uint8_t asi, uint32_t address, uint32_t data, int size) { - m_asi = asi; + assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. if (size == 1) { - m_program->write_byte(address, data >> ((3 - (address & 3)) * 8)); + m_access_cache[asi]->write_byte(address, data >> ((3 - (address & 3)) * 8)); } else if (size == 2) { - m_program->write_word(address, data >> ((2 - (address & 2)) * 8)); + m_access_cache[asi]->write_word(address, data >> ((2 - (address & 2)) * 8)); } else { - m_program->write_dword(address, data); + m_access_cache[asi]->write_dword(address, data); } } @@ -676,6 +692,9 @@ void mb86901_device::execute_add(uint32_t op) PSR |= ((BIT31(rs1) && BIT31(operand2)) || (!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; } + + PC = nPC; + nPC = nPC + 4; } @@ -724,19 +743,21 @@ void mb86901_device::execute_taddcc(uint32_t op) { m_trap = 1; m_tag_overflow = true; + return; } - else - { - CLEAR_ICC; - PSR |= (BIT31(result)) ? PSR_N_MASK : 0; - PSR |= (result == 0) ? PSR_Z_MASK : 0; - PSR |= temp_v ? PSR_V_MASK : 0; - PSR |= ((BIT31(rs1) && BIT31(operand2)) || - (!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; - if (RD != 0) - RDREG = result; - } + CLEAR_ICC; + PSR |= (BIT31(result)) ? PSR_N_MASK : 0; + PSR |= (result == 0) ? PSR_Z_MASK : 0; + PSR |= temp_v ? PSR_V_MASK : 0; + PSR |= ((BIT31(rs1) && BIT31(operand2)) || + (!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; + + if (RD != 0) + RDREG = result; + + PC = nPC; + nPC = nPC + 4; } @@ -791,6 +812,9 @@ void mb86901_device::execute_sub(uint32_t op) PSR |= ((!BIT31(rs1) && BIT31(operand2)) || (BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; } + + PC = nPC; + nPC = nPC + 4; } @@ -840,19 +864,21 @@ void mb86901_device::execute_tsubcc(uint32_t op) { m_trap = 1; m_tag_overflow = 1; + return; } - else - { - CLEAR_ICC; - PSR |= (BIT31(result)) ? PSR_N_MASK : 0; - PSR |= (result == 0) ? PSR_Z_MASK : 0; - PSR |= temp_v ? PSR_V_MASK : 0; - PSR |= ((!BIT31(rs1) && BIT31(operand2)) || - (BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; - if (RD != 0) - RDREG = result; - } + CLEAR_ICC; + PSR |= (BIT31(result)) ? PSR_N_MASK : 0; + PSR |= (result == 0) ? PSR_Z_MASK : 0; + PSR |= temp_v ? PSR_V_MASK : 0; + PSR |= ((!BIT31(rs1) && BIT31(operand2)) || + (BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; + + if (RD != 0) + RDREG = result; + + PC = nPC; + nPC = nPC + 4; } @@ -925,6 +951,9 @@ void mb86901_device::execute_logical(uint32_t op) PSR |= (BIT31(result)) ? PSR_N_MASK : 0; PSR |= (result == 0) ? PSR_Z_MASK : 0; } + + PC = nPC; + nPC = nPC + 4; } @@ -954,6 +983,9 @@ void mb86901_device::execute_shift(uint32_t op) RDREG = uint32_t(RS1REG) >> shift_count; else if (SRA && RD != 0) RDREG = int32_t(RS1REG) >> shift_count; + + PC = nPC; + nPC = nPC + 4; } @@ -1003,6 +1035,9 @@ void mb86901_device::execute_mulscc(uint32_t op) (!BIT31(operand1) && !BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0; PSR |= ((BIT31(operand1) && BIT31(operand2)) || (!BIT31(result) && (BIT31(operand1) || BIT31(operand2)))) ? PSR_C_MASK : 0; + + PC = nPC; + nPC = nPC + 4; } @@ -1035,13 +1070,16 @@ void mb86901_device::execute_rdsr(uint32_t op) { m_trap = 1; m_privileged_instruction = 1; + return; } else if (m_illegal_instruction_asr[RS1]) { m_trap = 1; m_illegal_instruction = 1; + return; } - else if (RD != 0) + + if (RD != 0) { if (RDASR) { @@ -1059,6 +1097,9 @@ void mb86901_device::execute_rdsr(uint32_t op) else if (RDTBR) RDREG = TBR; } + + PC = nPC; + nPC = nPC + 4; } @@ -1119,6 +1160,8 @@ void mb86901_device::execute_wrsr(uint32_t op) if (WRASR && RD == 0) { Y = result; + PC = nPC; + nPC = nPC + 4; } else if (WRASR) { @@ -1126,15 +1169,19 @@ void mb86901_device::execute_wrsr(uint32_t op) { m_trap = 1; m_privileged_instruction = 1; + return; } else if (m_illegal_instruction_asr[RD]) { m_trap = 1; m_illegal_instruction = 1; + return; } else { // SPARCv8 + PC = nPC; + nPC = nPC + 4; } } else if (WRPSR) @@ -1143,17 +1190,25 @@ void mb86901_device::execute_wrsr(uint32_t op) { m_trap = 1; m_privileged_instruction = 1; + return; } else if ((result & 31) >= NWINDOWS) { m_trap = 1; m_illegal_instruction = 1; + return; } - else - { - PSR = result &~ PSR_ZERO_MASK; - update_gpr_pointers(); - } + + PSR = result &~ PSR_ZERO_MASK; + update_gpr_pointers(); + + 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; + + PC = nPC; + nPC = nPC + 4; } else if (WRWIM) { @@ -1161,11 +1216,12 @@ void mb86901_device::execute_wrsr(uint32_t op) { m_trap = 1; m_privileged_instruction = 1; + return; } - else - { - WIM = result & 0x7f; - } + + WIM = result & 0x7f; + PC = nPC; + nPC = nPC + 4; } else if (WRTBR) { @@ -1173,11 +1229,12 @@ void mb86901_device::execute_wrsr(uint32_t op) { m_trap = 1; m_privileged_instruction = 1; + return; } - else - { - TBR = result & 0xfffff000; - } + + TBR = result & 0xfffff000; + PC = nPC; + nPC = nPC + 4; } } @@ -1227,7 +1284,7 @@ void mb86901_device::execute_rett(uint32_t op) uint8_t new_cwp = ((PSR & PSR_CWP_MASK) + 1) % NWINDOWS; uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - if (PSR & PSR_ET_MASK) + if (m_et) { m_trap = 1; if (IS_USER) @@ -1238,6 +1295,7 @@ void mb86901_device::execute_rett(uint32_t op) { m_illegal_instruction = 1; } + return; } else if (IS_USER) { @@ -1246,6 +1304,7 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 3; m_execute_mode = 0; m_error_mode = 1; + return; } else if ((WIM & (1 << new_cwp)) != 0) { @@ -1254,6 +1313,7 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 6; m_execute_mode = 0; m_error_mode = 1; + return; } else if (address & 3) { @@ -1262,20 +1322,28 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 7; m_execute_mode = 0; m_error_mode = 1; + return; } - else - { - PSR |= PSR_ET_MASK; - PC = nPC; - nPC = address; - PSR &= ~PSR_CWP_MASK; - PSR |= new_cwp; + PSR |= PSR_ET_MASK; + m_et = true; + PC = nPC; + nPC = address; - if (PSR & PSR_PS_MASK) - PSR |= PSR_S_MASK; - else - PSR &= ~PSR_S_MASK; + PSR &= ~PSR_CWP_MASK; + PSR |= new_cwp; + + if (PSR & PSR_PS_MASK) + { + PSR |= PSR_S_MASK; + m_s = true; + m_fetch_space = 9; + } + else + { + PSR &= ~PSR_S_MASK; + m_s = false; + m_fetch_space = 8; } update_gpr_pointers(); @@ -1331,14 +1399,13 @@ void mb86901_device::execute_saverestore(uint32_t op) { m_trap = 1; m_window_overflow = 1; + return; } - else - { - result = rs1 + operand2; - PSR &= ~PSR_CWP_MASK; - PSR |= new_cwp; - BREAK_PSR; - } + + result = rs1 + operand2; + PSR &= ~PSR_CWP_MASK; + PSR |= new_cwp; + //BREAK_PSR; } else if (RESTORE) { @@ -1347,20 +1414,22 @@ void mb86901_device::execute_saverestore(uint32_t op) { m_trap = 1; m_window_underflow = 1; + return; } - else - { - result = rs1 + operand2; - PSR &= ~PSR_CWP_MASK; - PSR |= new_cwp; - BREAK_PSR; - } + + result = rs1 + operand2; + PSR &= ~PSR_CWP_MASK; + PSR |= new_cwp; + //BREAK_PSR; } update_gpr_pointers(); - if (m_trap == 0 && RD != 0) + if (RD != 0) RDREG = result; + + PC = nPC; + nPC = nPC + 4; } @@ -1475,8 +1544,13 @@ void mb86901_device::execute_group2(uint32_t op) case OP3_FPOP1: case OP3_FPOP2: - // Not yet implemented - break; + if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present) + { + //printf("fpop @ %08x: %08x\n", PC, op); + m_trap = 1; + m_fp_disabled = 1; + } + return; case OP3_JMPL: execute_jmpl(op); @@ -1492,6 +1566,8 @@ void mb86901_device::execute_group2(uint32_t op) case OP3_IFLUSH: // Ignored + PC = nPC; + nPC = nPC + 4; break; case OP3_SAVE: @@ -1516,15 +1592,17 @@ void mb86901_device::execute_group2(uint32_t op) case OP3_CPOP1: case OP3_CPOP2: - break; + printf("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); m_trap = 1; m_illegal_instruction = 1; break; - } } } @@ -1676,188 +1754,186 @@ void mb86901_device::execute_store(uint32_t op) { m_trap = 1; m_privileged_instruction = 1; + return; } else if (USEIMM && (STDA || STA || STHA || STBA)) { m_trap = 1; m_illegal_instruction = 1; + return; } uint32_t address = 0; uint8_t addr_space = 0; - if (!m_trap) + if (STD || ST || STH || STB || STF || STDF || STFSR || STDFQ || STCSR || STC || STDC || STDCQ) { - if (STD || ST || STH || STB || STF || STDF || STFSR || STDFQ || STCSR || STC || STDC || STDCQ) - { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); - } - else if (STDA || STA || STHA || STBA) - { - address = RS1REG + RS2REG; - addr_space = ASI; - } - if ((STF || STDF || STFSR || STDFQ) && (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present)) - { - m_trap = 1; - m_fp_disabled = 1; - } - if ((STC || STDC || STCSR || STDCQ) && (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)) - { - m_trap = 1; - m_cp_disabled = 1; - } + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + } + else if (STDA || STA || STHA || STBA) + { + address = RS1REG + RS2REG; + addr_space = ASI; + } + if ((STF || STDF || STFSR || STDFQ) && (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present)) + { + m_trap = 1; + m_fp_disabled = 1; + return; + } + if ((STC || STDC || STCSR || STDCQ) && (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)) + { + m_trap = 1; + m_cp_disabled = 1; + return; } - if (!m_trap) + if ((STH || STHA) && ((address & 1) != 0)) { - if ((STH || STHA) && ((address & 1) != 0)) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - } - else if ((ST || STA || STF || STFSR || STC || STCSR) && ((address & 3) != 0)) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - } - else if ((STD || STDA || STDF || STDFQ || STDC || STDCQ) && ((address & 7) != 0)) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - } - else - { - if (STDFQ) - { - // assume no floating-point queue for now - m_trap = 1; - m_fp_exception = 1; - m_ftt = m_fpu_sequence_err; - } - if (STDCQ) - { - // assume no coprocessor queue for now - m_trap = 1; - m_cp_exception = 1; - // { possibly additional implementation-dependent actions } - } - if (STDF && ((RD & 1) != 0)) - { - m_trap = 1; - m_fp_exception = 1; - m_ftt = 0xff; - } - } + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + else if ((ST || STA || STF || STFSR || STC || STCSR) && ((address & 3) != 0)) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + else if ((STD || STDA || STDF || STDFQ || STDC || STDCQ) && ((address & 7) != 0)) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + if (STDFQ) + { + // assume no floating-point queue for now + m_trap = 1; + m_fp_exception = 1; + m_ftt = m_fpu_sequence_err; + return; + } + if (STDCQ) + { + // assume no coprocessor queue for now + m_trap = 1; + m_cp_exception = 1; + // { possibly additional implementation-dependent actions } + return; + } + if (STDF && ((RD & 1) != 0)) + { + m_trap = 1; + m_fp_exception = 1; + m_ftt = 0xff; + return; } uint32_t data0 = 0; - if (!m_trap) + //uint8_t byte_mask; + if (STF) { - //uint8_t byte_mask; - if (STF) - { - //byte_mask = 15; - data0 = FREG(RD); - } - else if (STC) - { - //byte_mask = 15; - data0 = 0; - } - else if (STDF) - { - //byte_mask = 15; - data0 = FREG(RD & 0x1e); - } - else if (STDC) - { - //byte_mask = 15; - data0 = 0; - } - else if (STD || STDA) + //byte_mask = 15; + data0 = FREG(RD); + } + else if (STC) + { + //byte_mask = 15; + data0 = 0; + } + else if (STDF) + { + //byte_mask = 15; + data0 = FREG(RD & 0x1e); + } + else if (STDC) + { + //byte_mask = 15; + data0 = 0; + } + else if (STD || STDA) + { + //byte_mask = 15; + data0 = REG(RD & 0x1e); + } + else if (STDFQ) + { + //byte_mask = 15; + data0 = 0; + } + else if (STDCQ) + { + //byte_mask = 15; + data0 = 0; + } + else if (STFSR) + { + // while ((FSR.qne = 1) and (trap = 0)) ( + // wait for pending floating-point instructions to complete + // ) + // next; + //byte_mask = 15; + data0 = FSR; + } + else if (STCSR) + { + // { implementation-dependent actions } + //byte_mask = 15; + data0 = 0; + } + else if (ST || STA) + { + //byte_mask = 15; + data0 = REG(RD); + } + else if (STH || STHA) + { + if ((address & 3) == 0) { - //byte_mask = 15; - data0 = REG(RD & 0x1e); + //byte_mask = 12; + data0 = REG(RD) << 16; } - else if (STDFQ) + else if ((address & 3) == 2) { - //byte_mask = 15; - data0 = 0; + //byte_mask = 3; + data0 = REG(RD); } - else if (STDCQ) + } + else if (STB || STBA) + { + if ((address & 3) == 0) { - //byte_mask = 15; - data0 = 0; + //byte_mask = 8; + data0 = REG(RD) << 24; } - else if (STFSR) + else if ((address & 3) == 1) { - // while ((FSR.qne = 1) and (trap = 0)) ( - // wait for pending floating-point instructions to complete - // ) - // next; - //byte_mask = 15; - data0 = FSR; + //byte_mask = 4; + data0 = REG(RD) << 16; } - else if (STCSR) + else if ((address & 3) == 2) { - // { implementation-dependent actions } - //byte_mask = 15; - data0 = 0; + //byte_mask = 2; + data0 = REG(RD) << 8; } - else if (ST || STA) + else if ((address & 3) == 3) { - //byte_mask = 15; + //byte_mask = 1; data0 = REG(RD); } - else if (STH || STHA) - { - if ((address & 3) == 0) - { - //byte_mask = 12; - data0 = REG(RD) << 16; - } - else if ((address & 3) == 2) - { - //byte_mask = 3; - data0 = REG(RD); - } - } - else if (STB || STBA) - { - if ((address & 3) == 0) - { - //byte_mask = 8; - data0 = REG(RD) << 24; - } - else if ((address & 3) == 1) - { - //byte_mask = 4; - data0 = REG(RD) << 16; - } - else if ((address & 3) == 2) - { - //byte_mask = 2; - data0 = REG(RD) << 8; - } - else if ((address & 3) == 3) - { - //byte_mask = 1; - data0 = REG(RD); - } - } } - if (!m_trap) + write_sized_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 4 : ((STH || STHA) ? 2 : 1)); + if (MAE) { - write_sized_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 4 : ((STH || STHA) ? 2 : 1)); - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - } + m_trap = 1; + m_data_access_exception = 1; + return; } - if (!m_trap && (STD || STDA || STDF || STDC || STDFQ || STDCQ)) + + if (STD || STDA || STDF || STDC || STDFQ || STDCQ) { uint32_t data1 = 0; if (STD || STDA) @@ -1886,8 +1962,12 @@ void mb86901_device::execute_store(uint32_t op) { m_trap = 1; m_data_access_exception = 1; + return; } } + + PC = nPC; + nPC = nPC + 4; } //------------------------------------------------- @@ -1998,140 +2078,688 @@ void mb86901_device::execute_load(uint32_t op) uint32_t address = 0; uint8_t addr_space = 0; - if (LDD || LD || LDSH || LDUH || LDSB || LDUB || LDDF || LDF || LDFSR || LDDC || LDC || LDCSR) - { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); - } - else if (LDDA || LDA || LDSHA || LDUHA || LDSBA || LDUBA) + switch (OP3) { - if (IS_USER) + case OP3_LDD: { - m_trap = 1; - m_privileged_instruction = 1; + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + if (address & 7) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + } + + const uint32_t data = read_sized_word(addr_space, address, 4); + + if (MAE) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + RDREG = data; + + const uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + if (MAE) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + REG(RD | 1) = word1; + break; } - else if (USEIMM) + case OP3_LD: { - m_trap = 1; - m_illegal_instruction = 1; + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + if (address & 3) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + const uint32_t data = read_sized_word(addr_space, address, 4); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + RDREG = data; + break; } - else + case OP3_LDSH: { - address = RS1REG + RS2REG; - addr_space = ASI; + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + if (address & 1) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + const uint32_t data = read_sized_word(addr_space, address, 2); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + { + if ((address & 3) == 0) RDREG = (int32_t)data >> 16; + else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 16; + } + break; } - } + case OP3_LDUH: + { + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); - if (!m_trap) - { - if ((LDF || LDDF || LDFSR) && (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0)) + if (address & 1) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + const uint32_t data = read_sized_word(addr_space, address, 2); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + { + if ((address & 3) == 0) RDREG = data >> 16; + else if ((address & 3) == 2) RDREG = data & 0xffff; + } + break; + } + case OP3_LDSB: { - m_trap = 1; - m_fp_disabled = 1; + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + const uint32_t data = read_sized_word(addr_space, address, 1); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + { + if ((address & 3) == 0) RDREG = (int32_t)data >> 24; + else if ((address & 3) == 1) RDREG = ((int32_t)data << 8) >> 24; + else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 24; + else if ((address & 3) == 3) RDREG = ((int32_t)data << 24) >> 24; + } + break; } - else if ((LDC || LDDC || LDCSR) && (!(PSR & PSR_EC_MASK) || m_bp_cp_present == 0)) + case OP3_LDUB: { - m_trap = 1; - m_cp_disabled = 1; + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + const uint32_t data = read_sized_word(addr_space, address, 1); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + { + if ((address & 3) == 0) RDREG = data >> 24; + else if ((address & 3) == 1) RDREG = (data >> 16) & 0xff; + else if ((address & 3) == 2) RDREG = (data >> 8) & 0xff; + else if ((address & 3) == 3) RDREG = data & 0xff; + } + break; } - else if (((LDD || LDDA || LDDF || LDDC) && ((address & 7) != 0)) || - ((LD || LDA || LDF || LDFSR || LDC || LDCSR) && ((address & 3) != 0)) || - ((LDSH || LDSHA || LDUH || LDUHA) && ((address & 1) != 0))) + case OP3_LDDFPR: { - m_trap = 1; - m_mem_address_not_aligned = 1; + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) + { + m_trap = 1; + m_fp_disabled = 1; + return; + } + + if (address & 7) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + if (RD & 1) + { + m_trap = 1; + m_fp_exception = 1; + m_ftt = 0xff; + return; + } + + if (m_fpu_sequence_err) + { + m_trap = 1; + m_fp_exception = 1; + m_ftt = m_fpu_sequence_err; + return; + } + + const uint32_t data = read_sized_word(addr_space, address, 4); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + FREG(RD & 0x1e) = data; + + const uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + if (MAE) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + FREG(RD | 1) = word1; + break; } - else if (LDDF && ((RD & 1) != 0)) + case OP3_LDFPR: { - m_trap = 1; - m_fp_exception = 1; - m_ftt = 0xff; + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) + { + m_trap = 1; + m_fp_disabled = 1; + return; + } + + if (address & 3) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + if (m_fpu_sequence_err) + { + m_trap = 1; + m_fp_exception = 1; + m_ftt = m_fpu_sequence_err; + return; + } + + const uint32_t data = read_sized_word(addr_space, address, 4); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + FDREG = data; + break; } - else if ((LDF || LDDF || LDFSR) && m_fpu_sequence_err != 0) + case OP3_LDFSR: { - m_trap = 1; - m_fp_exception = 1; - m_ftt = m_fpu_sequence_err; + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) + { + m_trap = 1; + m_fp_disabled = 1; + return; + } + + if (address & 3) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + if (m_fpu_sequence_err) + { + m_trap = 1; + m_fp_exception = 1; + m_ftt = m_fpu_sequence_err; + return; + } + + const uint32_t data = read_sized_word(addr_space, address, 4); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + FSR = data; + break; } - else if ((LDC || LDDC || LDCSR) && m_cp_sequence_err != 0) + case OP3_LDDCPR: { - m_trap = 1; - m_cp_exception = 1; - // possibly additional implementation-dependent actions + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) + { + m_trap = 1; + m_cp_disabled = 1; + return; + } + + if (address & 7) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + if (m_cp_sequence_err) + { + m_trap = 1; + m_cp_exception = 1; + // possibly additional implementation-dependent actions + return; + } + + read_sized_word(addr_space, address, 4); + if (MAE) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + // implementation-dependent actions + + read_sized_word(addr_space, address + 4, 4); + if (MAE) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + // implementation-dependent actions + break; } - } + case OP3_LDCPR: + { + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); - uint32_t word0(0); - if (!m_trap) - { - uint32_t data = read_sized_word(addr_space, address, (LD || LDD || LDA || LDDA) ? 4 : ((LDUH || LDSH || LDUHA || LDSHA) ? 2 : 1)); + if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) + { + m_trap = 1; + m_cp_disabled = 1; + return; + } + + if (address & 3) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + if (m_cp_sequence_err) + { + m_trap = 1; + m_cp_exception = 1; + // possibly additional implementation-dependent actions + return; + } - if (m_mae) + read_sized_word(addr_space, address, 4); + + if (MAE) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + // implementation-dependent actions + break; + } + case OP3_LDCSR: { - m_trap = 1; - m_data_access_exception = 1; + address = RS1REG + (USEIMM ? SIMM13 : RS2REG); + addr_space = (IS_USER ? 10 : 11); + + if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) + { + m_trap = 1; + m_cp_disabled = 1; + return; + } + + if (address & 3) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + if (m_cp_sequence_err) + { + m_trap = 1; + m_cp_exception = 1; + // possibly additional implementation-dependent actions + return; + } + + read_sized_word(addr_space, address, 4); + + if (MAE) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + // implementation-dependent actions + break; } - else + case OP3_LDDA: { - if (LDSB || LDSBA || LDUB || LDUBA) + if (IS_USER) + { + m_trap = 1; + m_privileged_instruction = 1; + return; + } + else if (USEIMM) { - uint8_t byte = 0; - if ((address & 3) == 0) byte = (data >> 24) & 0xff; - else if ((address & 3) == 1) byte = (data >> 16) & 0xff; - else if ((address & 3) == 2) byte = (data >> 8) & 0xff; - else if ((address & 3) == 3) byte = data & 0xff; + m_trap = 1; + m_illegal_instruction = 1; + return; + } + else + { + address = RS1REG + RS2REG; + addr_space = ASI; + } + + if (address & 7) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } - if (LDSB || LDSBA) - word0 = (((int32_t)byte) << 24) >> 24; - else - word0 = byte; + const uint32_t data = read_sized_word(addr_space, address, 4); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; } - else if (LDSH || LDSHA || LDUH || LDUHA) + + if (RD != 0) + RDREG = data; + + uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + if (MAE) { - uint16_t halfword = 0; - if ((address & 3) == 0) halfword = (data >> 16) & 0xffff; - else if ((address & 3) == 2) halfword = data & 0xffff; + m_trap = 1; + m_data_access_exception = 1; + return; + } - if (LDSH || LDSHA) - { - word0 = (((int32_t)halfword) << 16) >> 16; - } - else - { - word0 = halfword; - } + REG(RD | 1) = word1; + break; + } + case OP3_LDA: + { + if (IS_USER) + { + m_trap = 1; + m_privileged_instruction = 1; + return; + } + else if (USEIMM) + { + m_trap = 1; + m_illegal_instruction = 1; + return; } else { - word0 = data; + address = RS1REG + RS2REG; + addr_space = ASI; } + + if (address & 3) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + const uint32_t data = read_sized_word(addr_space, address, 4); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + RDREG = data; + break; } - } + case OP3_LDSHA: + { + if (IS_USER) + { + m_trap = 1; + m_privileged_instruction = 1; + return; + } + else if (USEIMM) + { + m_trap = 1; + m_illegal_instruction = 1; + return; + } + else + { + address = RS1REG + RS2REG; + addr_space = ASI; + } - if (!m_trap) - { - if (RD == 0) { } - else if (LD || LDA || LDSH || LDSHA || LDUHA || LDUH || LDSB || LDSBA || LDUB || LDUBA) RDREG = word0; - else if (LDF) FDREG = word0; - else if (LDC) { } // implementation-dependent actions - else if (LDFSR) FSR = word0; - else if (LDD || LDDA) REG(RD & 0x1e) = word0; - else if (LDDF) FREG(RD & 0x1e) = word0; - else if (LDDC) { } // implementation-dependent actions - } + if (address & 1) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } - if (!m_trap && (LDD || LDDA || LDDF || LDDC)) - { - uint32_t word1 = read_sized_word(addr_space, address + 4, 4); - if (MAE) + const uint32_t data = read_sized_word(addr_space, address, 2); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + { + if ((address & 3) == 0) RDREG = (int32_t)data >> 16; + else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 16; + } + break; + } + case OP3_LDUHA: { - m_trap = 1; - m_data_access_exception = 1; + if (IS_USER) + { + m_trap = 1; + m_privileged_instruction = 1; + return; + } + else if (USEIMM) + { + m_trap = 1; + m_illegal_instruction = 1; + return; + } + else + { + address = RS1REG + RS2REG; + addr_space = ASI; + } + + if (address & 1) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + return; + } + + const uint32_t data = read_sized_word(addr_space, address, 2); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + { + if ((address & 3) == 0) RDREG = data >> 16; + else if ((address & 3) == 2) RDREG = data & 0xffff; + } + break; + } + case OP3_LDSBA: + { + if (IS_USER) + { + m_trap = 1; + m_privileged_instruction = 1; + return; + } + else if (USEIMM) + { + m_trap = 1; + m_illegal_instruction = 1; + return; + } + else + { + address = RS1REG + RS2REG; + addr_space = ASI; + } + + const uint32_t data = read_sized_word(addr_space, address, 1); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + { + if ((address & 3) == 0) RDREG = (int32_t)data >> 24; + else if ((address & 3) == 1) RDREG = ((int32_t)data << 8) >> 24; + else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 24; + else if ((address & 3) == 3) RDREG = ((int32_t)data << 24) >> 24; + } + break; + } + case OP3_LDUBA: + { + if (IS_USER) + { + m_trap = 1; + m_privileged_instruction = 1; + return; + } + else if (USEIMM) + { + m_trap = 1; + m_illegal_instruction = 1; + return; + } + else + { + address = RS1REG + RS2REG; + addr_space = ASI; + } + + const uint32_t data = read_sized_word(addr_space, address, 1); + + if (m_mae) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + if (RD != 0) + { + if ((address & 3) == 0) RDREG = data >> 24; + else if ((address & 3) == 1) RDREG = (data >> 16) & 0xff; + else if ((address & 3) == 2) RDREG = (data >> 8) & 0xff; + else if ((address & 3) == 3) RDREG = data & 0xff; + } + break; } - else if (LDD || LDDA) REG(RD | 1) = word1; - else if (LDDF) FREG(RD | 1) = word1; - else if (LDDC) { } // implementation-dependent actions + default: + break; } + + PC = nPC; + nPC = nPC + 4; } @@ -2214,91 +2842,91 @@ void mb86901_device::execute_ldstub(uint32_t op) { m_trap = 1; m_privileged_instruction = 1; + return; } else if (USEIMM) { m_trap = 1; m_illegal_instruction = 1; + return; } else { address = RS1REG + RS2REG; addr_space = ASI; + return; } } uint32_t data(0); - if (!m_trap) + while (m_pb_block_ldst_byte || m_pb_block_ldst_word) { - while (m_pb_block_ldst_byte || m_pb_block_ldst_word) - { - // { wait for lock(s) to be lifted } - // { an implementation actually need only block when another LDSTUB or SWAP - // is pending on the same byte in memory as the one addressed by this LDSTUB } - } + // { wait for lock(s) to be lifted } + // { an implementation actually need only block when another LDSTUB or SWAP + // is pending on the same byte in memory as the one addressed by this LDSTUB } + } - m_pb_block_ldst_byte = 1; + m_pb_block_ldst_byte = 1; - data = read_sized_word(addr_space, address, 1); + data = read_sized_word(addr_space, address, 1); - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - } + if (MAE) + { + m_trap = 1; + m_data_access_exception = 1; + return; } - if (!m_trap) + //uint8_t byte_mask; + if ((address & 3) == 0) { - //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); + //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_pb_block_ldst_byte = 0; + m_pb_block_ldst_byte = 0; - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - } - else - { - uint32_t word; - if ((address & 3) == 0) - { - word = (data >> 24) & 0xff; - } - else if ((address & 3) == 1) - { - word = (data >> 16) & 0xff; - } - else if ((address & 3) == 2) - { - word = (data >> 8) & 0xff; - } - else // if ((address & 3) == 3) - { - word = data & 0xff; - } - if (RD != 0) - RDREG = word; - } + if (MAE) + { + m_trap = 1; + m_data_access_exception = 1; + return; + } + + uint32_t word; + if ((address & 3) == 0) + { + word = (data >> 24) & 0xff; + } + else if ((address & 3) == 1) + { + word = (data >> 16) & 0xff; + } + else if ((address & 3) == 2) + { + word = (data >> 8) & 0xff; + } + else // if ((address & 3) == 3) + { + word = data & 0xff; } + if (RD != 0) + RDREG = word; + + PC = nPC; + nPC = nPC + 4; } @@ -2373,6 +3001,12 @@ void mb86901_device::execute_group3(uint32_t op) execute_swap(op); break; #endif + + default: + printf("illegal instruction at %08x: %08x\n", PC, op); + m_trap = 1; + m_illegal_instruction = 1; + break; } if (MAE || HOLD_BUS) @@ -2548,7 +3182,7 @@ void mb86901_device::select_trap() m_trap = 0; return; } - else if (!(PSR & PSR_ET_MASK)) + else if (!m_et) { m_execute_mode = 0; m_error_mode = 1; @@ -2712,6 +3346,7 @@ void mb86901_device::execute_trap() if (!m_error_mode) { PSR &= ~PSR_ET_MASK; + m_et = false; if (IS_USER) PSR &= ~PSR_PS_MASK; @@ -2719,6 +3354,8 @@ void mb86901_device::execute_trap() PSR |= PSR_PS_MASK; PSR |= PSR_S_MASK; + m_s = true; + m_fetch_space = 9; int cwp = PSR & PSR_CWP_MASK; int new_cwp = ((cwp + NWINDOWS) - 1) % NWINDOWS; @@ -2756,17 +3393,41 @@ void mb86901_device::execute_trap() //------------------------------------------------- -// complete_instruction_execution - execute a -// single fetched instruction that has been -// checked for FP-disabled, CP-disabled, and -// validity. +// dispatch_instruction - executes a +// single fetched instruction. //------------------------------------------------- -void mb86901_device::complete_instruction_execution(uint32_t op) +/* The SPARC Instruction Manual: Version 8, page 159, "Appendix C - ISP Descriptions - C.6. Instruction Dispatch" (SPARCv8.pdf, pg. 156) + +illegal_IU_instr :- ( + if ( ( (op == 00) and (op2 == 000) ) { UNIMP instruction } + or + ( ((op=11) or (op=10)) and (op3=unassigned) ) + then 1 else 0 + +if (illegal_IU_instr = 1) then ( + trap <- 1 + illegal_instruction <- 1 +); +if ((FPop1 or FPop2 or FBfcc) and ((EF = 0) or (bp_FPU_present = 0))) then ( + trap <- 1; + fp_disabled <- 1 +); +if (CPop1 or CPop2 or CBccc) and ((EC = 0) or (bp_CP_present = 0))) then ( + trap <- 1; + cp_disabled <- 1 +); +next; +if (trap = 0) then ( + { code for specific instruction, defined below } +); +*/ + +inline void mb86901_device::dispatch_instruction(uint32_t op) { - switch (OP) + switch (OP_NS) { - case OP_TYPE0: // Bicc, SETHI, FBfcc + case OP_TYPE0_NS: // Bicc, SETHI, FBfcc switch (OP2) { case OP2_UNIMP: // unimp @@ -2776,22 +3437,41 @@ void mb86901_device::complete_instruction_execution(uint32_t op) execute_bicc(op); break; case OP2_SETHI: // sethi - SET_RDREG(IMM22); + //SET_RDREG(IMM22); + *m_regs[RD] = op << 10; + m_r[0] = 0; + PC = nPC; + nPC = nPC + 4; break; case OP2_FBFCC: // branch on floating-point condition codes - printf("fbfcc @ %x\n", PC); + if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present) + { + //printf("fbfcc at %08x: %08x\n", PC, op); + m_trap = 1; + m_fp_disabled = 1; + return; + } break; #if SPARCV8 case OP2_CBCCC: // branch on coprocessor condition codes, SPARCv8 - break; + if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) + { + printf("cbccc @ %08x: %08x\n", PC, op); + m_trap = 1; + m_cp_disabled = 1; + return; + } + return; #endif default: - printf("unknown %08x @ %x\n", op, PC); - break; + printf("illegal instruction at %08x: %08x\n", PC, op); + m_trap = 1; + m_illegal_instruction = 1; + return; } break; - case OP_CALL: // call + case OP_CALL_NS: // call { uint32_t pc = PC; uint32_t callpc = PC + DISP30; @@ -2802,77 +3482,16 @@ void mb86901_device::complete_instruction_execution(uint32_t op) break; } - case OP_ALU: + case OP_ALU_NS: execute_group2(op); break; - case OP_LDST: + case OP_LDST_NS: execute_group3(op); break; - default: - break; } } - -//------------------------------------------------- -// dispatch_instruction - dispatch the previously -// fetched instruction -//------------------------------------------------- - -void mb86901_device::dispatch_instruction(uint32_t op) -{ - /* The SPARC Instruction Manual: Version 8, page 159, "Appendix C - ISP Descriptions - C.6. Instruction Dispatch" (SPARCv8.pdf, pg. 156) - - illegal_IU_instr :- ( - if ( ( (op == 00) and (op2 == 000) ) { UNIMP instruction } - or - ( ((op=11) or (op=10)) and (op3=unassigned) ) - then 1 else 0 - - if (illegal_IU_instr = 1) then ( - trap <- 1 - illegal_instruction <- 1 - ); - if ((FPop1 or FPop2 or FBfcc) and ((EF = 0) or (bp_FPU_present = 0))) then ( - trap <- 1; - fp_disabled <- 1 - ); - if (CPop1 or CPop2 or CBccc) and ((EC = 0) or (bp_CP_present = 0))) then ( - trap <- 1; - cp_disabled <- 1 - ); - next; - if (trap = 0) then ( - { code for specific instruction, defined below } - ); - */ - bool illegal_IU_instr = (OP == 0 && OP2 == 0) || ((OP == 3 && !m_ldst_op3_assigned[OP3]) || (OP == 2 && !m_alu_op3_assigned[OP3])); - - if (illegal_IU_instr) - { - printf("illegal instruction at %08x: %08x\n", PC, op); - m_trap = 1; - m_illegal_instruction = 1; - } - if (((OP == OP_ALU && (FPOP1 || FPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_FBFCC)) && (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present)) - { - m_trap = 1; - m_fp_disabled = 1; - } - if (((OP == OP_ALU && (CPOP1 || CPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_CBCCC)) && (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)) - { - m_trap = 1; - m_cp_disabled = 1; - } - - if (!m_trap) - { - complete_instruction_execution(op); - } -} - - //------------------------------------------------- // complete_fp_execution - completes execution // of a floating-point operation @@ -2949,7 +3568,7 @@ void mb86901_device::execute_step() //printf("Entering reset mode\n"); return; } - else if ((PSR & PSR_ET_MASK) && (m_bp_irl == 15 || m_bp_irl > ((PSR & PSR_PIL_MASK) >> PSR_PIL_SHIFT))) + else if (m_et && (m_bp_irl == 15 || m_bp_irl > m_pil)) { m_trap = 1; m_interrupt_level = m_bp_irl; @@ -2958,7 +3577,7 @@ void mb86901_device::execute_step() if (m_trap) { execute_trap(); - BREAK_PSR; + //BREAK_PSR; debugger_instruction_hook(PC); } @@ -2966,8 +3585,7 @@ void mb86901_device::execute_step() { // write-state-register delay not yet implemented - uint32_t addr_space = (IS_USER ? 8 : 9); - uint32_t op = read_sized_word(addr_space, PC, 4); + const uint32_t op = read_sized_word(m_fetch_space, PC, 4); #if LOG_FCODES //if (m_log_fcodes) @@ -2992,11 +3610,11 @@ void mb86901_device::execute_step() 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; - } + //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 { @@ -3081,7 +3699,7 @@ void mb86901_device::execute_run() continue; } - BREAK_PSR; + //BREAK_PSR; debugger_instruction_hook(PC); if (m_reset_mode) diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h index 9c97b86bdef..41264b6ed2b 100644 --- a/src/devices/cpu/sparc/sparc.h +++ b/src/devices/cpu/sparc/sparc.h @@ -27,6 +27,19 @@ class mb86901_device : public cpu_device, 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 <typename T> void set_asi_addrmap(int asi, T &&obj) + { + set_addrmap(asi + AS_START, std::forward<T>(obj)); + } + // device-level overrides virtual void device_start() override; virtual void device_reset() override; @@ -48,7 +61,7 @@ public: // device_state_interface overrides virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - uint8_t get_asi() { return m_asi; } + uint8_t get_asi() { return 0; } uint32_t pc() { return m_pc; } void set_mae() { m_mae = 1; } @@ -96,7 +109,7 @@ protected: void execute_trap(); void complete_instruction_execution(uint32_t op); - void dispatch_instruction(uint32_t op); + inline void dispatch_instruction(uint32_t op); void complete_fp_execution(uint32_t /*op*/); void execute_step(); @@ -110,7 +123,10 @@ protected: #endif // address spaces - const address_space_config m_program_config; + 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); @@ -197,9 +213,6 @@ protected: // register windowing helpers uint32_t* m_regs[32]; - // addressing helpers - uint8_t m_asi; - // other internal states bool m_privileged_asr[32]; bool m_illegal_instruction_asr[32]; @@ -207,12 +220,13 @@ protected: bool m_annul; bool m_hold_bus; int m_icount; + int m_fetch_space; // debugger helpers uint32_t m_dbgregs[24]; // address spaces - address_space *m_program; + address_space *m_space[32]; #if LOG_FCODES uint32_t m_ss1_next_pc; @@ -288,4 +302,4 @@ enum SPARC_RESET }; -#endif // MAME_CPU_SPARC_SPARC_H +#endif // MAME_CPU_SPARC_SPARC_H
\ No newline at end of file diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h index b3ebb95d589..952702022eb 100644 --- a/src/devices/cpu/sparc/sparcdefs.h +++ b/src/devices/cpu/sparc/sparcdefs.h @@ -81,7 +81,9 @@ #define WIM m_wim #define TBR m_tbr -#define OP (op >> 30) // gangnam style +#define OP_NS (op & 0xc0000000) + +#define OP (op >> 30) #define OP2 ((op >> 22) & 7) #define OP3 ((op >> 19) & 63) #define OPF ((op >> 5) & 0x1ff) @@ -153,6 +155,11 @@ #define OP_ALU 2 #define OP_LDST 3 +#define OP_TYPE0_NS (OP_TYPE0 << 30) +#define OP_CALL_NS (OP_CALL << 30) +#define OP_ALU_NS (OP_ALU << 30) +#define OP_LDST_NS (OP_LDST << 30) + #define OP2_UNIMP 0 #define OP2_BICC 2 #define OP2_SETHI 4 diff --git a/src/mame/drivers/sun4.cpp b/src/mame/drivers/sun4.cpp index 2be69f71d95..45666d9e4ad 100644 --- a/src/mame/drivers/sun4.cpp +++ b/src/mame/drivers/sun4.cpp @@ -583,6 +583,36 @@ private: static const device_timer_id TIMER_1 = 1; static const device_timer_id TIMER_RESET = 2; + enum insn_data_mode + { + USER_INSN, + SUPER_INSN, + USER_DATA, + SUPER_DATA + }; + + DECLARE_READ32_MEMBER( sun4_cache_flush_r ); + DECLARE_WRITE32_MEMBER( sun4_cache_flush_w ); + DECLARE_READ32_MEMBER( sun4_system_r ); + DECLARE_WRITE32_MEMBER( sun4_system_w ); + DECLARE_READ32_MEMBER( sun4_segment_map_r ); + DECLARE_WRITE32_MEMBER( sun4_segment_map_w ); + DECLARE_READ32_MEMBER( sun4_page_map_r ); + DECLARE_WRITE32_MEMBER( sun4_page_map_w ); + template <insn_data_mode MODE> 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 <insn_data_mode MODE> DECLARE_READ32_MEMBER( sun4c_insn_data_r ); + template <insn_data_mode MODE> DECLARE_WRITE32_MEMBER( sun4c_insn_data_w ); + DECLARE_READ32_MEMBER( sun4_mmu_r ); DECLARE_WRITE32_MEMBER( sun4_mmu_w ); DECLARE_READ32_MEMBER( sun4c_mmu_r ); @@ -618,8 +648,23 @@ private: void ncr53c90a(device_t *device); - void sun4_mem(address_map &map); - void sun4c_mem(address_map &map); + void sun4_system_map(address_map &map); + void sun4_segment_map(address_map &map); + void sun4_page_map(address_map &map); + void sun4_insn_map(address_map &map); + void sun4_supervisor_insn_map(address_map &map); + 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 type0space_map(address_map &map); void type1space_map(address_map &map); void type1space_sbus_map(address_map &map); @@ -647,12 +692,15 @@ private: optional_device<sbus_device> m_sbus; optional_device<address_map_bank_device> m_type0space; optional_device<address_map_bank_device> m_type1space; + memory_access_cache<2, 0, ENDIANNESS_BIG> *m_type1_cache; required_device<ram_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]; @@ -663,9 +711,46 @@ private: int m_scsi_irq; int m_fdc_irq; + 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]; + + template <sun4_arch ARCH_4C> + uint32_t to_uint() + { + return valid | writable | supervisor | uncached | (type << 26) | accessed | modified | (ARCH_4C ? (page >> 10) : (page >> 11)); + } + + template <sun4_arch ARCH_4C> + void merge_uint(uint32_t data, uint32_t mem_mask) + { + const uint32_t new_value = (to_uint<ARCH_4C>() & ~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 = ARCH_4C ? ((new_value & 0xffff) << 10) : ((new_value & 0x7ffff) << 11); + } + }; + uint32_t *m_ram_ptr; uint8_t m_segmap[16][4096]; - uint32_t m_pagemap[16384]; + 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_ram_size; @@ -680,11 +765,6 @@ private: emu_timer *m_c0_timer, *m_c1_timer; emu_timer *m_reset_timer; - uint32_t read_insn_data(uint8_t asi, address_space &space, uint32_t offset, uint32_t mem_mask); - void write_insn_data(uint8_t asi, address_space &space, uint32_t offset, uint32_t data, uint32_t mem_mask); - uint32_t read_insn_data_4c(uint8_t asi, address_space &space, uint32_t offset, uint32_t mem_mask); - void write_insn_data_4c(uint8_t asi, address_space &space, uint32_t offset, uint32_t data, uint32_t mem_mask); - void dma_check_interrupts(); void dma_transfer(); void dma_transfer_write(); @@ -696,25 +776,226 @@ private: void fcodes_command(int ref, const std::vector<std::string> ¶ms); }; -uint32_t sun4_state::read_insn_data_4c(uint8_t asi, address_space &space, uint32_t offset, uint32_t mem_mask) +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<SUPER_INSN>), this) + , write32_delegate(FUNC(sun4_state::sun4c_insn_data_w<SUPER_INSN>), this)); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x00000000, 0xffffffff, 0, 0, 0 + , read32_delegate(FUNC(sun4_state::sun4c_insn_data_r<SUPER_INSN>), this) + , write32_delegate(FUNC(sun4_state::sun4c_insn_data_w<SUPER_INSN>), 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<SUN4C>(); +} + +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<SUN4C>(data, mem_mask); + m_page_valid[page] = m_pagemap[page].valid; +} + +template <sun4_state::insn_data_mode MODE> +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 - uint8_t pmeg = m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask; - uint32_t entry = (pmeg << 6) + ((offset >> 10) & 0x3f); + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; + const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); - if (m_pagemap[entry] & PM_VALID) + if (m_page_valid[entry_index]) { - m_pagemap[entry] |= PM_ACCESSED; + page_entry_t &entry = m_pagemap[entry_index]; + entry.accessed = PM_ACCESSED; - uint32_t tmp = (m_pagemap[entry] & 0xffff) << 10; - tmp |= (offset & 0x3ff); + 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, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], 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<SUN4C>(), m_maincpu->pc()); - switch ((m_pagemap[entry] >> 26) & 3) + switch (entry.type) { case 0: // type 0 space - return m_type0space->read32(space, tmp, mem_mask); + //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 @@ -737,7 +1018,7 @@ uint32_t sun4_state::read_insn_data_4c(uint8_t asi, address_space &space, uint32 { if (!machine().side_effects_disabled()) { - logerror("sun4c: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry, m_pagemap[entry], offset <<2, m_maincpu->pc()); + logerror("sun4c: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint<SUN4C>(), offset <<2, m_maincpu->pc()); m_maincpu->set_mae(); m_buserr[0] |= 0x80; // invalid PTE m_buserr[0] &= ~0x8000; // read @@ -762,15 +1043,17 @@ uint32_t sun4_state::read_insn_data_4c(uint8_t asi, address_space &space, uint32 } } -void sun4_state::write_insn_data_4c(uint8_t asi, address_space &space, uint32_t offset, uint32_t data, uint32_t mem_mask) +template <sun4_state::insn_data_mode MODE> +WRITE32_MEMBER( sun4_state::sun4c_insn_data_w ) { // it's translation time - uint8_t pmeg = m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask; - uint32_t entry = (pmeg << 6) + ((offset >> 10) & 0x3f); + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; + const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f); - if (m_pagemap[entry] & PM_VALID) + if (m_page_valid[entry_index]) { - if ((!(m_pagemap[entry] & PM_WRITEMASK)) || ((m_pagemap[entry] & PM_SYSMASK) && !(asi & 1))) + 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 @@ -779,23 +1062,32 @@ void sun4_state::write_insn_data_4c(uint8_t asi, address_space &space, uint32_t return; } - m_pagemap[entry] |= (PM_ACCESSED | PM_MODIFIED); + entry.accessed = PM_ACCESSED; + entry.modified = PM_MODIFIED; - uint32_t tmp = (m_pagemap[entry] & 0xffff) << 10; - tmp |= (offset & 0x3ff); + 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, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], asi, m_maincpu->pc()); + //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<ARCH_4C>(), asi, m_maincpu->pc()); - switch ((m_pagemap[entry] >> 26) & 3) + switch (entry.type) { case 0: // type 0 - m_type0space->write32(space, tmp, data, mem_mask); + //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(); @@ -806,7 +1098,7 @@ void sun4_state::write_insn_data_4c(uint8_t asi, address_space &space, uint32_t } else { - logerror("sun4c: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry, m_pagemap[entry], data, offset <<2, m_maincpu->pc()); + logerror("sun4c: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint<SUN4C>(), data, offset <<2, m_maincpu->pc()); m_maincpu->set_mae(); m_buserr[0] |= 0x8080; // write cycle, invalid PTE m_buserr[1] = offset<<2; @@ -829,221 +1121,181 @@ void sun4_state::write_insn_data_4c(uint8_t asi, address_space &space, uint32_t } -READ32_MEMBER( sun4_state::sun4c_mmu_r ) +// ----------------------------------------------------------------- + +READ32_MEMBER( sun4_state::sun4_system_r ) { - uint8_t asi = m_maincpu->get_asi(); - int page; - uint32_t retval = 0; + switch (offset >> 26) + { + case 3: // context reg + if (mem_mask == 0x00ff0000) return m_context<<16; + return m_context<<24; - // make debugger fetches emulate supervisor program for best compatibility with boot PROM execution - if (machine().side_effects_disabled()) asi = 9; + case 4: // system enable reg + return m_system_enable<<24; - // supervisor program fetches in boot state are special - if ((!(m_system_enable & ENA_NOTBOOT)) && (asi == 9)) - { - return m_rom_ptr[offset & 0x1ffff]; - } + case 6: // bus error register + //printf("sun4: read buserror, PC=%x (mask %08x)\n", m_maincpu->pc(), mem_mask); + return 0; - switch (asi) - { - case 2: // system space - 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); - 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 8: // (d-)cache tags + //logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc()); + return m_cachetags[offset&0xfff]; - 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; - } - break; - case 3: // segment map - //printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context & m_ctx_mask, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc()); - if (mem_mask == 0xffff0000) - { - return m_segmap[m_context & m_ctx_mask][(offset>>16) & 0xfff]<<16; - } - else if (mem_mask == 0xff000000) - { - return m_segmap[m_context & m_ctx_mask][(offset>>16) & 0xfff]<<24; - } - else - { - // printf("sun4: read segment map w/unk mask %08x\n", mem_mask); - } - return 0x0; - - case 4: // page map - page = (m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask) << 6; - page += (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_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask, mem_mask, m_maincpu->pc()); - return m_pagemap[page]; - - case 8: - case 9: - case 10: - case 11: - return read_insn_data_4c(asi, space, offset, mem_mask); - - default: - if (!machine().side_effects_disabled()) logerror("sun4c: ASI %d unhandled read @ %x (PC=%x)\n", asi, offset<<2, m_maincpu->pc()); - return 0; - } + case 9: // (d-)cache data + logerror("sun4: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc()); + return 0xffffffff; - logerror("sun4c: read asi %d byte offset %x, PC = %x\n", asi, offset << 2, m_maincpu->pc()); + case 0xf: // UART bypass + //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; + } + return 0xffffffff; - return 0; + case 0: + default: + logerror("sun4: ASI 2 space unhandled read @ %x (PC=%x)\n", offset<<2, m_maincpu->pc()); + return 0; + } } -WRITE32_MEMBER( sun4_state::sun4c_mmu_w ) +WRITE32_MEMBER( sun4_state::sun4_system_w ) { - uint8_t asi = m_maincpu->get_asi(); - int page; - - //printf("sun4: write %08x to %08x (ASI %d, mem_mask %08x, PC %x)\n", data, offset, asi, mem_mask, m_maincpu->pc()); - - switch (asi) + switch (offset >> 26) { - case 2: - switch (offset >> 26) - { - case 3: // context reg - //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset); - m_context = data>>24; - return; + case 3: // context reg + //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset); + m_context = data>>24; + return; - case 4: // system enable reg - m_system_enable = data>>24; + case 4: // system enable reg + m_system_enable = data>>24; - 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) + 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); + } + return; + + case 7: // diag reg + m_diag = data >> 24; + #if 1 + printf("sun4: CPU LEDs to %02x (PC=%x) => ", ((data>>24) & 0xff) ^ 0xff, m_maincpu->pc()); + for (int i = 0; i < 8; i++) + { + if (m_diag & (1<<i)) { - m_system_enable = 0; - m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + printf("."); } - 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) + else { - 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; + printf("*"); } - return; + } + printf("\n"); + #endif + 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; - } - break; - case 3: // segment map - { - 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, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc()); - m_segmap[m_context & m_ctx_mask][(offset>>16) & 0xfff] = segdata; // only 7 bits of the segment are necessary - } - return; + case 8: // cache tags + //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc()); + m_cachetags[offset&0xfff] = data; + return; - case 4: // page map - page = (m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask) << 6; // get the PMEG - page += (offset >> 10) & 0x3f; // add the offset - //printf("sun4c: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc()); - COMBINE_DATA(&m_pagemap[page]); - m_pagemap[page] &= 0xff00ffff; // these 8 bits are cleared when written and tested as such - return; + case 9: // cache data + logerror("sun4: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc()); + return; - case 8: - case 9: - case 10: - case 11: - write_insn_data_4c(asi, space, offset, data, mem_mask); - 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 12: // Flush Cache (Segment) - case 13: // Flush Cache (Page) - case 14: // Flush Cache (Context) - // Ignored - return; + case 0: // IDPROM + default: + logerror("sun4: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x)\n", data, offset<<2, mem_mask, m_maincpu->pc()); + return; } +} - logerror("sun4c: %08x to asi %d byte offset %x, PC = %x, mask = %08x\n", data, asi, offset << 2, m_maincpu->pc(), mem_mask); +READ32_MEMBER( sun4_state::sun4_segment_map_r ) +{ + //printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context, (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 0x0; } -// ----------------------------------------------------------------- +WRITE32_MEMBER( sun4_state::sun4_segment_map_w ) +{ + 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("sun4: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_maincpu->pc()); + + //printf("sun4: %08x to segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, m_context, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc()); + m_curr_segmap[(offset>>16) & 0xfff] = segdata; + m_curr_segmap_masked[(offset>>16) & 0xfff] = segdata << 5; +} -uint32_t sun4_state::read_insn_data(uint8_t asi, address_space &space, uint32_t offset, uint32_t mem_mask) +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<SUN4>(); +} + +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<SUN4>(data, mem_mask); + m_page_valid[page] = m_pagemap[page].valid; +} + +template <sun4_state::insn_data_mode MODE> +READ32_MEMBER( sun4_state::sun4_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 - uint8_t pmeg = m_segmap[m_context][(offset >> 16) & 0xfff]; - uint32_t entry = (pmeg << 5) + ((offset >> 11) & 0x1f); + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; + const uint32_t entry_index = pmeg | ((offset >> 11) & 0x1f); - if (m_pagemap[entry] & PM_VALID) + if (m_page_valid[entry_index]) { - m_pagemap[entry] |= PM_ACCESSED; + page_entry_t &entry = m_pagemap[entry_index]; + entry.accessed = PM_ACCESSED; - uint32_t tmp = (m_pagemap[entry] & 0x7ffff) << 11; - tmp |= (offset & 0x7ff); + 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, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], 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<SUN4>(), m_maincpu->pc()); - switch ((m_pagemap[entry] >> 26) & 3) + switch (entry.type) { case 0: // type 0 space return m_type0space->read32(space, tmp, mem_mask); @@ -1066,7 +1318,7 @@ uint32_t sun4_state::read_insn_data(uint8_t asi, address_space &space, uint32_t { if (!machine().side_effects_disabled()) { - logerror("sun4: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry, m_pagemap[entry], 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<SUN4>(), offset <<2, m_maincpu->pc()); m_maincpu->set_mae(); m_buserr[0] |= 0x80; // invalid PTE m_buserr[0] &= ~0x8000; // read @@ -1091,22 +1343,22 @@ uint32_t sun4_state::read_insn_data(uint8_t asi, address_space &space, uint32_t } } -void sun4_state::write_insn_data(uint8_t asi, address_space &space, uint32_t offset, uint32_t data, uint32_t mem_mask) +WRITE32_MEMBER( sun4_state::sun4_insn_data_w ) { // it's translation time - uint8_t pmeg = m_segmap[m_context][(offset >> 16) & 0xfff]; - uint32_t entry = (pmeg << 5) + ((offset >> 11) & 0x1f); + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; + const uint32_t entry_index = pmeg | ((offset >> 11) & 0x1f); - if (m_pagemap[entry] & PM_VALID) + if (m_page_valid[entry_index]) { - m_pagemap[entry] |= PM_ACCESSED; + page_entry_t &entry = m_pagemap[entry_index]; + entry.accessed = PM_ACCESSED; - uint32_t tmp = (m_pagemap[entry] & 0x7ffff) << 11; - tmp |= (offset & 0x7ff); + 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, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], 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<SUN4>(), m_maincpu->pc()); - switch ((m_pagemap[entry] >> 26) & 3) + switch (entry.type) { case 0: // type 0 m_type0space->write32(space, tmp, data, mem_mask); @@ -1124,220 +1376,15 @@ void sun4_state::write_insn_data(uint8_t asi, address_space &space, uint32_t off } else { - logerror("sun4: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry, m_pagemap[entry], 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<SUN4>(), data, offset <<2, m_maincpu->pc()); //m_maincpu->trap(SPARC_DATA_ACCESS_EXCEPTION); //m_buserr[0] = 0x8; // invalid PTE //m_buserr[1] = offset<<2; } } -READ32_MEMBER( sun4_state::sun4_mmu_r ) -{ - uint8_t asi = m_maincpu->get_asi(); - int page; - - // make debugger fetches emulate supervisor program for best compatibility with boot PROM execution - if (machine().side_effects_disabled()) asi = 9; - - // supervisor program fetches in boot state are special - if ((!(m_system_enable & ENA_NOTBOOT)) && (asi == 9)) - { - return m_rom_ptr[offset & 0x1ffff]; - } - - switch (asi) - { - case 2: // system space - 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("sun4: read buserror, PC=%x (mask %08x)\n", m_maincpu->pc(), mem_mask); - return 0; - - case 8: // (d-)cache tags - //logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc()); - return m_cachetags[offset&0xfff]; - - case 9: // (d-)cache data - logerror("sun4: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc()); - return 0xffffffff; - - case 0xf: // UART bypass - //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; - } - return 0xffffffff; - - case 0: - default: - logerror("sun4: ASI 2 space unhandled read @ %x (PC=%x)\n", offset<<2, m_maincpu->pc()); - return 0; - } - break; - case 3: // segment map - //printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context & m_ctx_mask, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc()); - if (mem_mask == 0xffff0000) - { - return m_segmap[m_context][(offset>>16) & 0xfff]<<16; - } - else if (mem_mask == 0xff000000) - { - return m_segmap[m_context][(offset>>16) & 0xfff]<<24; - } - else - { - // printf("sun4: read segment map w/unk mask %08x\n", mem_mask); - } - return 0x0; - - case 4: // page map - page = (m_segmap[m_context][(offset >> 16) & 0xfff]) << 5; - page += (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 & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask, mem_mask, m_maincpu->pc()); - return m_pagemap[page]; - - case 6: // region map used in 4/4xx, I don't know anything about this - return 0; - - case 8: - case 9: - case 10: - case 11: - return read_insn_data(asi, space, offset, mem_mask); - - default: - if (!machine().side_effects_disabled()) logerror("sun4: ASI %d unhandled read @ %x (PC=%x)\n", asi, offset<<2, m_maincpu->pc()); - return 0; - } - - logerror("sun4: read asi %d byte offset %x, PC = %x\n", asi, offset << 2, m_maincpu->pc()); - - return 0; -} - -WRITE32_MEMBER( sun4_state::sun4_mmu_w ) -{ - uint8_t asi = m_maincpu->get_asi(); - int page; - - //printf("sun4: write %08x to %08x (ASI %d, mem_mask %08x, PC %x)\n", data, offset, asi, mem_mask, m_maincpu->pc()); - - switch (asi) - { - case 2: - switch (offset >> 26) - { - case 3: // context reg - //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset); - m_context = data>>24; - return; - - case 4: // system enable reg - m_system_enable = data>>24; - - 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); - } - return; - - case 7: // diag reg - m_diag = data >> 24; - #if 1 - printf("sun4: CPU LEDs to %02x (PC=%x) => ", ((data>>24) & 0xff) ^ 0xff, m_maincpu->pc()); - for (int i = 0; i < 8; i++) - { - if (m_diag & (1<<i)) - { - printf("."); - } - else - { - printf("*"); - } - } - printf("\n"); - #endif - return; - - case 8: // cache tags - //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc()); - m_cachetags[offset&0xfff] = data; - return; - - case 9: // cache data - logerror("sun4: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc()); - 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("sun4: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x)\n", data, offset<<2, mem_mask, m_maincpu->pc()); - return; - } - break; - case 3: // segment map - { - 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("sun4: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_maincpu->pc()); - - //printf("sun4: %08x to segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, m_context, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc()); - m_segmap[m_context][(offset>>16) & 0xfff] = segdata; - } - return; - - case 4: // page map - page = (m_segmap[m_context][(offset >> 16) & 0xfff]) << 5; // get the PMEG - page += (offset >> 11) & 0x1f; // add the offset - //printf("sun4: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc()); - COMBINE_DATA(&m_pagemap[page]); - m_pagemap[page] &= 0xff07ffff; // these bits are cleared when written and tested as such - return; - - case 6: // region map, used in 4/4xx - return; - - case 8: - case 9: - case 10: - case 11: - write_insn_data(asi, space, offset, data, mem_mask); - break; - - } - - printf("sun4: %08x to asi %d byte offset %x, PC = %x, mask = %08x\n", data, asi, offset << 2, m_maincpu->pc(), mem_mask); -} +// make debugger fetches emulate supervisor program for best compatibility with boot PROM execution +//if (machine().side_effects_disabled()) asi = 9; void sun4_state::l2p_command(int ref, const std::vector<std::string> ¶ms) { @@ -1349,30 +1396,31 @@ void sun4_state::l2p_command(int ref, const std::vector<std::string> ¶ms) offset = addr >> 2; uint8_t pmeg = 0; - uint32_t entry = 0, tmp = 0; + uint32_t entry_index = 0, tmp = 0; + uint32_t entry_value = 0; if (m_arch == ARCH_SUN4) { - pmeg = m_segmap[m_context][(offset >> 16) & 0xfff]; - entry = (pmeg << 5) + ((offset >> 11) & 0x1f); - tmp = (m_pagemap[entry] & 0x7ffff) << 11; - tmp |= (offset & 0x7ff); + 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<SUN4>(); } else if (m_arch == ARCH_SUN4C) { - pmeg = m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff]; - entry = (pmeg << 6) + ((offset >> 10) & 0x3f); - tmp = (m_pagemap[entry] & 0xffff) << 10; - tmp |= (offset & 0x3ff); + 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<SUN4C>(); } - if (m_pagemap[entry] & PM_VALID) + if (m_page_valid[entry_index]) { - machine().debugger().console().printf("logical %08x => phys %08x, type %d (pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, (m_pagemap[entry] >> 26) & 3, pmeg, entry, m_pagemap[entry]); + machine().debugger().console().printf("logical %08x => phys %08x, type %d (pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, m_pagemap[entry_index].type, pmeg, entry_index, entry_value); } else { - machine().debugger().console().printf("logical %08x points to an invalid PTE! (pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, pmeg, entry, m_pagemap[entry]); + machine().debugger().console().printf("logical %08x points to an invalid PTE! (pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, pmeg, entry_index, entry_value); } } @@ -1397,14 +1445,114 @@ void sun4_state::fcodes_command(int ref, const std::vector<std::string> ¶ms) #endif } -void sun4_state::sun4_mem(address_map &map) +void sun4_state::sun4_system_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_system_r), FUNC(sun4_state::sun4_system_w)); +} + +void sun4_state::sun4_segment_map(address_map &map) { - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_mmu_r), FUNC(sun4_state::sun4_mmu_w)); + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_segment_map_r), FUNC(sun4_state::sun4_segment_map_w)); } -void sun4_state::sun4c_mem(address_map &map) +void sun4_state::sun4_page_map(address_map &map) { - map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_mmu_r), FUNC(sun4_state::sun4c_mmu_w)); + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_page_map_r), FUNC(sun4_state::sun4_page_map_w)); +} + +void sun4_state::sun4_supervisor_insn_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r<SUPER_INSN>), FUNC(sun4_state::sun4_insn_data_w)); +} + +void sun4_state::sun4_supervisor_data_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r<SUPER_DATA>), FUNC(sun4_state::sun4_insn_data_w)); +} + +void sun4_state::sun4_insn_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r<USER_INSN>), FUNC(sun4_state::sun4_insn_data_w)); +} + +void sun4_state::sun4_data_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r<USER_DATA>), 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<SUPER_INSN>), FUNC(sun4_state::sun4c_insn_data_w<SUPER_INSN>)); +} + +void sun4_state::sun4c_supervisor_data_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r<SUPER_DATA>), FUNC(sun4_state::sun4c_insn_data_w<SUPER_DATA>)); +} + +void sun4_state::sun4c_insn_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r<USER_INSN>), FUNC(sun4_state::sun4c_insn_data_w<USER_INSN>)); +} + +void sun4_state::sun4c_data_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r<USER_DATA>), FUNC(sun4_state::sun4c_insn_data_w<USER_DATA>)); +} + +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)); +} + +void sun4_state::type0space_map(address_map &map) +{ + map.unmap_value_high(); + map(0x00000000, 0x00ffffff).rw(FUNC(sun4_state::ram_r), FUNC(sun4_state::ram_w)); + map(0x04000000, 0x0fffffff).rw(FUNC(sun4_state::timeout_r), FUNC(sun4_state::timeout_w)); +} + +void sun4_state::type1space_map(address_map &map) +{ + map(0x00000000, 0x0000000f).rw(m_scc1, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00); + map(0x01000000, 0x0100000f).rw(m_scc2, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00); + map(0x02000000, 0x020007ff).rw(m_timekpr, FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)); + map(0x03000000, 0x0300000f).rw(FUNC(sun4_state::timer_r), FUNC(sun4_state::timer_w)).mirror(0xfffff0); + map(0x05000000, 0x05000003).rw(FUNC(sun4_state::irq_r), FUNC(sun4_state::irq_w)); + map(0x06000000, 0x0607ffff).rom().region("user1", 0); + map(0x07200000, 0x07200003).rw(FUNC(sun4_state::fdc_r), FUNC(sun4_state::fdc_w)); + map(0x07400003, 0x07400003).rw(FUNC(sun4_state::auxio_r), FUNC(sun4_state::auxio_w)); + map(0x08000000, 0x08000003).r(FUNC(sun4_state::ss1_sl0_id)); // slot 0 contains SCSI/DMA/Ethernet + map(0x08400000, 0x0840000f).rw(FUNC(sun4_state::dma_r), FUNC(sun4_state::dma_w)); + map(0x08800000, 0x0880002f).m(m_scsi, FUNC(ncr53c90a_device::map)).umask32(0xff000000); + map(0x08c00000, 0x08c00003).rw(m_lance, FUNC(am79c90_device::regs_r), FUNC(am79c90_device::regs_w)); +} + +void sun4_state::type1space_sbus_map(address_map &map) +{ + type1space_map(map); + map(0x0a000000, 0x0fffffff).rw(m_sbus, FUNC(sbus_device::read), FUNC(sbus_device::write)); +} + +void sun4_state::type1space_s4_map(address_map &map) +{ + map(0x00000000, 0x0000000f).rw(m_scc1, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00); + map(0x01000000, 0x0100000f).rw(m_scc2, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00); } /* Input ports */ @@ -1414,7 +1562,11 @@ 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; @@ -1435,6 +1587,12 @@ 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; @@ -1472,11 +1630,7 @@ WRITE32_MEMBER( sun4_state::timeout_w ) READ32_MEMBER( sun4_state::ram_r ) { - //printf("ram_r: @ %08x (mask %08x)\n", offset<<2, mem_mask); - - if (offset < m_ram_size_words) return m_ram_ptr[offset]; - - return 0xffffffff; + return m_ram_ptr[offset]; } WRITE32_MEMBER( sun4_state::ram_w ) @@ -1538,45 +1692,7 @@ WRITE32_MEMBER( sun4_state::ram_w ) //if ((offset<<2) == 0xfb2000) printf("write %08x to %08x, mask %08x, PC=%x\n", data, offset<<2, mem_mask, m_maincpu->pc()); - if (offset < m_ram_size_words) - { - COMBINE_DATA(&m_ram_ptr[offset]); - return; - } -} - -void sun4_state::type0space_map(address_map &map) -{ - map(0x00000000, 0x03ffffff).rw(FUNC(sun4_state::ram_r), FUNC(sun4_state::ram_w)); - map(0x04000000, 0x0fffffff).rw(FUNC(sun4_state::timeout_r), FUNC(sun4_state::timeout_w)); -} - -void sun4_state::type1space_map(address_map &map) -{ - map(0x00000000, 0x0000000f).rw(m_scc1, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00); - map(0x01000000, 0x0100000f).rw(m_scc2, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00); - map(0x02000000, 0x020007ff).rw(m_timekpr, FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)); - map(0x03000000, 0x0300000f).rw(FUNC(sun4_state::timer_r), FUNC(sun4_state::timer_w)).mirror(0xfffff0); - map(0x05000000, 0x05000003).rw(FUNC(sun4_state::irq_r), FUNC(sun4_state::irq_w)); - map(0x06000000, 0x0607ffff).rom().region("user1", 0); - map(0x07200000, 0x07200003).rw(FUNC(sun4_state::fdc_r), FUNC(sun4_state::fdc_w)); - map(0x07400003, 0x07400003).rw(FUNC(sun4_state::auxio_r), FUNC(sun4_state::auxio_w)); - map(0x08000000, 0x08000003).r(FUNC(sun4_state::ss1_sl0_id)); // slot 0 contains SCSI/DMA/Ethernet - map(0x08400000, 0x0840000f).rw(FUNC(sun4_state::dma_r), FUNC(sun4_state::dma_w)); - map(0x08800000, 0x0880002f).m(m_scsi, FUNC(ncr53c90a_device::map)).umask32(0xff000000); - map(0x08c00000, 0x08c00003).rw(m_lance, FUNC(am79c90_device::regs_r), FUNC(am79c90_device::regs_w)); -} - -void sun4_state::type1space_sbus_map(address_map &map) -{ - type1space_map(map); - map(0x0a000000, 0x0fffffff).rw(m_sbus, FUNC(sbus_device::read), FUNC(sbus_device::write)); -} - -void sun4_state::type1space_s4_map(address_map &map) -{ - map(0x00000000, 0x0000000f).rw(m_scc1, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00); - map(0x01000000, 0x0100000f).rw(m_scc2, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00); + COMBINE_DATA(&m_ram_ptr[offset]); } READ8_MEMBER( sun4_state::fdc_r ) @@ -1618,13 +1734,13 @@ WRITE8_MEMBER( sun4_state::fdc_w ) READ8_MEMBER( sun4_state::auxio_r ) { - logerror("%s: auxio_r: %02x\n", machine().describe_context(), m_auxio); + //logerror("%s: auxio_r: %02x\n", machine().describe_context(), m_auxio); return m_auxio; } WRITE8_MEMBER( sun4_state::auxio_w ) { - logerror("%s: auxio_w: %02x, drive_sel:%d tc:%d eject:%d LED:%d\n", machine().describe_context(), data, BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0)); + //logerror("%s: auxio_w: %02x, drive_sel:%d tc:%d eject:%d LED:%d\n", machine().describe_context(), data, BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0)); m_auxio = (m_auxio & 0xf0) | (data & 0x0f); if (!(m_auxio & AUXIO_DRIVE_SEL)) { @@ -1648,7 +1764,7 @@ WRITE8_MEMBER( sun4_state::irq_w ) m_irq_reg = data; const uint8_t changed = old_irq ^ data; - logerror("%02x to IRQ, %02x changed\n", data, changed); + //logerror("%02x to IRQ, %02x changed\n", data, changed); if (!changed) return; @@ -1836,7 +1952,7 @@ void sun4_state::dma_transfer_write() { //logerror("DMAing from device to RAM\n"); - address_space &space = m_maincpu->space(AS_PROGRAM); + 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) @@ -1855,11 +1971,11 @@ 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) { - write_insn_data_4c(11, space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); + sun4c_insn_data_w<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); } else { - write_insn_data(11, space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); + sun4c_insn_data_w<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); } pack_cnt = 0; @@ -1876,7 +1992,7 @@ void sun4_state::dma_transfer_read() { //logerror("DMAing from RAM to device\n"); - address_space &space = m_maincpu->space(AS_PROGRAM); + address_space &space = m_maincpu->space(mb86901_device::AS_START+9); bool word_cached = false; uint32_t current_word = 0; @@ -1886,11 +2002,11 @@ void sun4_state::dma_transfer_read() { if (m_arch == ARCH_SUN4C) { - current_word = read_insn_data_4c(11, space, m_dma[DMA_ADDR] >> 2, ~0); + current_word = sun4c_insn_data_r<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, ~0); } else { - current_word = read_insn_data(11, space, m_dma[DMA_ADDR] >> 2, ~0); + current_word = sun4c_insn_data_r<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, ~0); } word_cached = true; //logerror("Current word: %08x\n", current_word); @@ -1972,7 +2088,7 @@ 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)); - write_insn_data_4c(11, space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); + sun4c_insn_data_w<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); m_dma[DMA_ADDR]++; } m_dma_pack_register = 0; @@ -2041,17 +2157,17 @@ WRITE_LINE_MEMBER( sun4_state::fdc_irq ) READ32_MEMBER( sun4_state::lance_dma_r ) { if (m_arch == ARCH_SUN4) - return read_insn_data(11, m_maincpu->space(AS_PROGRAM), offset, mem_mask); + return sun4_insn_data_r<SUPER_DATA>(space, offset, mem_mask); else - return read_insn_data_4c(11, m_maincpu->space(AS_PROGRAM), offset, mem_mask); + return sun4c_insn_data_r<SUPER_DATA>(space, offset, mem_mask); } WRITE32_MEMBER( sun4_state::lance_dma_w ) { if (m_arch == ARCH_SUN4) - write_insn_data(11, m_maincpu->space(AS_PROGRAM), offset, data, mem_mask); + sun4_insn_data_w(space, offset, data, mem_mask); else - write_insn_data_4c(11, m_maincpu->space(AS_PROGRAM), offset, data, mem_mask); + sun4c_insn_data_w<SUPER_DATA>(space, offset, data, mem_mask); } WRITE32_MEMBER( sun4_state::buserr_w ) @@ -2099,8 +2215,14 @@ 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_ADDRESS_MAP(AS_PROGRAM, sun4_mem) 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); RAM(config, RAM_TAG).set_default_size("16M").set_default_value(0x00); @@ -2163,8 +2285,18 @@ MACHINE_CONFIG_END MACHINE_CONFIG_START(sun4_state::sun4c) /* basic machine hardware */ MCFG_DEVICE_ADD(m_maincpu, MB86901, 16670000) - MCFG_DEVICE_ADDRESS_MAP(AS_PROGRAM, sun4c_mem) 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); RAM(config, RAM_TAG).set_default_size("16M").set_default_value(0x00); @@ -2526,4 +2658,4 @@ COMP( 1990, sun4_75, sun4_300, 0, sun4c, sun4, sun4_state, init_ss2, // 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 ) -COMP( 1994, sun_s20, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +COMP( 1994, sun_s20, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
\ No newline at end of file |