summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/powerpc/ppccom.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/powerpc/ppccom.cpp')
-rw-r--r--src/devices/cpu/powerpc/ppccom.cpp249
1 files changed, 163 insertions, 86 deletions
diff --git a/src/devices/cpu/powerpc/ppccom.cpp b/src/devices/cpu/powerpc/ppccom.cpp
index 4a8a071f903..4e76a3efbb2 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,15 +214,23 @@ 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)
, m_cap(cap)
, m_tb_divisor(tb_divisor)
+ , m_spu(*this)
+ , m_dcr_read_func(*this)
+ , m_dcr_write_func(*this)
+ , m_dcstore_cb(*this)
+ , m_ext_dma_read_cb(*this)
+ , m_ext_dma_write_cb(*this)
, m_cache(CACHE_SIZE + sizeof(internal_ppc_state))
, m_drcuml(nullptr)
, m_drcfe(nullptr)
, m_drcoptions(0)
+ , m_dasm(powerpc_disassembler())
{
m_program_config.m_logaddr_width = 32;
m_program_config.m_page_shift = POWERPC_MIN_PAGE_SHIFT;
@@ -271,15 +281,31 @@ 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())
{
}
+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));
@@ -326,9 +352,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);
}
@@ -449,9 +475,9 @@ inline void ppc_device::set_decrementer(uint32_t newdec)
if (PRINTF_DECREMENTER)
{
uint64_t total = total_cycles();
- osd_printf_debug("set_decrementer: olddec=%08X newdec=%08X divisor=%d totalcyc=%08X%08X timer=%08X%08X\n",
+ osd_printf_debug("set_decrementer: olddec=%08X newdec=%08X divisor=%d totalcyc=%016X timer=%016X\n",
curdec, newdec, m_tb_divisor,
- (uint32_t)(total >> 32), (uint32_t)total, (uint32_t)(cycles_until_done >> 32), (uint32_t)cycles_until_done);
+ total, cycles_until_done);
}
m_dec_zero_cycles = total_cycles() + cycles_until_done;
@@ -485,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) );
}
@@ -694,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));
@@ -702,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;
@@ -711,58 +737,64 @@ 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);
if(m_cap & PPCCAP_4XX)
{
- auto cache = m_program->cache<2, 0, ENDIANNESS_BIG>();
- m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); };
- m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); };
+ m_program->cache(m_cache32);
+ m_pr32 = [this](offs_t address) -> u32 { return m_cache32.read_dword(address); };
+ m_prptr = [this](offs_t address) -> const void * { return m_cache32.read_ptr(address); };
}
else
{
- auto cache = m_program->cache<3, 0, ENDIANNESS_BIG>();
- m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); };
+ m_program->cache(m_cache64);
+ m_pr32 = [this](offs_t address) -> u32 { return m_cache64.read_dword(address); };
if(space_config()->m_endianness != ENDIANNESS_NATIVE)
- m_prptr = [cache](offs_t address) -> const void * {
- const u32 *ptr = static_cast<u32 *>(cache->read_ptr(address & ~7));
+ m_prptr = [this](offs_t address) -> const void * {
+ const u32 *ptr = static_cast<u32 *>(m_cache64.read_ptr(address & ~7));
if(!(address & 4))
ptr++;
return ptr;
};
else
- m_prptr = [cache](offs_t address) -> const void * {
- const u32 *ptr = static_cast<u32 *>(cache->read_ptr(address & ~7));
+ m_prptr = [this](offs_t address) -> const void * {
+ const u32 *ptr = static_cast<u32 *>(m_cache64.read_ptr(address & ~7));
if(address & 4)
ptr++;
return ptr;
};
}
m_system_clock = c_bus_frequency != 0 ? c_bus_frequency : clock();
- m_dcr_read_func = read32_delegate();
- m_dcr_write_func = write32_delegate();
+ m_dcr_read_func.set(nullptr);
+ m_dcr_write_func.set(nullptr);
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;
@@ -806,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");
@@ -836,7 +873,6 @@ void ppc_device::device_start()
state_add(STATE_GENPC, "GENPC", m_core->pc).noshow();
state_add(STATE_GENPCBASE, "CURPC", m_core->pc).noshow();
- state_add(STATE_GENSP, "GENSP", m_core->r[31]).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).noshow().formatstr("%1s");
set_icountptr(m_core->icount);
@@ -851,15 +887,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");
@@ -1144,7 +1180,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);
}
}
@@ -1195,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);
}
@@ -1208,7 +1244,7 @@ void ppc_device::ppccom_dcstore_callback()
{
if (!m_dcstore_cb.isnull())
{
- m_dcstore_cb(*m_program, m_core->param0, 0, 0xffffffff);
+ m_dcstore_cb(m_core->param0, 0);
}
}
@@ -1224,10 +1260,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;
@@ -1240,7 +1276,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));
@@ -1259,7 +1295,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 */
@@ -1269,9 +1305,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;
-
-// printf("bat %d upper = %08x privbit %d\n", batnum, upper, privbit);
+ int privbit = ((intention & TR_USER) == 0) ? 3 : 2;
// is this pair valid?
if (lower & 0x40)
@@ -1286,7 +1320,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 */
@@ -1299,7 +1333,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++)
{
@@ -1318,7 +1352,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 */
@@ -1340,13 +1374,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;
@@ -1369,12 +1403,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 */
@@ -1397,13 +1431,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;
}
@@ -1419,7 +1453,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);
}
@@ -1428,14 +1462,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);
}
@@ -1445,7 +1481,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);
}
@@ -1476,14 +1515,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);
}
/*-------------------------------------------------
@@ -1527,11 +1566,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);
@@ -1604,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?
@@ -1747,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)
{
@@ -1828,9 +1905,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 */
@@ -1843,7 +1920,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 */
@@ -1913,12 +1990,12 @@ void ppc_device::ppccom_execute_mfdcr()
/* default handling */
if (m_dcr_read_func.isnull()) {
osd_printf_debug("DCR %03X read\n", m_core->param0);
- if (m_core->param0 < ARRAY_LENGTH(m_dcr))
+ if (m_core->param0 < std::size(m_dcr))
m_core->param1 = m_dcr[m_core->param0];
else
m_core->param1 = 0;
} else {
- m_core->param1 = m_dcr_read_func(*m_program,m_core->param0,0xffffffff);
+ m_core->param1 = m_dcr_read_func(m_core->param0);
}
}
@@ -2005,10 +2082,10 @@ void ppc_device::ppccom_execute_mtdcr()
/* default handling */
if (m_dcr_write_func.isnull()) {
osd_printf_debug("DCR %03X write = %08X\n", m_core->param0, m_core->param1);
- if (m_core->param0 < ARRAY_LENGTH(m_dcr))
+ if (m_core->param0 < std::size(m_dcr))
m_dcr[m_core->param0] = m_core->param1;
} else {
- m_dcr_write_func(*m_program,m_core->param0,m_core->param1,0xffffffff);
+ m_dcr_write_func(m_core->param0,m_core->param1);
}
}
@@ -2093,7 +2170,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::decrementer_int_callback )
for detecting datacache stores with dcbst
-------------------------------------------------*/
-void ppc_device::ppc_set_dcstore_callback(write32_delegate callback)
+void ppc_device::ppc_set_dcstore_callback(write32sm_delegate callback)
{
m_dcstore_cb = callback;
}
@@ -2365,7 +2442,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_buffered_dma_callback )
{
uint8_t data = m_program->read_byte(dmaregs[DCR4XX_DMADA0]);
if (!m_ext_dma_write_cb[dmachan].isnull())
- (m_ext_dma_write_cb[dmachan])(*m_program, 1, data, 0xffffffff);
+ (m_ext_dma_write_cb[dmachan])(1, data);
dmaregs[DCR4XX_DMADA0] += destinc;
} while (!ppc4xx_dma_decrement_count(dmachan));
break;
@@ -2376,7 +2453,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_buffered_dma_callback )
{
uint16_t data = m_program->read_word(dmaregs[DCR4XX_DMADA0]);
if (!m_ext_dma_write_cb[dmachan].isnull())
- (m_ext_dma_write_cb[dmachan])(*m_program, 2, data, 0xffffffff);
+ (m_ext_dma_write_cb[dmachan])(2, data);
dmaregs[DCR4XX_DMADA0] += destinc;
} while (!ppc4xx_dma_decrement_count(dmachan));
break;
@@ -2387,7 +2464,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_buffered_dma_callback )
{
uint32_t data = m_program->read_dword(dmaregs[DCR4XX_DMADA0]);
if (!m_ext_dma_write_cb[dmachan].isnull())
- (m_ext_dma_write_cb[dmachan])(*m_program, 4, data, 0xffffffff);
+ (m_ext_dma_write_cb[dmachan])(4, data);
dmaregs[DCR4XX_DMADA0] += destinc;
} while (!ppc4xx_dma_decrement_count(dmachan));
break;
@@ -2656,7 +2733,7 @@ void ppc_device::ppc4xx_spu_rx_data(uint8_t data)
uint32_t new_rxin;
/* fail if we are going to overflow */
- new_rxin = (m_spu.rxin + 1) % ARRAY_LENGTH(m_spu.rxbuffer);
+ new_rxin = (m_spu.rxin + 1) % std::size(m_spu.rxbuffer);
if (new_rxin == m_spu.rxout)
fatalerror("ppc4xx_spu_rx_data: buffer overrun!\n");
@@ -2678,7 +2755,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);
@@ -2710,7 +2787,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_spu_callback )
{
/* if we have a transmit handler, send it that way */
if (!m_spu.tx_cb.isnull())
- (m_spu.tx_cb)(*m_program, 0, m_spu.txbuf, 0xff);
+ (m_spu.tx_cb)(m_spu.txbuf);
/* indicate that we have moved it to the shift register */
m_spu.regs[SPU4XX_LINE_STATUS] |= 0x04;
@@ -2735,7 +2812,7 @@ TIMER_CALLBACK_MEMBER( ppc_device::ppc4xx_spu_callback )
/* consume the byte and advance the out pointer */
rxbyte = m_spu.rxbuffer[m_spu.rxout];
- m_spu.rxout = (m_spu.rxout + 1) % ARRAY_LENGTH(m_spu.rxbuffer);
+ m_spu.rxout = (m_spu.rxout + 1) % std::size(m_spu.rxbuffer);
/* if we're not full, copy data to the buffer and update the line status */
if (!(m_spu.regs[SPU4XX_LINE_STATUS] & 0x80))
@@ -2766,7 +2843,7 @@ updateirq:
ppc4xx_spu_r - serial port read handler
-------------------------------------------------*/
-READ8_MEMBER( ppc4xx_device::ppc4xx_spu_r )
+uint8_t ppc4xx_device::ppc4xx_spu_r(offs_t offset)
{
uint8_t result = 0xff;
@@ -2778,7 +2855,7 @@ READ8_MEMBER( ppc4xx_device::ppc4xx_spu_r )
break;
default:
- if (offset < ARRAY_LENGTH(m_spu.regs))
+ if (offset < std::size(m_spu.regs))
result = m_spu.regs[offset];
break;
}
@@ -2792,7 +2869,7 @@ READ8_MEMBER( ppc4xx_device::ppc4xx_spu_r )
ppc4xx_spu_w - serial port write handler
-------------------------------------------------*/
-WRITE8_MEMBER( ppc4xx_device::ppc4xx_spu_w )
+void ppc4xx_device::ppc4xx_spu_w(offs_t offset, uint8_t data)
{
uint8_t oldstate, newstate;
@@ -2842,7 +2919,7 @@ WRITE8_MEMBER( ppc4xx_device::ppc4xx_spu_w )
break;
default:
- if (offset < ARRAY_LENGTH(m_spu.regs))
+ if (offset < std::size(m_spu.regs))
m_spu.regs[offset] = data;
break;
}
@@ -2855,7 +2932,7 @@ WRITE8_MEMBER( ppc4xx_device::ppc4xx_spu_w )
specific TX handler configuration
-------------------------------------------------*/
-void ppc4xx_device::ppc4xx_spu_set_tx_handler(write8_delegate callback)
+void ppc4xx_device::ppc4xx_spu_set_tx_handler(write8smo_delegate callback)
{
m_spu.tx_cb = callback;
}
@@ -2887,7 +2964,7 @@ void ppc4xx_device::ppc4xx_set_dma_read_handler(int channel, read32_delegate cal
specific external DMA write handler configuration
-------------------------------------------------*/
-void ppc4xx_device::ppc4xx_set_dma_write_handler(int channel, write32_delegate callback, int rate)
+void ppc4xx_device::ppc4xx_set_dma_write_handler(int channel, write32sm_delegate callback, int rate)
{
m_ext_dma_write_cb[channel] = callback;
m_buffered_dma_rate[channel] = rate;
@@ -2897,7 +2974,7 @@ void ppc4xx_device::ppc4xx_set_dma_write_handler(int channel, write32_delegate c
ppc4xx_set_dcr_read_handler
-------------------------------------------------*/
-void ppc4xx_device::ppc4xx_set_dcr_read_handler(read32_delegate dcr_read_func)
+void ppc4xx_device::ppc4xx_set_dcr_read_handler(read32sm_delegate dcr_read_func)
{
m_dcr_read_func = dcr_read_func;
@@ -2907,7 +2984,7 @@ void ppc4xx_device::ppc4xx_set_dcr_read_handler(read32_delegate dcr_read_func)
ppc4xx_set_dcr_write_handler
-------------------------------------------------*/
-void ppc4xx_device::ppc4xx_set_dcr_write_handler(write32_delegate dcr_write_func)
+void ppc4xx_device::ppc4xx_set_dcr_write_handler(write32sm_delegate dcr_write_func)
{
m_dcr_write_func = dcr_write_func;
}