diff options
Diffstat (limited to 'src/devices/cpu/powerpc/ppccom.cpp')
-rw-r--r-- | src/devices/cpu/powerpc/ppccom.cpp | 114 |
1 files changed, 69 insertions, 45 deletions
diff --git a/src/devices/cpu/powerpc/ppccom.cpp b/src/devices/cpu/powerpc/ppccom.cpp index f94240490d7..b0e4b583955 100644 --- a/src/devices/cpu/powerpc/ppccom.cpp +++ b/src/devices/cpu/powerpc/ppccom.cpp @@ -205,6 +205,8 @@ DEFINE_DEVICE_TYPE(MPC8240, mpc8240_device, "mpc8240", "IBM PowerPC MPC82 DEFINE_DEVICE_TYPE(PPC403GA, ppc403ga_device, "ppc403ga", "IBM PowerPC 403GA") DEFINE_DEVICE_TYPE(PPC403GCX, ppc403gcx_device, "ppc403gcx", "IBM PowerPC 403GCX") DEFINE_DEVICE_TYPE(PPC405GP, ppc405gp_device, "ppc405gp", "IBM PowerPC 405GP") +DEFINE_DEVICE_TYPE(PPC740, ppc740_device, "ppc740", "IBM PowerPC 740") +DEFINE_DEVICE_TYPE(PPC750, ppc750_device, "ppc750", "IBM PowerPC 750") ppc_device::ppc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int address_bits, int data_bits, powerpc_flavor flavor, uint32_t cap, uint32_t tb_divisor, address_map_constructor internal_map) @@ -212,6 +214,7 @@ ppc_device::ppc_device(const machine_config &mconfig, device_type type, const ch , device_vtlb_interface(mconfig, *this, AS_PROGRAM) , m_program_config("program", ENDIANNESS_BIG, data_bits, address_bits, 0, internal_map) , c_bus_frequency(0) + , c_serial_clock(0) , m_core(nullptr) , m_bus_freq_multiplier(1) , m_flavor(flavor) @@ -287,6 +290,16 @@ ppc604_device::ppc604_device(const machine_config &mconfig, const char *tag, dev { } +ppc740_device::ppc740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ppc_device(mconfig, PPC740, tag, owner, clock, 32, 64, PPC_MODEL_740, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_604_MMU | PPCCAP_750_TLB , 4, address_map_constructor()) +{ +} + +ppc750_device::ppc750_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ppc_device(mconfig, PPC750, tag, owner, clock, 32, 64, PPC_MODEL_750, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_604_MMU | PPCCAP_750_TLB, 4, address_map_constructor()) +{ +} + void ppc4xx_device::internal_ppc4xx(address_map &map) { map(0x40000000, 0x4000000f).rw(FUNC(ppc4xx_device::ppc4xx_spu_r), FUNC(ppc4xx_device::ppc4xx_spu_w)); @@ -333,9 +346,9 @@ device_memory_interface::space_config_vector ppc_device::memory_space_config() c static inline bool page_access_allowed(int transtype, uint8_t key, uint8_t protbits) { if (key == 0) - return (transtype == TRANSLATE_WRITE) ? (protbits != 3) : true; + return (transtype == device_memory_interface::TR_WRITE) ? (protbits != 3) : true; else - return (transtype == TRANSLATE_WRITE) ? (protbits == 2) : (protbits != 0); + return (transtype == device_memory_interface::TR_WRITE) ? (protbits == 2) : (protbits != 0); } @@ -718,6 +731,8 @@ void ppc_device::device_start() m_debugger_temp = 0; + m_serial_clock = 0; + m_cache_line_size = 32; m_cpu_clock = clock(); m_program = &space(AS_PROGRAM); @@ -752,24 +767,28 @@ void ppc_device::device_start() m_tb_divisor = (m_tb_divisor * clock() + m_system_clock / 2 - 1) / m_system_clock; + m_serial_clock = c_serial_clock != 0 ? c_serial_clock : 3'686'400; // TODO: get rid of this hard-coded magic number + if (m_serial_clock > m_system_clock / 2) + fatalerror("%s: PPC: serial clock (%d) must not be more than half of the system clock (%d)\n", tag(), m_serial_clock, m_system_clock); + /* allocate a timer for the compare interrupt */ if ((m_cap & PPCCAP_OEA) && (m_tb_divisor)) - m_decrementer_int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::decrementer_int_callback), this)); + m_decrementer_int_timer = timer_alloc(FUNC(ppc_device::decrementer_int_callback), this); /* and for the 4XX interrupts if needed */ if (m_cap & PPCCAP_4XX) { - m_fit_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_fit_callback), this)); - m_pit_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_pit_callback), this)); - m_spu.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_spu_callback), this)); + m_fit_timer = timer_alloc(FUNC(ppc_device::ppc4xx_fit_callback), this); + m_pit_timer = timer_alloc(FUNC(ppc_device::ppc4xx_pit_callback), this); + m_spu.timer = timer_alloc(FUNC(ppc_device::ppc4xx_spu_callback), this); } if (m_cap & PPCCAP_4XX) { - m_buffered_dma_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this)); - m_buffered_dma_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this)); - m_buffered_dma_timer[2] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this)); - m_buffered_dma_timer[3] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this)); + m_buffered_dma_timer[0] = timer_alloc(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this); + m_buffered_dma_timer[1] = timer_alloc(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this); + m_buffered_dma_timer[2] = timer_alloc(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this); + m_buffered_dma_timer[3] = timer_alloc(FUNC(ppc_device::ppc4xx_buffered_dma_callback), this); m_buffered_dma_rate[0] = 10000; m_buffered_dma_rate[1] = 10000; @@ -857,15 +876,15 @@ void ppc_device::device_start() for (int regnum = 0; regnum < 32; regnum++) { char buf[10]; - sprintf(buf, "r%d", regnum); + snprintf(buf, 10, "r%d", regnum); m_drcuml->symbol_add(&m_core->r[regnum], sizeof(m_core->r[regnum]), buf); - sprintf(buf, "fpr%d", regnum); + snprintf(buf, 10, "fpr%d", regnum); m_drcuml->symbol_add(&m_core->f[regnum], sizeof(m_core->f[regnum]), buf); } for (int regnum = 0; regnum < 8; regnum++) { char buf[10]; - sprintf(buf, "cr%d", regnum); + snprintf(buf, 10, "cr%d", regnum); m_drcuml->symbol_add(&m_core->cr[regnum], sizeof(m_core->cr[regnum]), buf); } m_drcuml->symbol_add(&m_core->xerso, sizeof(m_core->xerso), "xerso"); @@ -1150,7 +1169,7 @@ void ppc_device::device_reset() m_dec_zero_cycles = total_cycles(); if (m_tb_divisor) { - decrementer_int_callback(nullptr, 0); + decrementer_int_callback(0); } } @@ -1230,10 +1249,10 @@ void ppc_device::ppccom_dcstore_callback() filling -------------------------------------------------*/ -uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &address) +uint32_t ppc_device::ppccom_translate_address_internal(int intention, bool debug, offs_t &address) { - int transpriv = ((intention & TRANSLATE_USER_MASK) == 0); // 1 for supervisor, 0 for user - int transtype = intention & TRANSLATE_TYPE_MASK; + int transpriv = ((intention & TR_USER) == 0); // 1 for supervisor, 0 for user + int transtype = intention & TR_TYPE; offs_t hash, hashbase, hashmask; int batbase, batnum, hashnum; uint32_t segreg; @@ -1246,7 +1265,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad fatalerror("MMU enabled but not supported!\n"); /* only check if PE is enabled */ - if (transtype == TRANSLATE_WRITE && (m_core->msr & MSR4XX_PE)) + if (transtype == TR_WRITE && (m_core->msr & MSR4XX_PE)) { /* are we within one of the protection ranges? */ int inrange1 = ((address >> 12) >= (m_core->spr[SPR4XX_PBL1] >> 12) && (address >> 12) < (m_core->spr[SPR4XX_PBU1] >> 12)); @@ -1265,7 +1284,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad return 0x001; /* also no translation necessary if translation is disabled */ - if ((transtype == TRANSLATE_FETCH && (m_core->msr & MSROEA_IR) == 0) || (transtype != TRANSLATE_FETCH && (m_core->msr & MSROEA_DR) == 0)) + if ((transtype == TR_FETCH && (m_core->msr & MSROEA_IR) == 0) || (transtype != TR_FETCH && (m_core->msr & MSROEA_DR) == 0)) return 0x001; /* first scan the appropriate BAT */ @@ -1275,7 +1294,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad { uint32_t upper = m_core->spr[SPROEA_IBAT0U + 2*batnum + 0]; uint32_t lower = m_core->spr[SPROEA_IBAT0U + 2*batnum + 1]; - int privbit = ((intention & TRANSLATE_USER_MASK) == 0) ? 3 : 2; + int privbit = ((intention & TR_USER) == 0) ? 3 : 2; // printf("bat %d upper = %08x privbit %d\n", batnum, upper, privbit); @@ -1292,7 +1311,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad /* verify protection; if we fail, return false and indicate a protection violation */ if (!page_access_allowed(transtype, key, upper & 3)) { - return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0); + return DSISR_PROTECTED | ((transtype == TR_WRITE) ? DSISR_STORE : 0); } /* otherwise we're good */ @@ -1305,7 +1324,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad } else { - batbase = (transtype == TRANSLATE_FETCH) ? SPROEA_IBAT0U : SPROEA_DBAT0U; + batbase = (transtype == TR_FETCH) ? SPROEA_IBAT0U : SPROEA_DBAT0U; for (batnum = 0; batnum < 4; batnum++) { @@ -1324,7 +1343,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad /* verify protection; if we fail, return false and indicate a protection violation */ if (!page_access_allowed(transtype, 1, lower & 3)) { - return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0); + return DSISR_PROTECTED | ((transtype == TR_WRITE) ? DSISR_STORE : 0); } /* otherwise we're good */ @@ -1346,13 +1365,13 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad /* look up the segment register */ segreg = m_core->sr[address >> 28]; - if (transtype == TRANSLATE_FETCH && (segreg & 0x10000000)) - return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0); + if (transtype == TR_FETCH && (segreg & 0x10000000)) + return DSISR_PROTECTED | ((transtype == TR_WRITE) ? DSISR_STORE : 0); /* check for memory-forced I/O */ if (m_cap & PPCCAP_MFIOC) { - if ((transtype != TRANSLATE_FETCH) && ((segreg & 0x87f00000) == 0x87f00000)) + if ((transtype != TR_FETCH) && ((segreg & 0x87f00000) == 0x87f00000)) { address = ((segreg & 0xf)<<28) | (address & 0x0fffffff); return 1; @@ -1375,12 +1394,12 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad m_core->mmu603_cmp = 0x80000000 | ((segreg & 0xffffff) << 7) | (0 << 6) | ((address >> 22) & 0x3f); m_core->mmu603_hash[0] = hashbase | ((hash << 6) & hashmask); m_core->mmu603_hash[1] = hashbase | ((~hash << 6) & hashmask); - if ((entry & (VTLB_FLAG_FIXED | VTLB_FLAG_VALID)) == (VTLB_FLAG_FIXED | VTLB_FLAG_VALID)) + if ((entry & (FLAG_FIXED | FLAG_VALID)) == (FLAG_FIXED | FLAG_VALID)) { address = (entry & 0xfffff000) | (address & 0x00000fff); return 0x001; } - return DSISR_NOT_FOUND | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0); + return DSISR_NOT_FOUND | ((transtype == TR_WRITE) ? DSISR_STORE : 0); } /* loop twice over hashes */ @@ -1403,13 +1422,13 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad /* verify protection; if we fail, return false and indicate a protection violation */ if (!page_access_allowed(transtype, (segreg >> (29 + transpriv)) & 1, pteglower & 3)) - return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0); + return DSISR_PROTECTED | ((transtype == TR_WRITE) ? DSISR_STORE : 0); /* update page table bits */ - if (!(intention & TRANSLATE_DEBUG_MASK)) + if (!debug) { pteglower |= 0x100; - if (transtype == TRANSLATE_WRITE) + if (transtype == TR_WRITE) pteglower |= 0x080; ptegptr[BYTE_XOR_BE(ptenum * 2 + 1)] = pteglower; } @@ -1425,7 +1444,7 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad } /* we failed to find any match: not found */ - return DSISR_NOT_FOUND | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0); + return DSISR_NOT_FOUND | ((transtype == TR_WRITE) ? DSISR_STORE : 0); } @@ -1434,14 +1453,16 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, offs_t &ad from logical to physical -------------------------------------------------*/ -bool ppc_device::memory_translate(int spacenum, int intention, offs_t &address) +bool ppc_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) { + target_space = &space(spacenum); + /* only applies to the program address space */ if (spacenum != AS_PROGRAM) return true; /* translation is successful if the internal routine returns 0 or 1 */ - return (ppccom_translate_address_internal(intention, address) <= 1); + return (ppccom_translate_address_internal(intention, true, address) <= 1); } @@ -1451,7 +1472,10 @@ bool ppc_device::memory_translate(int spacenum, int intention, offs_t &address) void ppc_device::ppccom_tlb_fill() { - vtlb_fill(m_core->param0, m_core->param1); + offs_t address = m_core->param0; + if(ppccom_translate_address_internal(m_core->param1, false, address) > 1) + return; + vtlb_fill(m_core->param0, address, m_core->param1); } @@ -1482,14 +1506,14 @@ void ppc_device::ppccom_get_dsisr() if (m_core->param1 & 1) { - intent = TRANSLATE_WRITE; + intent = TR_WRITE; } else { - intent = TRANSLATE_READ; + intent = TR_READ; } - m_core->param1 = ppccom_translate_address_internal(intent, m_core->param0); + m_core->param1 = ppccom_translate_address_internal(intent, false, m_core->param0); } /*------------------------------------------------- @@ -1533,11 +1557,11 @@ void ppc_device::ppccom_execute_tlbl() entrynum = ((address >> 12) & 0x1f) | (machine().rand() & 0x20) | (isitlb ? 0x40 : 0); /* determine the flags */ - flags = VTLB_FLAG_VALID | VTLB_READ_ALLOWED | VTLB_FETCH_ALLOWED; + flags = FLAG_VALID | READ_ALLOWED | FETCH_ALLOWED; if (m_core->spr[SPR603_RPA] & 0x80) - flags |= VTLB_WRITE_ALLOWED; + flags |= WRITE_ALLOWED; if (isitlb) - flags |= VTLB_FETCH_ALLOWED; + flags |= FETCH_ALLOWED; /* load the entry */ vtlb_load(entrynum, 1, address, (m_core->spr[SPR603_RPA] & 0xfffff000) | flags); @@ -1834,9 +1858,9 @@ void ppc_device::ppccom_execute_mtspr() case SPR4XX_TCR: m_core->spr[SPR4XX_TCR] = m_core->param1 | (oldval & PPC4XX_TCR_WRC_MASK); if ((oldval ^ m_core->spr[SPR4XX_TCR]) & PPC4XX_TCR_FIE) - ppc4xx_fit_callback(nullptr, false); + ppc4xx_fit_callback(false); if ((oldval ^ m_core->spr[SPR4XX_TCR]) & PPC4XX_TCR_PIE) - ppc4xx_pit_callback(nullptr, false); + ppc4xx_pit_callback(false); return; /* timer status register */ @@ -1849,7 +1873,7 @@ void ppc_device::ppccom_execute_mtspr() case SPR4XX_PIT: m_core->spr[SPR4XX_PIT] = m_core->param1; m_pit_reload = m_core->param1; - ppc4xx_pit_callback(nullptr, false); + ppc4xx_pit_callback(false); return; /* timebase */ @@ -2684,7 +2708,7 @@ void ppc_device::ppc4xx_spu_timer_reset() /* if we're enabled, reset at the current baud rate */ if (enabled) { - attotime clockperiod = attotime::from_hz((m_dcr[DCR4XX_IOCR] & 0x02) ? 3686400 : 33333333); + attotime clockperiod = attotime::from_hz((m_dcr[DCR4XX_IOCR] & 0x02) ? m_serial_clock : m_system_clock); int divisor = ((m_spu.regs[SPU4XX_BAUD_DIVISOR_H] * 256 + m_spu.regs[SPU4XX_BAUD_DIVISOR_L]) & 0xfff) + 1; int bpc = 7 + ((m_spu.regs[SPU4XX_CONTROL] & 8) >> 3) + 1 + (m_spu.regs[SPU4XX_CONTROL] & 1); attotime charperiod = clockperiod * (divisor * 16 * bpc); |