diff options
Diffstat (limited to 'src/devices/cpu/sparc/mb86901.cpp')
-rw-r--r-- | src/devices/cpu/sparc/mb86901.cpp | 448 |
1 files changed, 222 insertions, 226 deletions
diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp index 76ef7ac56e4..751e39610e3 100644 --- a/src/devices/cpu/sparc/mb86901.cpp +++ b/src/devices/cpu/sparc/mb86901.cpp @@ -8,6 +8,13 @@ // the integer instructions in a SPARC v7 // compatible instruction set. // +// Notes: +// - The CPU core implementation has been simplified +// somewhat compared to the spec. In particular, bus +// holding on read/write accesses is disabled, as there +// is currently no use made of it, and it is unlikely to +// ever be. +// // To-Do: // - Ops: FBFcc, LDF, STF // - Test: SPARCv8 ops are untested @@ -41,16 +48,9 @@ const int mb86901_device::NWINDOWS = 7; mb86901_device::mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, MB86901, tag, owner, clock) + , m_mmu(*this, finder_base::DUMMY_TAG) { m_default_config = address_space_config("program", ENDIANNESS_BIG, 32, 32); - - char buf[32]; - for (uint32_t i = 0; i < AS_COUNT; i++) - { - snprintf(buf, ARRAY_LENGTH(buf), "asi%d", i); - m_asi_names[i] = buf; - m_asi_config[i] = address_space_config(m_asi_names[i].c_str(), ENDIANNESS_BIG, 32, 32); - } } @@ -153,6 +153,29 @@ void mb86901_device::device_start() memset(m_privileged_asr, 1, 32 * sizeof(bool)); m_privileged_asr[0] = false; + memset(m_alu_setcc, 0, 64 * sizeof(bool)); + m_alu_setcc[OP3_ADDCC] = true; + m_alu_setcc[OP3_ANDCC] = true; + m_alu_setcc[OP3_ORCC] = true; + m_alu_setcc[OP3_XORCC] = true; + m_alu_setcc[OP3_SUBCC] = true; + m_alu_setcc[OP3_ANDNCC] = true; + m_alu_setcc[OP3_ORNCC] = true; + m_alu_setcc[OP3_XNORCC] = true; + m_alu_setcc[OP3_ADDXCC] = true; + m_alu_setcc[OP3_SUBXCC] = true; + m_alu_setcc[OP3_TADDCC] = true; + m_alu_setcc[OP3_TSUBCC] = true; + m_alu_setcc[OP3_TADDCCTV] = true; + m_alu_setcc[OP3_TSUBCCTV] = true; + m_alu_setcc[OP3_MULSCC] = true; +#if SPARCV8 + m_alu_setcc[OP3_UMULCC] = true; + m_alu_setcc[OP3_SMULCC] = true; + m_alu_setcc[OP3_UDIVCC] = true; + m_alu_setcc[OP3_SDIVCC] = true; +#endif + memset(m_alu_op3_assigned, 0, 64 * sizeof(bool)); m_alu_op3_assigned[OP3_ADD] = true; m_alu_op3_assigned[OP3_AND] = true; @@ -210,11 +233,6 @@ void mb86901_device::device_start() m_alu_op3_assigned[OP3_UDIVCC] = true; m_alu_op3_assigned[OP3_SDIVCC] = true; #endif - for (uint32_t i = 0; i < AS_COUNT; i++) - { - m_space[i] = &space(AS_START + i); - m_access_cache[i] = m_space[i]->cache<2, 0, ENDIANNESS_BIG>(); - } memset(m_ldst_op3_assigned, 0, 64 * sizeof(bool)); m_ldst_op3_assigned[OP3_LD] = true; @@ -379,6 +397,10 @@ void mb86901_device::device_stop() { } +void mb86901_device::device_resolve_objects() +{ + m_mmu->set_host(this); +} void mb86901_device::device_reset() { @@ -405,6 +427,8 @@ void mb86901_device::device_reset() m_bp_irl = 0; m_irq_state = 0; + m_stashed_icount = -1; + MAE = false; HOLD_BUS = false; m_annul = false; @@ -420,7 +444,8 @@ void mb86901_device::device_reset() PSR = PSR_S_MASK | PSR_PS_MASK; m_s = true; - m_fetch_space = 9; + m_insn_space = 9; + m_data_space = 11; for (int i = 0; i < 8; i++) { @@ -448,10 +473,6 @@ device_memory_interface::space_config_vector mb86901_device::memory_space_config { space_config_vector config_vector; config_vector.push_back(std::make_pair(AS_PROGRAM, &m_default_config)); - for (uint32_t i = 0; i < 32; i++) - { - config_vector.push_back(std::make_pair(AS_START + i, &m_asi_config[i])); - } return config_vector; } @@ -463,21 +484,10 @@ device_memory_interface::space_config_vector mb86901_device::memory_space_config // a 32-bit word in a big-endian system. //------------------------------------------------- -uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size) +uint32_t mb86901_device::read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask) { assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - if (size == 1) - { - return m_access_cache[asi]->read_byte(address) << ((3 - (address & 3)) * 8); - } - else if (size == 2) - { - return m_access_cache[asi]->read_word(address) << ((2 - (address & 2)) * 8); - } - else - { - return m_access_cache[asi]->read_dword(address); - } + return m_mmu->read_asi(asi, address >> 2, mem_mask); } @@ -490,21 +500,10 @@ uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size // size handlers //------------------------------------------------- -void mb86901_device::write_sized_word(uint8_t asi, uint32_t address, uint32_t data, int size) +void mb86901_device::write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask) { assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - if (size == 1) - { - m_access_cache[asi]->write_byte(address, data >> ((3 - (address & 3)) * 8)); - } - else if (size == 2) - { - m_access_cache[asi]->write_word(address, data >> ((2 - (address & 2)) * 8)); - } - else - { - m_access_cache[asi]->write_dword(address, data); - } + m_mmu->write_asi(asi, address >> 2, data, mem_mask); } @@ -911,10 +910,11 @@ void mb86901_device::execute_logical(uint32_t op) ); */ - uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; + const uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; + const uint32_t op3 = OP3; uint32_t result = 0; - switch (OP3) + switch (op3) { case OP3_AND: case OP3_ANDCC: @@ -945,11 +945,13 @@ void mb86901_device::execute_logical(uint32_t op) if (RD != 0) RDREG = result; - if (ANDCC || ANDNCC || ORCC || ORNCC || XORCC || XNORCC) + if (m_alu_setcc[op3]) { CLEAR_ICC; - PSR |= (BIT31(result)) ? PSR_N_MASK : 0; - PSR |= (result == 0) ? PSR_Z_MASK : 0; + if (result & 0x80000000) + PSR |= PSR_N_MASK; + else if (result == 0) + PSR |= PSR_Z_MASK; } PC = nPC; @@ -1205,7 +1207,16 @@ void mb86901_device::execute_wrsr(uint32_t op) m_et = PSR & PSR_ET_MASK; m_pil = (PSR & PSR_PIL_MASK) >> PSR_PIL_SHIFT; m_s = PSR & PSR_S_MASK; - m_fetch_space = m_s ? 9 : 8; + if (m_s) + { + m_insn_space = 9; + m_data_space = 11; + } + else + { + m_insn_space = 8; + m_data_space = 10; + } PC = nPC; nPC = nPC + 4; @@ -1304,6 +1315,8 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 3; m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; return; } else if ((WIM & (1 << new_cwp)) != 0) @@ -1313,6 +1326,8 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 6; m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; return; } else if (address & 3) @@ -1322,6 +1337,8 @@ void mb86901_device::execute_rett(uint32_t op) m_tt = 7; m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; return; } @@ -1337,13 +1354,15 @@ void mb86901_device::execute_rett(uint32_t op) { PSR |= PSR_S_MASK; m_s = true; - m_fetch_space = 9; + m_insn_space = 9; + m_data_space = 11; } else { PSR &= ~PSR_S_MASK; m_s = false; - m_fetch_space = 8; + m_insn_space = 8; + m_data_space = 10; } update_gpr_pointers(); @@ -1405,7 +1424,6 @@ void mb86901_device::execute_saverestore(uint32_t op) result = rs1 + operand2; PSR &= ~PSR_CWP_MASK; PSR |= new_cwp; - //BREAK_PSR; } else if (RESTORE) { @@ -1420,7 +1438,6 @@ void mb86901_device::execute_saverestore(uint32_t op) result = rs1 + operand2; PSR &= ~PSR_CWP_MASK; PSR |= new_cwp; - //BREAK_PSR; } update_gpr_pointers(); @@ -1475,7 +1492,7 @@ void mb86901_device::execute_jmpl(uint32_t op) // mostly ALU ops //------------------------------------------------- -void mb86901_device::execute_group2(uint32_t op) +inline void mb86901_device::execute_group2(uint32_t op) { switch (OP3) { @@ -1550,6 +1567,7 @@ void mb86901_device::execute_group2(uint32_t op) m_trap = 1; m_fp_disabled = 1; } + complete_fp_execution(op); return; case OP3_JMPL: @@ -1592,14 +1610,14 @@ void mb86901_device::execute_group2(uint32_t op) case OP3_CPOP1: case OP3_CPOP2: - printf("fpop @ %08x: %08x\n", PC, op); + logerror("fpop @ %08x: %08x\n", PC, op); m_trap = 1; m_cp_disabled = 1; return; #endif default: - printf("illegal instruction at %08x: %08x\n", PC, op); + logerror("illegal instruction at %08x: %08x\n", PC, op); m_trap = 1; m_illegal_instruction = 1; break; @@ -1768,7 +1786,7 @@ void mb86901_device::execute_store(uint32_t op) if (STD || ST || STH || STB || STF || STDF || STFSR || STDFQ || STCSR || STC || STDC || STDCQ) { address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + addr_space = m_data_space; } else if (STDA || STA || STHA || STBA) { @@ -1925,7 +1943,9 @@ void mb86901_device::execute_store(uint32_t op) } } - write_sized_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 4 : ((STH || STHA) ? 2 : 1)); + static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; + static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; + m_mmu->write_asi(addr_space, address >> 2, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 0xffffffff : ((STH || STHA) ? mask16[address & 2] : mask8[address & 3])); if (MAE) { m_trap = 1; @@ -1957,7 +1977,7 @@ void mb86901_device::execute_store(uint32_t op) data1 = 0; } - write_sized_word(addr_space, address + 4, data1, 4); + m_mmu->write_asi(addr_space, (address + 4) >> 2, data1, 0xffffffff); if (MAE) { m_trap = 1; @@ -2076,14 +2096,14 @@ void mb86901_device::execute_load(uint32_t op) ); */ - uint32_t address = 0; - uint8_t addr_space = 0; + static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; + static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; + switch (OP3) { case OP3_LDD: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 7) { @@ -2091,7 +2111,7 @@ void mb86901_device::execute_load(uint32_t op) m_mem_address_not_aligned = 1; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { @@ -2103,7 +2123,7 @@ void mb86901_device::execute_load(uint32_t op) if (RD != 0) RDREG = data; - const uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2116,8 +2136,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LD: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 3) { @@ -2126,7 +2145,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2141,8 +2160,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDSH: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 1) { @@ -2151,7 +2169,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2169,8 +2187,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDUH: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (address & 1) { @@ -2179,7 +2196,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2197,10 +2214,9 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDSB: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2220,10 +2236,9 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDUB: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2243,8 +2258,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDDFPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) { @@ -2276,7 +2290,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2287,7 +2301,7 @@ void mb86901_device::execute_load(uint32_t op) FREG(RD & 0x1e) = data; - const uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2300,8 +2314,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDFPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) { @@ -2325,7 +2338,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2339,8 +2352,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDFSR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) { @@ -2364,7 +2376,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2378,8 +2390,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDDCPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { @@ -2403,7 +2414,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - read_sized_word(addr_space, address, 4); + m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2413,7 +2424,7 @@ void mb86901_device::execute_load(uint32_t op) // implementation-dependent actions - read_sized_word(addr_space, address + 4, 4); + m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2426,8 +2437,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDCPR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { @@ -2451,7 +2461,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - read_sized_word(addr_space, address, 4); + m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { @@ -2465,8 +2475,7 @@ void mb86901_device::execute_load(uint32_t op) } case OP3_LDCSR: { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); + const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { @@ -2490,7 +2499,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - read_sized_word(addr_space, address, 4); + m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); if (MAE) { @@ -2516,11 +2525,9 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + + const uint32_t address = RS1REG + RS2REG; + const uint32_t addr_space = ASI; if (address & 7) { @@ -2529,7 +2536,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(addr_space, address >> 2, 0xffffffff); if (m_mae) { @@ -2541,7 +2548,7 @@ void mb86901_device::execute_load(uint32_t op) if (RD != 0) RDREG = data; - uint32_t word1 = read_sized_word(addr_space, address + 4, 4); + uint32_t word1 = m_mmu->read_asi(addr_space, (address + 4) >> 2, 0xffffffff); if (MAE) { m_trap = 1; @@ -2566,11 +2573,8 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + + const uint32_t address = RS1REG + RS2REG; if (address & 3) { @@ -2579,7 +2583,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 4); + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, 0xffffffff); if (m_mae) { @@ -2606,11 +2610,8 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + + const uint32_t address = RS1REG + RS2REG; if (address & 1) { @@ -2619,7 +2620,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2649,12 +2650,8 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } + const uint32_t address = RS1REG + RS2REG; if (address & 1) { m_trap = 1; @@ -2662,7 +2659,7 @@ void mb86901_device::execute_load(uint32_t op) return; } - const uint32_t data = read_sized_word(addr_space, address, 2); + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); if (m_mae) { @@ -2692,13 +2689,9 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t address = RS1REG + RS2REG; + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2730,13 +2723,9 @@ void mb86901_device::execute_load(uint32_t op) m_illegal_instruction = 1; return; } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - } - const uint32_t data = read_sized_word(addr_space, address, 1); + const uint32_t address = RS1REG + RS2REG; + const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); if (m_mae) { @@ -2868,7 +2857,8 @@ void mb86901_device::execute_ldstub(uint32_t op) m_pb_block_ldst_byte = 1; - data = read_sized_word(addr_space, address, 1); + static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; + data = m_mmu->read_asi(addr_space, address >> 2, mask8[address & 3]); if (MAE) { @@ -2877,24 +2867,7 @@ void mb86901_device::execute_ldstub(uint32_t op) return; } - //uint8_t byte_mask; - if ((address & 3) == 0) - { - //byte_mask = 8; - } - else if ((address & 3) == 1) - { - //byte_mask = 4; - } - else if ((address & 3) == 2) - { - //byte_mask = 2; - } - else if ((address & 3) == 3) - { - //byte_mask = 1; - } - write_sized_word(addr_space, address, 0xffffffff, 1); + m_mmu->write_asi(addr_space, address >> 2, 0xffffffff, mask8[address & 3]); m_pb_block_ldst_byte = 0; @@ -2935,7 +2908,7 @@ void mb86901_device::execute_ldstub(uint32_t op) // (load/store) //------------------------------------------------- -void mb86901_device::execute_group3(uint32_t op) +inline void mb86901_device::execute_group3(uint32_t op) { static const int ldst_cycles[64] = { 1, 1, 1, 2, 2, 2, 2, 3, @@ -3003,13 +2976,13 @@ void mb86901_device::execute_group3(uint32_t op) #endif default: - printf("illegal instruction at %08x: %08x\n", PC, op); + logerror("illegal instruction at %08x: %08x\n", PC, op); m_trap = 1; m_illegal_instruction = 1; break; } - if (MAE || HOLD_BUS) + if (MAE /*|| HOLD_BUS*/) m_icount--; else m_icount -= ldst_cycles[OP3]; @@ -3186,6 +3159,8 @@ void mb86901_device::select_trap() { m_execute_mode = 0; m_error_mode = 1; + m_stashed_icount = m_icount; + m_icount = 0; } else if (m_data_store_error) m_tt = 0x2b; @@ -3355,7 +3330,8 @@ void mb86901_device::execute_trap() PSR |= PSR_S_MASK; m_s = true; - m_fetch_space = 9; + m_insn_space = 9; + m_data_space = 11; int cwp = PSR & PSR_CWP_MASK; int new_cwp = ((cwp + NWINDOWS) - 1) % NWINDOWS; @@ -3425,13 +3401,14 @@ if (trap = 0) then ( inline void mb86901_device::dispatch_instruction(uint32_t op) { - switch (OP_NS) + const uint8_t op_type = OP; + switch (op_type) { - case OP_TYPE0_NS: // Bicc, SETHI, FBfcc + case OP_TYPE0: // Bicc, SETHI, FBfcc switch (OP2) { case OP2_UNIMP: // unimp - printf("unimp @ %x\n", PC); + logerror("unimp @ %x\n", PC); break; case OP2_BICC: // branch on integer condition codes execute_bicc(op); @@ -3446,7 +3423,7 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) case OP2_FBFCC: // branch on floating-point condition codes if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present) { - //printf("fbfcc at %08x: %08x\n", PC, op); + logerror("fbfcc at %08x: %08x\n", PC, op); m_trap = 1; m_fp_disabled = 1; return; @@ -3456,7 +3433,7 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) case OP2_CBCCC: // branch on coprocessor condition codes, SPARCv8 if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) { - printf("cbccc @ %08x: %08x\n", PC, op); + logerror("cbccc @ %08x: %08x\n", PC, op); m_trap = 1; m_cp_disabled = 1; return; @@ -3464,14 +3441,14 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) return; #endif default: - printf("illegal instruction at %08x: %08x\n", PC, op); + logerror("illegal instruction at %08x: %08x\n", PC, op); m_trap = 1; m_illegal_instruction = 1; return; } break; - case OP_CALL_NS: // call + case OP_CALL: { uint32_t pc = PC; uint32_t callpc = PC + DISP30; @@ -3482,11 +3459,11 @@ inline void mb86901_device::dispatch_instruction(uint32_t op) break; } - case OP_ALU_NS: + case OP_ALU: execute_group2(op); break; - case OP_LDST_NS: + case OP_LDST: execute_group3(op); break; } @@ -3506,7 +3483,7 @@ void mb86901_device::complete_fp_execution(uint32_t /*op*/) // mode (versus error or reset modes) //------------------------------------------------- -void mb86901_device::execute_step() +inline void mb86901_device::execute_step() { /* The SPARC Instruction Manual: Version 8, page 156, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 153) @@ -3565,7 +3542,8 @@ void mb86901_device::execute_step() m_execute_mode = 0; m_error_mode = 0; m_reset_mode = 1; - //printf("Entering reset mode\n"); + m_stashed_icount = m_icount; + m_icount = 0; return; } else if (m_et && (m_bp_irl == 15 || m_bp_irl > m_pil)) @@ -3577,51 +3555,35 @@ void mb86901_device::execute_step() if (m_trap) { execute_trap(); - //BREAK_PSR; - debugger_instruction_hook(PC); } - if (m_execute_mode) - { - // write-state-register delay not yet implemented + // write-state-register delay not yet implemented - const uint32_t op = read_sized_word(m_fetch_space, PC, 4); + const uint32_t op = m_mmu->read_asi(m_insn_space, PC >> 2, 0xffffffff); #if LOG_FCODES - //if (m_log_fcodes) - { - log_fcodes(); - } + //if (m_log_fcodes) + { + log_fcodes(); + } #endif - if (MAE && !m_annul) + if (MAE && !m_annul) + { + m_trap = 1; + m_instruction_access_exception = 1; + } + else + { + if (!m_annul) { - m_trap = 1; - m_instruction_access_exception = 1; + dispatch_instruction(op); } else { - if (!m_annul) - { - dispatch_instruction(op); - - if (FPOP1 || FPOP2) - { - complete_fp_execution(op); - } - - //if (m_trap == 0 && !(OP == OP_CALL || (OP == OP_TYPE0 && (OP2 == OP2_BICC || OP2 == OP2_FBFCC || OP2 == OP2_CBCCC)) || (OP == OP_ALU && (JMPL || TICC || RETT)))) - //{ - //PC = nPC; - //nPC = nPC + 4; - //} - } - else - { - m_annul = 0; - PC = nPC; - nPC = nPC + 4; - } + m_annul = 0; + PC = nPC; + nPC = nPC + 4; } } } @@ -3651,7 +3613,8 @@ void mb86901_device::reset_step() m_execute_mode = 1; m_trap = 1; m_reset_trap = 1; - //printf("m_bp_reset_in is false, resetting\n"); + m_stashed_icount = m_icount; + m_icount = 0; } } @@ -3678,44 +3641,39 @@ void mb86901_device::error_step() m_error_mode = 0; m_reset_mode = 1; m_pb_error = 0; + m_stashed_icount = m_icount; + m_icount = 0; } } - -//------------------------------------------------- -// execute_run - execute a timeslice's worth of -// opcodes -//------------------------------------------------- - -void mb86901_device::execute_run() +template <bool CHECK_DEBUG, mb86901_device::running_mode MODE> +void mb86901_device::run_loop() { - bool debug = machine().debug_flags & DEBUG_FLAG_ENABLED; - - while (m_icount > 0) + do { - if (HOLD_BUS) + /*if (HOLD_BUS) { m_icount--; continue; - } + }*/ - //BREAK_PSR; - debugger_instruction_hook(PC); + if (CHECK_DEBUG) + debugger_instruction_hook(PC); - if (m_reset_mode) + if (MODE == MODE_RESET) { reset_step(); } - else if (m_error_mode) + else if (MODE == MODE_ERROR) { error_step(); } - else if (m_execute_mode) + else if (MODE == MODE_EXECUTE) { execute_step(); } - if (debug) + if (CHECK_DEBUG) { for (int i = 0; i < 8; i++) { @@ -3725,7 +3683,45 @@ void mb86901_device::execute_run() } } --m_icount; - } + } while (m_icount >= 0); +} + +//------------------------------------------------- +// execute_run - execute a timeslice's worth of +// opcodes +//------------------------------------------------- + +void mb86901_device::execute_run() +{ + bool debug = machine().debug_flags & DEBUG_FLAG_ENABLED; + + do + { + if (debug) + { + if (m_reset_mode) + run_loop<true, MODE_RESET>(); + else if (m_error_mode) + run_loop<true, MODE_ERROR>(); + else + run_loop<true, MODE_EXECUTE>(); + } + else + { + if (m_reset_mode) + run_loop<false, MODE_RESET>(); + else if (m_error_mode) + run_loop<false, MODE_ERROR>(); + else + run_loop<false, MODE_EXECUTE>(); + } + + if (m_stashed_icount >= 0) + { + m_icount = m_stashed_icount; + m_stashed_icount = -1; + } + } while (m_icount >= 0); } |