mirror of
https://github.com/holub/mame
synced 2025-05-22 21:58:57 +03:00
680x0: '030 MMU now emulates translation cache; fixed misinterpreted MMU opcodes [R. Belmont]
This commit is contained in:
parent
ac0b9c471a
commit
6bc248ae49
@ -33,6 +33,10 @@ enum
|
|||||||
M68K_CPU_TYPE_SCC68070
|
M68K_CPU_TYPE_SCC68070
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* HMMU enable types for use with m68k_set_hmmu_enable() */
|
||||||
|
#define M68K_HMMU_DISABLE 0 /* no translation */
|
||||||
|
#define M68K_HMMU_ENABLE_II 1 /* Mac II style fixed translation */
|
||||||
|
#define M68K_HMMU_ENABLE_LC 2 /* Mac LC style fixed translation */
|
||||||
|
|
||||||
/* Special interrupt acknowledge values.
|
/* Special interrupt acknowledge values.
|
||||||
* Use these as special returns from the interrupt acknowledge callback
|
* Use these as special returns from the interrupt acknowledge callback
|
||||||
@ -79,6 +83,7 @@ DECLARE_LEGACY_CPU_DEVICE(M68010, m68010);
|
|||||||
DECLARE_LEGACY_CPU_DEVICE(M68EC020, m68ec020);
|
DECLARE_LEGACY_CPU_DEVICE(M68EC020, m68ec020);
|
||||||
DECLARE_LEGACY_CPU_DEVICE(M68020, m68020);
|
DECLARE_LEGACY_CPU_DEVICE(M68020, m68020);
|
||||||
DECLARE_LEGACY_CPU_DEVICE(M68020PMMU, m68020pmmu);
|
DECLARE_LEGACY_CPU_DEVICE(M68020PMMU, m68020pmmu);
|
||||||
|
DECLARE_LEGACY_CPU_DEVICE(M68020HMMU, m68020hmmu);
|
||||||
DECLARE_LEGACY_CPU_DEVICE(M68EC030, m68ec030);
|
DECLARE_LEGACY_CPU_DEVICE(M68EC030, m68ec030);
|
||||||
DECLARE_LEGACY_CPU_DEVICE(M68030, m68030);
|
DECLARE_LEGACY_CPU_DEVICE(M68030, m68030);
|
||||||
DECLARE_LEGACY_CPU_DEVICE(M68EC040, m68ec040);
|
DECLARE_LEGACY_CPU_DEVICE(M68EC040, m68ec040);
|
||||||
@ -89,6 +94,8 @@ DECLARE_LEGACY_CPU_DEVICE(SCC68070, scc68070);
|
|||||||
|
|
||||||
void m68k_set_encrypted_opcode_range(running_device *device, offs_t start, offs_t end);
|
void m68k_set_encrypted_opcode_range(running_device *device, offs_t start, offs_t end);
|
||||||
|
|
||||||
|
void m68k_set_hmmu_enable(running_device *device, int enable);
|
||||||
|
|
||||||
unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type);
|
unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type);
|
||||||
|
|
||||||
void m68k_set_reset_callback(running_device *device, m68k_reset_func callback);
|
void m68k_set_reset_callback(running_device *device, m68k_reset_func callback);
|
||||||
|
@ -571,6 +571,22 @@ static CPU_TRANSLATE( m68k )
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* translate logical to physical addresses for Apple HMMU */
|
||||||
|
static CPU_TRANSLATE( m68khmmu )
|
||||||
|
{
|
||||||
|
m68ki_cpu_core *m68k = get_safe_token(device);
|
||||||
|
|
||||||
|
/* only applies to the program address space and only does something if the MMU's enabled */
|
||||||
|
if (m68k)
|
||||||
|
{
|
||||||
|
if ((space == ADDRESS_SPACE_PROGRAM) && (m68k->hmmu_enabled))
|
||||||
|
{
|
||||||
|
*address = hmmu_translate_addr(m68k, *address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Execute some instructions until we use up cycles clock cycles */
|
/* Execute some instructions until we use up cycles clock cycles */
|
||||||
static CPU_EXECUTE( m68k )
|
static CPU_EXECUTE( m68k )
|
||||||
{
|
{
|
||||||
@ -633,6 +649,12 @@ static CPU_INIT( m68k )
|
|||||||
m68k->program = device->space(AS_PROGRAM);
|
m68k->program = device->space(AS_PROGRAM);
|
||||||
m68k->int_ack_callback = irqcallback;
|
m68k->int_ack_callback = irqcallback;
|
||||||
|
|
||||||
|
/* disable all MMUs */
|
||||||
|
m68k->has_pmmu = 0;
|
||||||
|
m68k->has_hmmu = 0;
|
||||||
|
m68k->pmmu_enabled = 0;
|
||||||
|
m68k->hmmu_enabled = 0;
|
||||||
|
|
||||||
/* The first call to this function initializes the opcode handler jump table */
|
/* The first call to this function initializes the opcode handler jump table */
|
||||||
if(!emulation_initialized)
|
if(!emulation_initialized)
|
||||||
{
|
{
|
||||||
@ -667,8 +689,9 @@ static CPU_RESET( m68k )
|
|||||||
{
|
{
|
||||||
m68ki_cpu_core *m68k = get_safe_token(device);
|
m68ki_cpu_core *m68k = get_safe_token(device);
|
||||||
|
|
||||||
/* Disable the PMMU on reset */
|
/* Disable the PMMU/HMMU on reset, if any */
|
||||||
m68k->pmmu_enabled = 0;
|
m68k->pmmu_enabled = 0;
|
||||||
|
m68k->hmmu_enabled = 0;
|
||||||
|
|
||||||
/* Clear all stop levels and eat up all remaining cycles */
|
/* Clear all stop levels and eat up all remaining cycles */
|
||||||
m68k->stopped = 0;
|
m68k->stopped = 0;
|
||||||
@ -702,6 +725,9 @@ static CPU_RESET( m68k )
|
|||||||
m68k->run_mode = RUN_MODE_NORMAL;
|
m68k->run_mode = RUN_MODE_NORMAL;
|
||||||
|
|
||||||
m68k->reset_cycles = m68k->cyc_exception[EXCEPTION_RESET];
|
m68k->reset_cycles = m68k->cyc_exception[EXCEPTION_RESET];
|
||||||
|
|
||||||
|
/* flush the MMU's cache */
|
||||||
|
pmmu_atc_flush(m68k);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CPU_DISASSEMBLE( m68k )
|
static CPU_DISASSEMBLE( m68k )
|
||||||
@ -940,6 +966,13 @@ void m68k_set_encrypted_opcode_range(running_device *device, offs_t start, offs_
|
|||||||
m68k->encrypted_end = end;
|
m68k->encrypted_end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void m68k_set_hmmu_enable(running_device *device, int enable)
|
||||||
|
{
|
||||||
|
m68ki_cpu_core *m68k = get_safe_token(device);
|
||||||
|
|
||||||
|
m68k->hmmu_enabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* 8-bit data memory interface
|
* 8-bit data memory interface
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -1143,6 +1176,132 @@ void m68k_memory_interface::init32mmu(address_space &space)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* interface for 32-bit data bus with PMMU (68EC020, 68020) */
|
||||||
|
UINT8 m68k_memory_interface::read_byte_32_hmmu(offs_t address)
|
||||||
|
{
|
||||||
|
if (m_cpustate->hmmu_enabled)
|
||||||
|
{
|
||||||
|
address = hmmu_translate_addr(m_cpustate, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_space->read_byte(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_memory_interface::write_byte_32_hmmu(offs_t address, UINT8 data)
|
||||||
|
{
|
||||||
|
if (m_cpustate->hmmu_enabled)
|
||||||
|
{
|
||||||
|
address = hmmu_translate_addr(m_cpustate, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_space->write_byte(address, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 m68k_memory_interface::read_immediate_16_hmmu(offs_t address)
|
||||||
|
{
|
||||||
|
if (m_cpustate->hmmu_enabled)
|
||||||
|
{
|
||||||
|
address = hmmu_translate_addr(m_cpustate, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_direct->read_decrypted_word((address) ^ m_cpustate->memory.opcode_xor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* potentially misaligned 16-bit reads with a 32-bit data bus (and 24-bit address bus) */
|
||||||
|
UINT16 m68k_memory_interface::readword_d32_hmmu(offs_t address)
|
||||||
|
{
|
||||||
|
UINT16 result;
|
||||||
|
|
||||||
|
if (m_cpustate->hmmu_enabled)
|
||||||
|
{
|
||||||
|
address = hmmu_translate_addr(m_cpustate, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(address & 1))
|
||||||
|
return m_space->read_word(address);
|
||||||
|
result = m_space->read_byte(address) << 8;
|
||||||
|
return result | m_space->read_byte(address + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* potentially misaligned 16-bit writes with a 32-bit data bus (and 24-bit address bus) */
|
||||||
|
void m68k_memory_interface::writeword_d32_hmmu(offs_t address, UINT16 data)
|
||||||
|
{
|
||||||
|
if (m_cpustate->hmmu_enabled)
|
||||||
|
{
|
||||||
|
address = hmmu_translate_addr(m_cpustate, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(address & 1))
|
||||||
|
{
|
||||||
|
m_space->write_word(address, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_space->write_byte(address, data >> 8);
|
||||||
|
m_space->write_byte(address + 1, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* potentially misaligned 32-bit reads with a 32-bit data bus (and 24-bit address bus) */
|
||||||
|
UINT32 m68k_memory_interface::readlong_d32_hmmu(offs_t address)
|
||||||
|
{
|
||||||
|
UINT32 result;
|
||||||
|
|
||||||
|
if (m_cpustate->hmmu_enabled)
|
||||||
|
{
|
||||||
|
address = hmmu_translate_addr(m_cpustate, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(address & 3))
|
||||||
|
return m_space->read_dword(address);
|
||||||
|
else if (!(address & 1))
|
||||||
|
{
|
||||||
|
result = m_space->read_word(address) << 16;
|
||||||
|
return result | m_space->read_word(address + 2);
|
||||||
|
}
|
||||||
|
result = m_space->read_byte(address) << 24;
|
||||||
|
result |= m_space->read_word(address + 1) << 8;
|
||||||
|
return result | m_space->read_byte(address + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* potentially misaligned 32-bit writes with a 32-bit data bus (and 24-bit address bus) */
|
||||||
|
void m68k_memory_interface::writelong_d32_hmmu(offs_t address, UINT32 data)
|
||||||
|
{
|
||||||
|
if (m_cpustate->hmmu_enabled)
|
||||||
|
{
|
||||||
|
address = hmmu_translate_addr(m_cpustate, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(address & 3))
|
||||||
|
{
|
||||||
|
m_space->write_dword(address, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!(address & 1))
|
||||||
|
{
|
||||||
|
m_space->write_word(address, data >> 16);
|
||||||
|
m_space->write_word(address + 2, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_space->write_byte(address, data >> 24);
|
||||||
|
m_space->write_word(address + 1, data >> 8);
|
||||||
|
m_space->write_byte(address + 3, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_memory_interface::init32hmmu(address_space &space)
|
||||||
|
{
|
||||||
|
m_space = &space;
|
||||||
|
m_direct = &space.direct();
|
||||||
|
m_cpustate = get_safe_token(&space.device());
|
||||||
|
opcode_xor = WORD_XOR_BE(0);
|
||||||
|
|
||||||
|
readimm16 = m68k_readimm16_delegate(m68k_readimm16_proto_delegate::create_member(m68k_memory_interface, read_immediate_16_hmmu), *this);
|
||||||
|
read8 = m68k_read8_delegate(m68k_read8_proto_delegate::create_member(m68k_memory_interface, read_byte_32_hmmu), *this);
|
||||||
|
read16 = m68k_read16_delegate(m68k_read16_proto_delegate::create_member(m68k_memory_interface, readword_d32_hmmu), *this);
|
||||||
|
read32 = m68k_read32_delegate(m68k_read32_proto_delegate::create_member(m68k_memory_interface, readlong_d32_hmmu), *this);
|
||||||
|
write8 = m68k_write8_delegate(m68k_write8_proto_delegate::create_member(m68k_memory_interface, write_byte_32_hmmu), *this);
|
||||||
|
write16 = m68k_write16_delegate(m68k_write16_proto_delegate::create_member(m68k_memory_interface, writeword_d32_hmmu), *this);
|
||||||
|
write32 = m68k_write32_delegate(m68k_write32_proto_delegate::create_member(m68k_memory_interface, writelong_d32_hmmu), *this);
|
||||||
|
}
|
||||||
|
|
||||||
void m68k_set_reset_callback(running_device *device, m68k_reset_func callback)
|
void m68k_set_reset_callback(running_device *device, m68k_reset_func callback)
|
||||||
{
|
{
|
||||||
m68ki_cpu_core *m68k = get_safe_token(device);
|
m68ki_cpu_core *m68k = get_safe_token(device);
|
||||||
@ -1253,6 +1412,7 @@ static CPU_INIT( m68000 )
|
|||||||
m68k->cyc_shift = 1;
|
m68k->cyc_shift = 1;
|
||||||
m68k->cyc_reset = 132;
|
m68k->cyc_reset = 132;
|
||||||
m68k->has_pmmu = 0;
|
m68k->has_pmmu = 0;
|
||||||
|
m68k->has_hmmu = 0;
|
||||||
|
|
||||||
define_state(device);
|
define_state(device);
|
||||||
}
|
}
|
||||||
@ -1403,7 +1563,6 @@ static CPU_INIT( m68020 )
|
|||||||
m68k->cyc_movem_l = 2;
|
m68k->cyc_movem_l = 2;
|
||||||
m68k->cyc_shift = 0;
|
m68k->cyc_shift = 0;
|
||||||
m68k->cyc_reset = 518;
|
m68k->cyc_reset = 518;
|
||||||
m68k->has_pmmu = 0;
|
|
||||||
|
|
||||||
define_state(device);
|
define_state(device);
|
||||||
}
|
}
|
||||||
@ -1459,6 +1618,36 @@ CPU_GET_INFO( m68020pmmu )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 68020 with Apple HMMU
|
||||||
|
static CPU_INIT( m68020hmmu )
|
||||||
|
{
|
||||||
|
m68ki_cpu_core *m68k = get_safe_token(device);
|
||||||
|
|
||||||
|
CPU_INIT_CALL(m68020);
|
||||||
|
|
||||||
|
m68k->has_hmmu = 1;
|
||||||
|
// hack alert: we use placement new to ensure we are properly initialized
|
||||||
|
// because we live in the device state which is allocated as bytes
|
||||||
|
// remove me when we have a real C++ device
|
||||||
|
new(&m68k->memory) m68k_memory_interface;
|
||||||
|
m68k->memory.init32mmu(*m68k->program);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU_GET_INFO( m68020hmmu )
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
/* --- the following bits of info are returned as pointers to data or functions --- */
|
||||||
|
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68020hmmu); break;
|
||||||
|
case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(m68khmmu); break;
|
||||||
|
|
||||||
|
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||||
|
case DEVINFO_STR_NAME: strcpy(info->s, "68020, Apple HMMU"); break;
|
||||||
|
|
||||||
|
default: CPU_GET_INFO_CALL(m68020); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* M680EC20 section
|
* M680EC20 section
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -1803,6 +1992,7 @@ DEFINE_LEGACY_CPU_DEVICE(M68010, m68010);
|
|||||||
DEFINE_LEGACY_CPU_DEVICE(M68EC020, m68ec020);
|
DEFINE_LEGACY_CPU_DEVICE(M68EC020, m68ec020);
|
||||||
DEFINE_LEGACY_CPU_DEVICE(M68020, m68020);
|
DEFINE_LEGACY_CPU_DEVICE(M68020, m68020);
|
||||||
DEFINE_LEGACY_CPU_DEVICE(M68020PMMU, m68020pmmu);
|
DEFINE_LEGACY_CPU_DEVICE(M68020PMMU, m68020pmmu);
|
||||||
|
DEFINE_LEGACY_CPU_DEVICE(M68020HMMU, m68020hmmu);
|
||||||
DEFINE_LEGACY_CPU_DEVICE(M68EC030, m68ec030);
|
DEFINE_LEGACY_CPU_DEVICE(M68EC030, m68ec030);
|
||||||
DEFINE_LEGACY_CPU_DEVICE(M68030, m68030);
|
DEFINE_LEGACY_CPU_DEVICE(M68030, m68030);
|
||||||
DEFINE_LEGACY_CPU_DEVICE(M68EC040, m68ec040);
|
DEFINE_LEGACY_CPU_DEVICE(M68EC040, m68ec040);
|
||||||
|
@ -100,6 +100,8 @@ typedef struct _m68ki_cpu_core m68ki_cpu_core;
|
|||||||
#define RUN_MODE_NORMAL 0
|
#define RUN_MODE_NORMAL 0
|
||||||
#define RUN_MODE_BERR_AERR_RESET 1
|
#define RUN_MODE_BERR_AERR_RESET 1
|
||||||
|
|
||||||
|
/* MMU constants */
|
||||||
|
#define MMU_ATC_ENTRIES (22) // 68851 has 64, 030 has 22
|
||||||
|
|
||||||
/* ======================================================================== */
|
/* ======================================================================== */
|
||||||
/* ================================ MACROS ================================ */
|
/* ================================ MACROS ================================ */
|
||||||
@ -558,6 +560,7 @@ public:
|
|||||||
void init16(address_space &space);
|
void init16(address_space &space);
|
||||||
void init32(address_space &space);
|
void init32(address_space &space);
|
||||||
void init32mmu(address_space &space);
|
void init32mmu(address_space &space);
|
||||||
|
void init32hmmu(address_space &space);
|
||||||
|
|
||||||
offs_t opcode_xor; // Address Calculation
|
offs_t opcode_xor; // Address Calculation
|
||||||
m68k_readimm16_delegate readimm16; // Immediate read 16 bit
|
m68k_readimm16_delegate readimm16; // Immediate read 16 bit
|
||||||
@ -581,6 +584,14 @@ private:
|
|||||||
UINT32 readlong_d32_mmu(offs_t address);
|
UINT32 readlong_d32_mmu(offs_t address);
|
||||||
void writelong_d32_mmu(offs_t address, UINT32 data);
|
void writelong_d32_mmu(offs_t address, UINT32 data);
|
||||||
|
|
||||||
|
UINT8 read_byte_32_hmmu(offs_t address);
|
||||||
|
void write_byte_32_hmmu(offs_t address, UINT8 data);
|
||||||
|
UINT16 read_immediate_16_hmmu(offs_t address);
|
||||||
|
UINT16 readword_d32_hmmu(offs_t address);
|
||||||
|
void writeword_d32_hmmu(offs_t address, UINT16 data);
|
||||||
|
UINT32 readlong_d32_hmmu(offs_t address);
|
||||||
|
void writelong_d32_hmmu(offs_t address, UINT32 data);
|
||||||
|
|
||||||
address_space *m_space;
|
address_space *m_space;
|
||||||
direct_read_data *m_direct;
|
direct_read_data *m_direct;
|
||||||
m68ki_cpu_core *m_cpustate;
|
m68ki_cpu_core *m_cpustate;
|
||||||
@ -622,7 +633,9 @@ struct _m68ki_cpu_core
|
|||||||
UINT32 instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
|
UINT32 instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
|
||||||
UINT32 run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
|
UINT32 run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
|
||||||
int has_pmmu; /* Indicates if a PMMU available (yes on 030, 040, no on EC030) */
|
int has_pmmu; /* Indicates if a PMMU available (yes on 030, 040, no on EC030) */
|
||||||
|
int has_hmmu; /* Indicates if an Apple HMMU is available in place of the 68851 (020 only) */
|
||||||
int pmmu_enabled; /* Indicates if the PMMU is enabled */
|
int pmmu_enabled; /* Indicates if the PMMU is enabled */
|
||||||
|
int hmmu_enabled; /* Indicates if the HMMU is enabled */
|
||||||
int fpu_just_reset; /* Indicates the FPU was just reset */
|
int fpu_just_reset; /* Indicates the FPU was just reset */
|
||||||
|
|
||||||
/* Clocks required for instructions / exceptions */
|
/* Clocks required for instructions / exceptions */
|
||||||
@ -683,6 +696,9 @@ struct _m68ki_cpu_core
|
|||||||
UINT32 mmu_srp_aptr, mmu_srp_limit;
|
UINT32 mmu_srp_aptr, mmu_srp_limit;
|
||||||
UINT32 mmu_tc;
|
UINT32 mmu_tc;
|
||||||
UINT16 mmu_sr;
|
UINT16 mmu_sr;
|
||||||
|
UINT32 mmu_atc_tag[MMU_ATC_ENTRIES], mmu_atc_data[MMU_ATC_ENTRIES];
|
||||||
|
UINT32 mmu_atc_rr;
|
||||||
|
UINT32 mmu_tt0, mmu_tt1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
m68kmmu.h - PMMU implementation for 68851/68030/68040
|
m68kmmu.h - PMMU implementation for 68851/68030/68040
|
||||||
|
HMMU implementation for 68020 (II and LC variants)
|
||||||
|
|
||||||
By R. Belmont
|
By R. Belmont
|
||||||
|
|
||||||
@ -7,6 +8,128 @@
|
|||||||
Visit http://mamedev.org for licensing and usage restrictions.
|
Visit http://mamedev.org for licensing and usage restrictions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* decodes the effective address */
|
||||||
|
static UINT32 DECODE_EA_32(m68ki_cpu_core *m68k, int ea)
|
||||||
|
{
|
||||||
|
int mode = (ea >> 3) & 0x7;
|
||||||
|
int reg = (ea & 0x7);
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case 2: // (An)
|
||||||
|
{
|
||||||
|
return REG_A[reg];
|
||||||
|
}
|
||||||
|
case 3: // (An)+
|
||||||
|
{
|
||||||
|
UINT32 ea = EA_AY_PI_32(m68k);
|
||||||
|
return ea;
|
||||||
|
}
|
||||||
|
case 5: // (d16, An)
|
||||||
|
{
|
||||||
|
UINT32 ea = EA_AY_DI_32(m68k);
|
||||||
|
return ea;
|
||||||
|
}
|
||||||
|
case 6: // (An) + (Xn) + d8
|
||||||
|
{
|
||||||
|
UINT32 ea = EA_AY_IX_32(m68k);
|
||||||
|
return ea;
|
||||||
|
}
|
||||||
|
case 7:
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case 0: // (xxx).W
|
||||||
|
{
|
||||||
|
UINT32 ea = (UINT32)OPER_I_16(m68k);
|
||||||
|
return ea;
|
||||||
|
}
|
||||||
|
case 1: // (xxx).L
|
||||||
|
{
|
||||||
|
UINT32 d1 = OPER_I_16(m68k);
|
||||||
|
UINT32 d2 = OPER_I_16(m68k);
|
||||||
|
UINT32 ea = (d1 << 16) | d2;
|
||||||
|
return ea;
|
||||||
|
}
|
||||||
|
case 2: // (d16, PC)
|
||||||
|
{
|
||||||
|
UINT32 ea = EA_PCDI_32(m68k);
|
||||||
|
return ea;
|
||||||
|
}
|
||||||
|
default: fatalerror("m68k: DECODE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: fatalerror("m68k: DECODE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pmmu_atc_add: adds this address to the ATC
|
||||||
|
*/
|
||||||
|
void pmmu_atc_add(m68ki_cpu_core *m68k, UINT32 logical, UINT32 physical)
|
||||||
|
{
|
||||||
|
int i, found, curfc;
|
||||||
|
|
||||||
|
curfc = (m68ki_get_sr(m68k) & 0x2000) ? 4 : 0;
|
||||||
|
curfc |= 1; // program vs. data space is not implemented
|
||||||
|
|
||||||
|
// first see if this is already in the cache
|
||||||
|
for (i = 0; i < MMU_ATC_ENTRIES; i++)
|
||||||
|
{
|
||||||
|
// if tag bits and function code match, don't add
|
||||||
|
if (((m68k->mmu_atc_tag[i] & 0xffffff) == (logical>>8)) && (((m68k->mmu_atc_tag[i]>>24) & 7) == curfc))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find an open entry
|
||||||
|
found = -1;
|
||||||
|
for (i = 0; i < MMU_ATC_ENTRIES; i++)
|
||||||
|
{
|
||||||
|
if (!(m68k->mmu_atc_tag[i] & 0x80000000))
|
||||||
|
{
|
||||||
|
found = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// did we find an entry? steal one by round-robin then
|
||||||
|
if (found == -1)
|
||||||
|
{
|
||||||
|
found = m68k->mmu_atc_rr++;
|
||||||
|
|
||||||
|
if (m68k->mmu_atc_rr >= MMU_ATC_ENTRIES)
|
||||||
|
{
|
||||||
|
m68k->mmu_atc_rr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the entry
|
||||||
|
// logerror("ATC[%d] add: log %08x -> phys %08x\n", found, logical, physical);
|
||||||
|
m68k->mmu_atc_tag[found] = (logical>>8) | (curfc<<24) | 0x80000000;
|
||||||
|
m68k->mmu_atc_data[found] = (physical>>8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pmmu_atc_flush: flush entire ATC
|
||||||
|
|
||||||
|
7fff0003 001ffd10 80f05750 is what should load
|
||||||
|
*/
|
||||||
|
void pmmu_atc_flush(m68ki_cpu_core *m68k)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MMU_ATC_ENTRIES; i++)
|
||||||
|
{
|
||||||
|
m68k->mmu_atc_tag[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m68k->mmu_atc_rr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pmmu_translate_addr: perform 68851/68030-style PMMU address translation
|
pmmu_translate_addr: perform 68851/68030-style PMMU address translation
|
||||||
*/
|
*/
|
||||||
@ -15,10 +138,29 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
|||||||
UINT32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0, tcmode = 0;
|
UINT32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0, tcmode = 0;
|
||||||
UINT32 root_aptr, root_limit, tofs, is, abits, bbits, cbits;
|
UINT32 root_aptr, root_limit, tofs, is, abits, bbits, cbits;
|
||||||
UINT32 resolved, tptr, shift;
|
UINT32 resolved, tptr, shift;
|
||||||
|
int curfc, i;
|
||||||
|
// int verbose = 0;
|
||||||
|
|
||||||
resolved = 0;
|
resolved = 0;
|
||||||
addr_out = addr_in;
|
addr_out = addr_in;
|
||||||
|
|
||||||
|
curfc = (m68ki_get_sr(m68k) & 0x2000) ? 4 : 0;
|
||||||
|
curfc |= 1; // program vs. data space is not implemented
|
||||||
|
|
||||||
|
// first see if this is already in the ATC
|
||||||
|
for (i = 0; i < MMU_ATC_ENTRIES; i++)
|
||||||
|
{
|
||||||
|
// if tag bits and function code match, we've got it
|
||||||
|
if (((m68k->mmu_atc_tag[i] & 0xffffff) == (addr_in>>8)) && (((m68k->mmu_atc_tag[i]>>24) & 7) == curfc))
|
||||||
|
{
|
||||||
|
addr_out = (m68k->mmu_atc_data[i]<<8) | (addr_in & 0xff);
|
||||||
|
// logerror("ATC[%d] hit: log %08x -> phys %08x\n", i, addr_in, addr_out);
|
||||||
|
return addr_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (addr_in == 0x5fa04c) verbose = 1;
|
||||||
|
|
||||||
// if SRP is enabled and we're in supervisor mode, use it
|
// if SRP is enabled and we're in supervisor mode, use it
|
||||||
if ((m68k->mmu_tc & 0x02000000) && (m68ki_get_sr(m68k) & 0x2000))
|
if ((m68k->mmu_tc & 0x02000000) && (m68ki_get_sr(m68k) & 0x2000))
|
||||||
{
|
{
|
||||||
@ -37,7 +179,7 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
|||||||
bbits = (m68k->mmu_tc>>8)&0xf;
|
bbits = (m68k->mmu_tc>>8)&0xf;
|
||||||
cbits = (m68k->mmu_tc>>4)&0xf;
|
cbits = (m68k->mmu_tc>>4)&0xf;
|
||||||
|
|
||||||
// logerror("PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68k->mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits);
|
//logerror("PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68k->mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits);
|
||||||
|
|
||||||
// get table A offset
|
// get table A offset
|
||||||
tofs = (addr_in<<is)>>(32-abits);
|
tofs = (addr_in<<is)>>(32-abits);
|
||||||
@ -47,24 +189,26 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
|||||||
{
|
{
|
||||||
case 0: // invalid, should cause MMU exception
|
case 0: // invalid, should cause MMU exception
|
||||||
case 1: // page descriptor, should cause direct mapping
|
case 1: // page descriptor, should cause direct mapping
|
||||||
fatalerror("680x0 PMMU: Unhandled root mode\n");
|
logerror("680x0 PMMU: Unhandled root mode %d, not translating (addr_in %x)\n", root_limit & 3, addr_in);
|
||||||
|
logerror(" : aptr %08x limit %08x\n", root_aptr, root_limit);
|
||||||
|
return addr_in;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // valid 4 byte descriptors
|
case 2: // valid 4 byte descriptors
|
||||||
tofs *= 4;
|
tofs *= 4;
|
||||||
// logerror("PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc));
|
// if (verbose) logerror("PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc));
|
||||||
tbl_entry = m68k->program->read_dword(tofs + (root_aptr & 0xfffffffc));
|
tbl_entry = m68k->program->read_dword(tofs + (root_aptr & 0xfffffffc));
|
||||||
tamode = tbl_entry & 3;
|
tamode = tbl_entry & 3;
|
||||||
// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs);
|
// if (verbose) logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // valid 8 byte descriptors
|
case 3: // valid 8 byte descriptors
|
||||||
tofs *= 8;
|
tofs *= 8;
|
||||||
// logerror("PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc));
|
// if (verbose) logerror("PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc));
|
||||||
tbl_entry2 = m68k->program->read_dword(tofs + (root_aptr & 0xfffffffc));
|
tbl_entry2 = m68k->program->read_dword(tofs + (root_aptr & 0xfffffffc));
|
||||||
tbl_entry = m68k->program->read_dword(tofs + (root_aptr & 0xfffffffc)+4);
|
tbl_entry = m68k->program->read_dword(tofs + (root_aptr & 0xfffffffc)+4);
|
||||||
tamode = tbl_entry2 & 3;
|
tamode = tbl_entry2 & 3;
|
||||||
// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
|
// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,24 +220,24 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
|||||||
switch (tamode)
|
switch (tamode)
|
||||||
{
|
{
|
||||||
case 0: // invalid, should cause MMU exception
|
case 0: // invalid, should cause MMU exception
|
||||||
fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in);
|
fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x PC %x)\n", tamode, addr_in, m68k->pc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // 4-byte table B descriptor
|
case 2: // 4-byte table B descriptor
|
||||||
tofs *= 4;
|
tofs *= 4;
|
||||||
// logerror("PMMU: reading table B entry at %08x\n", tofs + tptr);
|
// if (verbose) logerror("PMMU: reading table B entry at %08x\n", tofs + tptr);
|
||||||
tbl_entry = m68k->program->read_dword(tofs + tptr);
|
tbl_entry = m68k->program->read_dword(tofs + tptr);
|
||||||
tbmode = tbl_entry & 3;
|
tbmode = tbl_entry & 3;
|
||||||
// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
|
// if (verbose) logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // 8-byte table B descriptor
|
case 3: // 8-byte table B descriptor
|
||||||
tofs *= 8;
|
tofs *= 8;
|
||||||
// logerror("PMMU: reading table B entries at %08x\n", tofs + tptr);
|
// if (verbose) logerror("PMMU: reading table B entries at %08x\n", tofs + tptr);
|
||||||
tbl_entry2 = m68k->program->read_dword(tofs + tptr);
|
tbl_entry2 = m68k->program->read_dword(tofs + tptr);
|
||||||
tbl_entry = m68k->program->read_dword(tofs + tptr + 4);
|
tbl_entry = m68k->program->read_dword(tofs + tptr + 4);
|
||||||
tbmode = tbl_entry2 & 3;
|
tbmode = tbl_entry2 & 3;
|
||||||
// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
|
// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // early termination descriptor
|
case 1: // early termination descriptor
|
||||||
@ -120,19 +264,19 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
|||||||
|
|
||||||
case 2: // 4-byte table C descriptor
|
case 2: // 4-byte table C descriptor
|
||||||
tofs *= 4;
|
tofs *= 4;
|
||||||
// logerror("PMMU: reading table C entry at %08x\n", tofs + tptr);
|
// if (verbose) logerror("PMMU: reading table C entry at %08x\n", tofs + tptr);
|
||||||
tbl_entry = m68k->program->read_dword(tofs + tptr);
|
tbl_entry = m68k->program->read_dword(tofs + tptr);
|
||||||
tcmode = tbl_entry & 3;
|
tcmode = tbl_entry & 3;
|
||||||
// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
|
// if (verbose) logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // 8-byte table C descriptor
|
case 3: // 8-byte table C descriptor
|
||||||
tofs *= 8;
|
tofs *= 8;
|
||||||
// logerror("PMMU: reading table C entries at %08x\n", tofs + tptr);
|
// if (verbose) logerror("PMMU: reading table C entries at %08x\n", tofs + tptr);
|
||||||
tbl_entry2 = m68k->program->read_dword(tofs + tptr);
|
tbl_entry2 = m68k->program->read_dword(tofs + tptr);
|
||||||
tbl_entry = m68k->program->read_dword(tofs + tptr + 4);
|
tbl_entry = m68k->program->read_dword(tofs + tptr + 4);
|
||||||
tcmode = tbl_entry2 & 3;
|
tcmode = tbl_entry2 & 3;
|
||||||
// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
|
// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // termination descriptor
|
case 1: // termination descriptor
|
||||||
@ -150,9 +294,9 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
|||||||
switch (tcmode)
|
switch (tcmode)
|
||||||
{
|
{
|
||||||
case 0: // invalid, should cause MMU exception
|
case 0: // invalid, should cause MMU exception
|
||||||
case 2: // 4-byte ??? descriptor
|
case 2: // 4-byte table D descriptor
|
||||||
case 3: // 8-byte ??? descriptor
|
case 3: // 8-byte table D descriptor
|
||||||
fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, m68k->pc);
|
fatalerror("680x0 PMMU: Unhandled Table C mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, m68k->pc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // termination descriptor
|
case 1: // termination descriptor
|
||||||
@ -165,8 +309,9 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pmmu_atc_add(m68k, addr_in, addr_out);
|
||||||
|
|
||||||
// logerror("PMMU: [%08x] => [%08x]\n", addr_in, addr_out);
|
//logerror("PMMU: [%08x] => [%08x]\n", addr_in, addr_out);
|
||||||
|
|
||||||
return addr_out;
|
return addr_out;
|
||||||
}
|
}
|
||||||
@ -202,17 +347,28 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
|
|||||||
|
|
||||||
if ((modes & 0xfde0) == 0x2000) // PLOAD
|
if ((modes & 0xfde0) == 0x2000) // PLOAD
|
||||||
{
|
{
|
||||||
logerror("680x0: unhandled PLOAD\n");
|
UINT32 ltmp = DECODE_EA_32(m68k, ea);
|
||||||
|
UINT32 ptmp;
|
||||||
|
|
||||||
|
ptmp = ltmp;
|
||||||
|
if (m68k->pmmu_enabled)
|
||||||
|
{
|
||||||
|
ptmp = pmmu_translate_addr(m68k, ltmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// logerror("680x0: PLOADing ATC with logical %08x => phys %08x\n", ltmp, ptmp);
|
||||||
|
|
||||||
|
pmmu_atc_add(m68k, ltmp, ptmp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ((modes & 0xe200) == 0x2000) // PFLUSH
|
else if ((modes & 0xe200) == 0x2000) // PFLUSH
|
||||||
{
|
{
|
||||||
logerror("680x0: unhandled PFLUSH PC=%x\n", m68k->pc);
|
pmmu_atc_flush(m68k);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (modes == 0xa000) // PFLUSHR
|
else if (modes == 0xa000) // PFLUSHR
|
||||||
{
|
{
|
||||||
logerror("680x0: unhandled PFLUSHR\n");
|
pmmu_atc_flush(m68k);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (modes == 0x2800) // PVALID (FORMAT 1)
|
else if (modes == 0x2800) // PVALID (FORMAT 1)
|
||||||
@ -257,37 +413,86 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // top 3 bits of modes: 010 for this, 011 for status, 000 for transparent translation regs
|
||||||
{
|
{
|
||||||
switch ((modes>>10) & 7)
|
switch ((modes>>13) & 7)
|
||||||
{
|
{
|
||||||
case 0: // translation control register
|
case 0:
|
||||||
m68k->mmu_tc = READ_EA_32(m68k, ea);
|
{
|
||||||
|
UINT32 temp = READ_EA_32(m68k, ea);
|
||||||
|
|
||||||
if (m68k->mmu_tc & 0x80000000)
|
if (((modes>>10) & 7) == 2)
|
||||||
{
|
{
|
||||||
m68k->pmmu_enabled = 1;
|
m68k->mmu_tt0 = temp;
|
||||||
}
|
}
|
||||||
else
|
else if (((modes>>10) & 7) == 3)
|
||||||
{
|
{
|
||||||
m68k->pmmu_enabled = 0;
|
m68k->mmu_tt1 = temp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // supervisor root pointer
|
case 1:
|
||||||
temp64 = READ_EA_64(m68k, ea);
|
logerror("680x0: unknown PMOVE case 1, PC %x\n", m68k->pc);
|
||||||
m68k->mmu_srp_limit = (temp64>>32) & 0xffffffff;
|
|
||||||
m68k->mmu_srp_aptr = temp64 & 0xffffffff;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // CPU root pointer
|
case 2:
|
||||||
temp64 = READ_EA_64(m68k, ea);
|
switch ((modes>>10) & 7)
|
||||||
m68k->mmu_crp_limit = (temp64>>32) & 0xffffffff;
|
{
|
||||||
m68k->mmu_crp_aptr = temp64 & 0xffffffff;
|
case 0: // translation control register
|
||||||
|
m68k->mmu_tc = READ_EA_32(m68k, ea);
|
||||||
|
// logerror("PMMU: TC = %08x\n", m68k->mmu_tc);
|
||||||
|
|
||||||
|
if (m68k->mmu_tc & 0x80000000)
|
||||||
|
{
|
||||||
|
m68k->pmmu_enabled = 1;
|
||||||
|
// logerror("PMMU enabled\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m68k->pmmu_enabled = 0;
|
||||||
|
// logerror("PMMU disabled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(modes & 0x100)) // flush ATC on moves to TC, SRP, CRP with FD bit clear
|
||||||
|
{
|
||||||
|
pmmu_atc_flush(m68k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // supervisor root pointer
|
||||||
|
temp64 = READ_EA_64(m68k, ea);
|
||||||
|
m68k->mmu_srp_limit = (temp64>>32) & 0xffffffff;
|
||||||
|
m68k->mmu_srp_aptr = temp64 & 0xffffffff;
|
||||||
|
// logerror("PMMU: SRP limit = %08x aptr = %08x\n", m68k->mmu_srp_limit, m68k->mmu_srp_aptr);
|
||||||
|
if (!(modes & 0x100))
|
||||||
|
{
|
||||||
|
pmmu_atc_flush(m68k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // CPU root pointer
|
||||||
|
temp64 = READ_EA_64(m68k, ea);
|
||||||
|
m68k->mmu_crp_limit = (temp64>>32) & 0xffffffff;
|
||||||
|
m68k->mmu_crp_aptr = temp64 & 0xffffffff;
|
||||||
|
// logerror("PMMU: CRP limit = %08x aptr = %08x\n", m68k->mmu_crp_limit, m68k->mmu_crp_aptr);
|
||||||
|
if (!(modes & 0x100))
|
||||||
|
{
|
||||||
|
pmmu_atc_flush(m68k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logerror("680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case 3: // MMU status
|
||||||
logerror("680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
|
{
|
||||||
|
UINT32 temp = READ_EA_32(m68k, ea);
|
||||||
|
logerror("680x0: unsupported PMOVE %x to MMU status, PC %x\n", temp, m68k->pc);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,6 +512,7 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
|
|||||||
default:
|
default:
|
||||||
logerror("680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, m68k->pc);
|
logerror("680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, m68k->pc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -318,3 +524,34 @@ void m68881_mmu_ops(m68ki_cpu_core *m68k)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Apple HMMU translation is much simpler */
|
||||||
|
INLINE UINT32 hmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
||||||
|
{
|
||||||
|
UINT32 addr_out;
|
||||||
|
|
||||||
|
addr_out = addr_in;
|
||||||
|
|
||||||
|
// check if LC mode is enabled
|
||||||
|
if (m68k->hmmu_enabled == M68K_HMMU_ENABLE_LC)
|
||||||
|
{
|
||||||
|
addr_in &= 0xffffff;
|
||||||
|
addr_out &= 0xffffff;
|
||||||
|
|
||||||
|
if ((addr_in >= 0xa00000) && (addr_in <= 0xdfffff))
|
||||||
|
{
|
||||||
|
addr_out |= 0x40000000;
|
||||||
|
}
|
||||||
|
if ((addr_in >= 0xe00000) && (addr_in <= 0xefffff))
|
||||||
|
{
|
||||||
|
addr_out &= 0xfffff;
|
||||||
|
addr_out |= 0xfe000000;
|
||||||
|
}
|
||||||
|
else if (addr_in >= 0xf00000)
|
||||||
|
{
|
||||||
|
addr_out |= 0x50000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr_out;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user