diff options
Diffstat (limited to 'src/devices/cpu/powerpc/ppccom.cpp')
-rw-r--r-- | src/devices/cpu/powerpc/ppccom.cpp | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/src/devices/cpu/powerpc/ppccom.cpp b/src/devices/cpu/powerpc/ppccom.cpp index b0e4b583955..4e76a3efbb2 100644 --- a/src/devices/cpu/powerpc/ppccom.cpp +++ b/src/devices/cpu/powerpc/ppccom.cpp @@ -281,10 +281,16 @@ mpc8240_device::mpc8240_device(const machine_config &mconfig, const char *tag, d } ppc601_device::ppc601_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ppc_device(mconfig, PPC601, tag, owner, clock, 32, 64, PPC_MODEL_601, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_MFIOC | PPCCAP_601BAT, 0/* no TB */, address_map_constructor()) + : ppc_device(mconfig, PPC601, tag, owner, clock, 32, 64, PPC_MODEL_601, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_MFIOC | PPCCAP_601BAT | PPCCAP_LEGACY_POWER, 0 /* no TB */, address_map_constructor()) { } +std::unique_ptr<util::disasm_interface> ppc601_device::create_disassembler() +{ + // 601 has both POWER and PowerPC instructions + return std::make_unique<powerpc_disassembler>((powerpc_disassembler::implementation)(powerpc_disassembler::I_POWER|powerpc_disassembler::I_POWERPC)); +} + ppc604_device::ppc604_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ppc_device(mconfig, PPC604, tag, owner, clock, 32, 64, PPC_MODEL_604, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_604_MMU, 4, address_map_constructor()) { @@ -505,8 +511,7 @@ static inline int is_qnan_double(double x) { uint64_t xi = *(uint64_t*)&x; return( ((xi & DOUBLE_EXP) == DOUBLE_EXP) && - ((xi & 0x0007fffffffffffU) == 0x000000000000000U) && - ((xi & 0x000800000000000U) == 0x000800000000000U) ); + ((xi & 0x0008000000000000U) == 0x0008000000000000U) ); } @@ -714,7 +719,7 @@ void ppc_device::device_start() m_sebr = 0; m_ser = 0; - memset(&m_spu, 0, sizeof(m_spu)); + m_spu.clear(); m_pit_reload = 0; m_irqstate = 0; memset(m_buffered_dma_rate, 0, sizeof(m_buffered_dma_rate)); @@ -722,6 +727,7 @@ void ppc_device::device_start() m_cpu_clock = 0; m_tb_zero_cycles = 0; m_dec_zero_cycles = 0; + m_rtc_zero_cycles = 0; m_arg1 = 0; m_fastram_select = 0; @@ -832,6 +838,11 @@ void ppc_device::device_start() state_add(PPC_PC, "PC", m_core->pc).formatstr("%08X"); state_add(PPC_MSR, "MSR", m_core->msr).formatstr("%08X"); state_add(PPC_CR, "CR", m_debugger_temp).callimport().callexport().formatstr("%08X"); + // If the legacy POWER instructions exist, that implies MQ is used and should be shown + if (m_cap & PPCCAP_LEGACY_POWER) + { + state_add(PPC_MQ, "MQ", m_core->spr[SPR601_MQ]).formatstr("%08X"); + } state_add(PPC_LR, "LR", m_core->spr[SPR_LR]).formatstr("%08X"); state_add(PPC_CTR, "CTR", m_core->spr[SPR_CTR]).formatstr("%08X"); state_add(PPC_XER, "XER", m_debugger_temp).callimport().callexport().formatstr("%08X"); @@ -1220,7 +1231,7 @@ void ppc_device::device_reset() std::unique_ptr<util::disasm_interface> ppc_device::create_disassembler() { - return std::make_unique<powerpc_disassembler>(); + return std::make_unique<powerpc_disassembler>(powerpc_disassembler::I_POWERPC); } @@ -1296,8 +1307,6 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, bool debug uint32_t lower = m_core->spr[SPROEA_IBAT0U + 2*batnum + 1]; int privbit = ((intention & TR_USER) == 0) ? 3 : 2; -// printf("bat %d upper = %08x privbit %d\n", batnum, upper, privbit); - // is this pair valid? if (lower & 0x40) { @@ -1634,6 +1643,29 @@ void ppc_device::ppccom_execute_mfspr() } } + /* handle 601 specific SPRs (POWER holdovers) */ + if (m_flavor == PPC_MODEL_601) + { + switch (m_core->param0) + { + case SPR601_PWRDEC: + m_core->param1 = get_decrementer(); + return; + + case SPR601_RTCUR_PWR: + m_core->param1 = (total_cycles() - m_rtc_zero_cycles) / clock(); + return; + + case SPR601_RTCLR_PWR: + { + const uint64_t remainder = (total_cycles() - m_rtc_zero_cycles) % clock(); + const double seconds = remainder / clock(); // get fractional seconds + m_core->param1 = (uint64_t)(seconds * 1'000'000'000); // and convert to nanoseconds + } + return; + } + } + /* handle 602 SPRs */ if (m_flavor == PPC_MODEL_602) { // TODO: Which are read/write only? @@ -1777,6 +1809,21 @@ void ppc_device::ppccom_execute_mtspr() } } + /* handle 601 specific POWER-holdover SPRs */ + if (m_flavor == PPC_MODEL_601) + { + switch (m_core->param0) + { + case SPR601_MQ: + m_core->spr[m_core->param0] = m_core->param1; + return; + + case SPR601_RTCUW_PWR: + m_rtc_zero_cycles = total_cycles(); + break; + } + } + /* handle 602 SPRs */ if (m_flavor == PPC_MODEL_602) { |