diff options
Diffstat (limited to 'src/devices/cpu/mips/mips3.cpp')
-rw-r--r-- | src/devices/cpu/mips/mips3.cpp | 786 |
1 files changed, 538 insertions, 248 deletions
diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index bd50fb22df7..060c5acfc2f 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -9,7 +9,6 @@ ***************************************************************************/ #include "emu.h" -#include "debugger.h" #include "mips3.h" #include "mips3com.h" #include "mips3dsm.h" @@ -19,6 +18,9 @@ #define ENABLE_OVERFLOWS (0) #define ENABLE_EE_ELF_LOADER (0) #define ENABLE_EE_DECI2 (0) +#define ENABLE_O2_DPRINTF (0) + +#include "o2dprintf.hxx" /*************************************************************************** HELPER MACROS @@ -124,7 +126,8 @@ DEFINE_DEVICE_TYPE(R5000BE, r5000be_device, "r5000be", "MIPS R5000 (big)") DEFINE_DEVICE_TYPE(R5000LE, r5000le_device, "r5000le", "MIPS R5000 (little)") DEFINE_DEVICE_TYPE(VR5500BE, vr5500be_device, "vr5500be", "NEC VR5500 (big)") DEFINE_DEVICE_TYPE(VR5500LE, vr5500le_device, "vr5500le", "NEC VR5500 (little)") -DEFINE_DEVICE_TYPE(R5900LE, r5900le_device, "r5900le", "Emotion Engine Core") +DEFINE_DEVICE_TYPE(R5900BE, r5900be_device, "r5900be", "Emotion Engine Core (big)") +DEFINE_DEVICE_TYPE(R5900LE, r5900le_device, "r5900le", "Emotion Engine Core (little)") DEFINE_DEVICE_TYPE(QED5271BE, qed5271be_device, "qed5271be", "MIPS QED5271 (big)") DEFINE_DEVICE_TYPE(QED5271LE, qed5271le_device, "qed5271le", "MIPS QED5271 (little)") DEFINE_DEVICE_TYPE(RM7000BE, rm7000be_device, "rm7000be", "MIPS RM7000 (big)") @@ -244,7 +247,7 @@ void mips3_device::generate_exception(int exception, int backup) if (exception != 0) { - fprintf(stderr, "Exception: PC=%08X, PPC=%08X\n", m_core->pc, m_ppc); + fprintf(stderr, "Exception type %d: PC=%08X, PPC=%08X\n", exception, m_core->pc, m_ppc); machine().debug_break(); } */ @@ -345,11 +348,9 @@ void mips3_device::generate_exception(int exception, int backup) void mips3_device::generate_tlb_exception(int exception, offs_t address) { m_core->cpr[0][COP0_BadVAddr] = address; - if(exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE || exception == EXCEPTION_TLBLOAD_FILL || exception == EXCEPTION_TLBSTORE_FILL) - { - m_core->cpr[0][COP0_Context] = (m_core->cpr[0][COP0_Context] & 0xff800000) | ((address >> 9) & 0x007ffff0); - m_core->cpr[0][COP0_EntryHi] = (address & 0xffffe000) | (m_core->cpr[0][COP0_EntryHi] & 0xff); - } + m_core->cpr[0][COP0_Context] = (m_core->cpr[0][COP0_Context] & 0xff800000) | ((address >> 9) & 0x007ffff0); + m_core->cpr[0][COP0_EntryHi] = (address & 0xffffe000) | (m_core->cpr[0][COP0_EntryHi] & 0xff); + generate_exception(exception, 1); } @@ -372,7 +373,7 @@ void mips3_device::check_irqs() generate_exception(EXCEPTION_INTERRUPT, 0); } -void r5900le_device::check_irqs() +void r5900_device::check_irqs() { if ((CAUSE & SR & 0xfc00) && (SR & SR_IE) && (SR & SR_EIE) && !(SR & (SR_EXL | SR_ERL))) generate_exception(EXCEPTION_INTERRUPT, 0); @@ -401,38 +402,35 @@ void mips3_device::device_start() { if (m_data_bits == 32) { - auto cache = m_program->cache<2, 0, ENDIANNESS_LITTLE>(); - 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_cache32le); + m_pr32 = delegate<u32 (offs_t)>(&memory_access<32, 2, 0, ENDIANNESS_LITTLE>::cache::read_dword, &m_cache32le); + m_prptr = [this] (offs_t address) -> const void * { return m_cache32le.read_ptr(address); }; } else { - auto cache = m_program->cache<3, 0, ENDIANNESS_LITTLE>(); - 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_cache64le); + m_pr32 = delegate<u32 (offs_t)>(&memory_access<32, 3, 0, ENDIANNESS_LITTLE>::cache::read_dword, &m_cache64le); + m_prptr = [this] (offs_t address) -> const void * { return m_cache64le.read_ptr(address); }; } } else { if (m_data_bits == 32) { - 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_cache32be); + m_pr32 = delegate<u32 (offs_t)>(&memory_access<32, 2, 0, ENDIANNESS_BIG>::cache::read_dword, &m_cache32be); + m_prptr = [this] (offs_t address) -> const void * { return m_cache32be.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_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; + m_program->cache(m_cache64be); + m_pr32 = delegate<u32 (offs_t)>(&memory_access<32, 3, 0, ENDIANNESS_BIG>::cache::read_dword, &m_cache64be); + m_prptr = [this] (offs_t address) -> const void * { return m_cache64be.read_ptr(address); }; } } - /* set up the endianness */ - m_program->accessors(m_memory); - /* allocate a timer for the compare interrupt */ - m_compare_int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mips3_device::compare_int_callback), this)); + m_compare_int_timer = timer_alloc(FUNC(mips3_device::compare_int_callback), this); uint32_t flags = 0; /* initialize the UML generator */ @@ -444,9 +442,9 @@ void mips3_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, "f%d", regnum); + snprintf(buf, 10, "f%d", regnum); m_drcuml->symbol_add(&m_core->cpr[1][regnum], sizeof(m_core->cpr[1][regnum]), buf); } m_drcuml->symbol_add(&m_core->r[REG_LO], sizeof(m_core->r[REG_LO]), "lo"); @@ -474,7 +472,8 @@ void mips3_device::device_start() m_drcuml->symbol_add(&m_core->cpr[0][COP0_TagLo], sizeof(m_core->cpr[0][COP0_TagLo]), "TagLo"); m_drcuml->symbol_add(&m_core->cpr[0][COP0_TagHi], sizeof(m_core->cpr[0][COP0_TagHi]), "TagHi"); m_drcuml->symbol_add(&m_core->cpr[0][COP0_ErrorPC], sizeof(m_core->cpr[0][COP0_ErrorPC]), "ErrorPC"); - m_drcuml->symbol_add(&m_core->ccr[1][31], sizeof(m_core->cpr[1][31]), "fcr31"); + m_drcuml->symbol_add(&m_core->ccr[1][0], sizeof(m_core->ccr[1][0]), "fcr0"); + m_drcuml->symbol_add(&m_core->ccr[1][31], sizeof(m_core->ccr[1][31]), "fcr31"); m_drcuml->symbol_add(&m_core->mode, sizeof(m_core->mode), "mode"); m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0"); m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1"); @@ -545,73 +544,73 @@ void mips3_device::device_start() #if USE_ABI_REG_NAMES state_add( MIPS3_R0, "zero", m_core->r[0]).callimport().formatstr("%016X"); // Can't change R0 - state_add( MIPS3_R1, "at", m_core->r[1]).formatstr("%016X"); - state_add( MIPS3_R2, "v0", m_core->r[2]).formatstr("%016X"); - state_add( MIPS3_R3, "v1", m_core->r[3]).formatstr("%016X"); - state_add( MIPS3_R4, "a0", m_core->r[4]).formatstr("%016X"); - state_add( MIPS3_R5, "a1", m_core->r[5]).formatstr("%016X"); - state_add( MIPS3_R6, "a2", m_core->r[6]).formatstr("%016X"); - state_add( MIPS3_R7, "a3", m_core->r[7]).formatstr("%016X"); - state_add( MIPS3_R8, "t0", m_core->r[8]).formatstr("%016X"); - state_add( MIPS3_R9, "t1", m_core->r[9]).formatstr("%016X"); - state_add( MIPS3_R10, "t2", m_core->r[10]).formatstr("%016X"); - state_add( MIPS3_R11, "t3", m_core->r[11]).formatstr("%016X"); - state_add( MIPS3_R12, "t4", m_core->r[12]).formatstr("%016X"); - state_add( MIPS3_R13, "t5", m_core->r[13]).formatstr("%016X"); - state_add( MIPS3_R14, "t6", m_core->r[14]).formatstr("%016X"); - state_add( MIPS3_R15, "t7", m_core->r[15]).formatstr("%016X"); - state_add( MIPS3_R16, "s0", m_core->r[16]).formatstr("%016X"); - state_add( MIPS3_R17, "s1", m_core->r[17]).formatstr("%016X"); - state_add( MIPS3_R18, "s2", m_core->r[18]).formatstr("%016X"); - state_add( MIPS3_R19, "s3", m_core->r[19]).formatstr("%016X"); - state_add( MIPS3_R20, "s4", m_core->r[20]).formatstr("%016X"); - state_add( MIPS3_R21, "s5", m_core->r[21]).formatstr("%016X"); - state_add( MIPS3_R22, "s6", m_core->r[22]).formatstr("%016X"); - state_add( MIPS3_R23, "s7", m_core->r[23]).formatstr("%016X"); - state_add( MIPS3_R24, "t8", m_core->r[24]).formatstr("%016X"); - state_add( MIPS3_R25, "t9", m_core->r[25]).formatstr("%016X"); - state_add( MIPS3_R26, "k0", m_core->r[26]).formatstr("%016X"); - state_add( MIPS3_R27, "k1", m_core->r[27]).formatstr("%016X"); - state_add( MIPS3_R28, "gp", m_core->r[28]).formatstr("%016X"); - state_add( MIPS3_R29, "sp", m_core->r[29]).formatstr("%016X"); - state_add( MIPS3_R30, "fp", m_core->r[30]).formatstr("%016X"); - state_add( MIPS3_R31, "ra", m_core->r[31]).formatstr("%016X"); + state_add( MIPS3_R1, "at", m_core->r[1]).formatstr("%016X").callimport(); + state_add( MIPS3_R2, "v0", m_core->r[2]).formatstr("%016X").callimport(); + state_add( MIPS3_R3, "v1", m_core->r[3]).formatstr("%016X").callimport(); + state_add( MIPS3_R4, "a0", m_core->r[4]).formatstr("%016X").callimport(); + state_add( MIPS3_R5, "a1", m_core->r[5]).formatstr("%016X").callimport(); + state_add( MIPS3_R6, "a2", m_core->r[6]).formatstr("%016X").callimport(); + state_add( MIPS3_R7, "a3", m_core->r[7]).formatstr("%016X").callimport(); + state_add( MIPS3_R8, "t0", m_core->r[8]).formatstr("%016X").callimport(); + state_add( MIPS3_R9, "t1", m_core->r[9]).formatstr("%016X").callimport(); + state_add( MIPS3_R10, "t2", m_core->r[10]).formatstr("%016X").callimport(); + state_add( MIPS3_R11, "t3", m_core->r[11]).formatstr("%016X").callimport(); + state_add( MIPS3_R12, "t4", m_core->r[12]).formatstr("%016X").callimport(); + state_add( MIPS3_R13, "t5", m_core->r[13]).formatstr("%016X").callimport(); + state_add( MIPS3_R14, "t6", m_core->r[14]).formatstr("%016X").callimport(); + state_add( MIPS3_R15, "t7", m_core->r[15]).formatstr("%016X").callimport(); + state_add( MIPS3_R16, "s0", m_core->r[16]).formatstr("%016X").callimport(); + state_add( MIPS3_R17, "s1", m_core->r[17]).formatstr("%016X").callimport(); + state_add( MIPS3_R18, "s2", m_core->r[18]).formatstr("%016X").callimport(); + state_add( MIPS3_R19, "s3", m_core->r[19]).formatstr("%016X").callimport(); + state_add( MIPS3_R20, "s4", m_core->r[20]).formatstr("%016X").callimport(); + state_add( MIPS3_R21, "s5", m_core->r[21]).formatstr("%016X").callimport(); + state_add( MIPS3_R22, "s6", m_core->r[22]).formatstr("%016X").callimport(); + state_add( MIPS3_R23, "s7", m_core->r[23]).formatstr("%016X").callimport(); + state_add( MIPS3_R24, "t8", m_core->r[24]).formatstr("%016X").callimport(); + state_add( MIPS3_R25, "t9", m_core->r[25]).formatstr("%016X").callimport(); + state_add( MIPS3_R26, "k0", m_core->r[26]).formatstr("%016X").callimport(); + state_add( MIPS3_R27, "k1", m_core->r[27]).formatstr("%016X").callimport(); + state_add( MIPS3_R28, "gp", m_core->r[28]).formatstr("%016X").callimport(); + state_add( MIPS3_R29, "sp", m_core->r[29]).formatstr("%016X").callimport(); + state_add( MIPS3_R30, "fp", m_core->r[30]).formatstr("%016X").callimport(); + state_add( MIPS3_R31, "ra", m_core->r[31]).formatstr("%016X").callimport(); #else state_add( MIPS3_R0, "R0", m_core->r[0]).callimport().formatstr("%016X"); // Can't change R0 - state_add( MIPS3_R1, "R1", m_core->r[1]).formatstr("%016X"); - state_add( MIPS3_R2, "R2", m_core->r[2]).formatstr("%016X"); - state_add( MIPS3_R3, "R3", m_core->r[3]).formatstr("%016X"); - state_add( MIPS3_R4, "R4", m_core->r[4]).formatstr("%016X"); - state_add( MIPS3_R5, "R5", m_core->r[5]).formatstr("%016X"); - state_add( MIPS3_R6, "R6", m_core->r[6]).formatstr("%016X"); - state_add( MIPS3_R7, "R7", m_core->r[7]).formatstr("%016X"); - state_add( MIPS3_R8, "R8", m_core->r[8]).formatstr("%016X"); - state_add( MIPS3_R9, "R9", m_core->r[9]).formatstr("%016X"); - state_add( MIPS3_R10, "R10", m_core->r[10]).formatstr("%016X"); - state_add( MIPS3_R11, "R11", m_core->r[11]).formatstr("%016X"); - state_add( MIPS3_R12, "R12", m_core->r[12]).formatstr("%016X"); - state_add( MIPS3_R13, "R13", m_core->r[13]).formatstr("%016X"); - state_add( MIPS3_R14, "R14", m_core->r[14]).formatstr("%016X"); - state_add( MIPS3_R15, "R15", m_core->r[15]).formatstr("%016X"); - state_add( MIPS3_R16, "R16", m_core->r[16]).formatstr("%016X"); - state_add( MIPS3_R17, "R17", m_core->r[17]).formatstr("%016X"); - state_add( MIPS3_R18, "R18", m_core->r[18]).formatstr("%016X"); - state_add( MIPS3_R19, "R19", m_core->r[19]).formatstr("%016X"); - state_add( MIPS3_R20, "R20", m_core->r[20]).formatstr("%016X"); - state_add( MIPS3_R21, "R21", m_core->r[21]).formatstr("%016X"); - state_add( MIPS3_R22, "R22", m_core->r[22]).formatstr("%016X"); - state_add( MIPS3_R23, "R23", m_core->r[23]).formatstr("%016X"); - state_add( MIPS3_R24, "R24", m_core->r[24]).formatstr("%016X"); - state_add( MIPS3_R25, "R25", m_core->r[25]).formatstr("%016X"); - state_add( MIPS3_R26, "R26", m_core->r[26]).formatstr("%016X"); - state_add( MIPS3_R27, "R27", m_core->r[27]).formatstr("%016X"); - state_add( MIPS3_R28, "R28", m_core->r[28]).formatstr("%016X"); - state_add( MIPS3_R29, "R29", m_core->r[29]).formatstr("%016X"); - state_add( MIPS3_R30, "R30", m_core->r[30]).formatstr("%016X"); - state_add( MIPS3_R31, "R31", m_core->r[31]).formatstr("%016X"); + state_add( MIPS3_R1, "R1", m_core->r[1]).formatstr("%016X").callimport(); + state_add( MIPS3_R2, "R2", m_core->r[2]).formatstr("%016X").callimport(); + state_add( MIPS3_R3, "R3", m_core->r[3]).formatstr("%016X").callimport(); + state_add( MIPS3_R4, "R4", m_core->r[4]).formatstr("%016X").callimport(); + state_add( MIPS3_R5, "R5", m_core->r[5]).formatstr("%016X").callimport(); + state_add( MIPS3_R6, "R6", m_core->r[6]).formatstr("%016X").callimport(); + state_add( MIPS3_R7, "R7", m_core->r[7]).formatstr("%016X").callimport(); + state_add( MIPS3_R8, "R8", m_core->r[8]).formatstr("%016X").callimport(); + state_add( MIPS3_R9, "R9", m_core->r[9]).formatstr("%016X").callimport(); + state_add( MIPS3_R10, "R10", m_core->r[10]).formatstr("%016X").callimport(); + state_add( MIPS3_R11, "R11", m_core->r[11]).formatstr("%016X").callimport(); + state_add( MIPS3_R12, "R12", m_core->r[12]).formatstr("%016X").callimport(); + state_add( MIPS3_R13, "R13", m_core->r[13]).formatstr("%016X").callimport(); + state_add( MIPS3_R14, "R14", m_core->r[14]).formatstr("%016X").callimport(); + state_add( MIPS3_R15, "R15", m_core->r[15]).formatstr("%016X").callimport(); + state_add( MIPS3_R16, "R16", m_core->r[16]).formatstr("%016X").callimport(); + state_add( MIPS3_R17, "R17", m_core->r[17]).formatstr("%016X").callimport(); + state_add( MIPS3_R18, "R18", m_core->r[18]).formatstr("%016X").callimport(); + state_add( MIPS3_R19, "R19", m_core->r[19]).formatstr("%016X").callimport(); + state_add( MIPS3_R20, "R20", m_core->r[20]).formatstr("%016X").callimport(); + state_add( MIPS3_R21, "R21", m_core->r[21]).formatstr("%016X").callimport(); + state_add( MIPS3_R22, "R22", m_core->r[22]).formatstr("%016X").callimport(); + state_add( MIPS3_R23, "R23", m_core->r[23]).formatstr("%016X").callimport(); + state_add( MIPS3_R24, "R24", m_core->r[24]).formatstr("%016X").callimport(); + state_add( MIPS3_R25, "R25", m_core->r[25]).formatstr("%016X").callimport(); + state_add( MIPS3_R26, "R26", m_core->r[26]).formatstr("%016X").callimport(); + state_add( MIPS3_R27, "R27", m_core->r[27]).formatstr("%016X").callimport(); + state_add( MIPS3_R28, "R28", m_core->r[28]).formatstr("%016X").callimport(); + state_add( MIPS3_R29, "R29", m_core->r[29]).formatstr("%016X").callimport(); + state_add( MIPS3_R30, "R30", m_core->r[30]).formatstr("%016X").callimport(); + state_add( MIPS3_R31, "R31", m_core->r[31]).formatstr("%016X").callimport(); #endif - state_add( MIPS3_HI, "HI", m_core->r[REG_HI]).formatstr("%016X"); - state_add( MIPS3_LO, "LO", m_core->r[REG_LO]).formatstr("%016X"); + state_add( MIPS3_HI, "HI", m_core->r[REG_HI]).formatstr("%016X").callimport(); + state_add( MIPS3_LO, "LO", m_core->r[REG_LO]).formatstr("%016X").callimport(); state_add( MIPS3_CCR1_31, "CCR31", m_core->ccr[1][31]).formatstr("%08X"); @@ -728,13 +727,12 @@ void mips3_device::device_start() state_add( MIPS3_LLADDR, "LLAddr", m_core->cpr[0][COP0_LLAddr]).formatstr("%08X"); state_add( STATE_GENPCBASE, "CURPC", m_core->pc).noshow(); - state_add( STATE_GENSP, "CURSP", m_core->r[31]).noshow(); state_add( STATE_GENFLAGS, "CURFLAGS", m_debugger_temp).formatstr("%1s").noshow(); set_icountptr(m_core->icount); } -void r5900le_device::device_start() +void r5900_device::device_start() { mips3_device::device_start(); #if USE_ABI_REG_NAMES @@ -816,6 +814,16 @@ void mips3_device::state_export(const device_state_entry &entry) } } +void mips3_device::state_import(const device_state_entry &entry) +{ + if (m_isdrc && (entry.index() >= MIPS3_R1) && (entry.index() <= MIPS3_LO)) + { + // this refers to HI as R32 and LO as R33 because I'm lazy + const unsigned regnum = entry.index() - MIPS3_R0; + if (m_regmap[regnum].is_int_register()) + logerror("debugger R%u = %08X, must update UML I%u\n", regnum, m_core->r[regnum], m_regmap[regnum].ireg() - uml::REG_I0); + } +} void mips3_device::state_string_export(const device_state_entry &entry, std::string &str) const { @@ -1102,6 +1110,9 @@ void mips3_device::device_reset() m_core->llbit = 0; m_core->count_zero_time = total_cycles(); + /* initialize the FPU state */ + m_core->ccr[1][0] = compute_fpu_prid_register(); + /* initialize the TLB state */ for (int tlbindex = 0; tlbindex < m_tlbentries; tlbindex++) { @@ -1117,11 +1128,11 @@ void mips3_device::device_reset() } /* load the fixed TLB range */ - vtlb_load(2 * m_tlbentries + 0, (0xa0000000 - 0x80000000) >> MIPS3_MIN_PAGE_SHIFT, 0x80000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID); - vtlb_load(2 * m_tlbentries + 1, (0xc0000000 - 0xa0000000) >> MIPS3_MIN_PAGE_SHIFT, 0xa0000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID); + vtlb_load(2 * m_tlbentries + 0, (0xa0000000 - 0x80000000) >> MIPS3_MIN_PAGE_SHIFT, 0x80000000, 0x00000000 | READ_ALLOWED | WRITE_ALLOWED | FETCH_ALLOWED | FLAG_VALID); + vtlb_load(2 * m_tlbentries + 1, (0xc0000000 - 0xa0000000) >> MIPS3_MIN_PAGE_SHIFT, 0xa0000000, 0x00000000 | READ_ALLOWED | WRITE_ALLOWED | FETCH_ALLOWED | FLAG_VALID); // TX4925 on-board peripherals pass-through if (m_flavor == MIPS3_TYPE_TX4925) - vtlb_load(2 * m_tlbentries + 2, (0xff200000 - 0xff1f0000) >> MIPS3_MIN_PAGE_SHIFT, 0xff1f0000, 0xff1f0000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID); + vtlb_load(2 * m_tlbentries + 2, (0xff200000 - 0xff1f0000) >> MIPS3_MIN_PAGE_SHIFT, 0xff1f0000, 0xff1f0000 | READ_ALLOWED | WRITE_ALLOWED | FETCH_ALLOWED | FLAG_VALID); m_tlb_seed = 0; m_core->mode = (MODE_KERNEL << 1) | 0; @@ -1137,26 +1148,34 @@ void mips3_device::device_reset() } -bool mips3_device::memory_translate(int spacenum, int intention, offs_t &address) +bool mips3_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) { const vtlb_entry *table = vtlb_table(); vtlb_entry entry = table[address >> MIPS3_MIN_PAGE_SHIFT]; - if ((entry & (1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK)))) == 0) + if ((entry & (1 << intention)) == 0) return false; address = (entry & ~MIPS3_MIN_PAGE_MASK) | (address & MIPS3_MIN_PAGE_MASK); } return true; } +bool r4650_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) +{ + target_space = &space(spacenum); + return true; +} + std::unique_ptr<util::disasm_interface> mips3_device::create_disassembler() { return std::make_unique<mips3_disassembler>(); } -std::unique_ptr<util::disasm_interface> r5900le_device::create_disassembler() +std::unique_ptr<util::disasm_interface> r5900_device::create_disassembler() { return std::make_unique<ee_disassembler>(); } @@ -1170,7 +1189,7 @@ std::unique_ptr<util::disasm_interface> r5900le_device::create_disassembler() inline bool mips3_device::RBYTE(offs_t address, uint32_t *result) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { const uint32_t tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) @@ -1182,11 +1201,11 @@ inline bool mips3_device::RBYTE(offs_t address, uint32_t *result) *result = m_fastram[ramnum].offset_base8[tlbaddress ^ m_byte_xor]; return true; } - *result = (*m_memory.read_byte)(*m_program, tlbaddress); + *result = m_program->read_byte(tlbaddress); } else { - if(tlbval & VTLB_FLAG_FIXED) + if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBLOAD, address); } @@ -1203,7 +1222,7 @@ inline bool mips3_device::RBYTE(offs_t address, uint32_t *result) inline bool mips3_device::RHALF(offs_t address, uint32_t *result) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { const uint32_t tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) @@ -1215,11 +1234,11 @@ inline bool mips3_device::RHALF(offs_t address, uint32_t *result) *result = m_fastram[ramnum].offset_base16[(tlbaddress ^ m_word_xor) >> 1]; return true; } - *result = (*m_memory.read_word)(*m_program, tlbaddress); + *result = m_program->read_word(tlbaddress); } else { - if(tlbval & VTLB_FLAG_FIXED) + if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBLOAD, address); } @@ -1236,7 +1255,7 @@ inline bool mips3_device::RHALF(offs_t address, uint32_t *result) inline bool mips3_device::RWORD(offs_t address, uint32_t *result, bool insn) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { const uint32_t tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) @@ -1248,11 +1267,11 @@ inline bool mips3_device::RWORD(offs_t address, uint32_t *result, bool insn) *result = m_fastram[ramnum].offset_base32[(tlbaddress ^ m_dword_xor) >> 2]; return true; } - *result = (*m_memory.read_dword)(*m_program, tlbaddress); + *result = m_program->read_dword(tlbaddress); } else { - if(tlbval & VTLB_FLAG_FIXED) + if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBLOAD, address); } @@ -1269,13 +1288,13 @@ inline bool mips3_device::RWORD(offs_t address, uint32_t *result, bool insn) inline bool mips3_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { - *result = (*m_memory.read_dword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), mem_mask); + *result = m_program->read_dword((tlbval & ~0xfff) | (address & 0xfff), mem_mask); } else { - if(tlbval & VTLB_FLAG_FIXED) + if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBLOAD, address); } @@ -1292,13 +1311,13 @@ inline bool mips3_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_ inline bool mips3_device::RDOUBLE(offs_t address, uint64_t *result) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { - *result = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff)); + *result = m_program->read_qword((tlbval & ~0xfff) | (address & 0xfff)); } else { - if(tlbval & VTLB_FLAG_FIXED) + if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBLOAD, address); } @@ -1315,13 +1334,13 @@ inline bool mips3_device::RDOUBLE(offs_t address, uint64_t *result) inline bool mips3_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { - *result = (*m_memory.read_qword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), mem_mask); + *result = m_program->read_qword((tlbval & ~0xfff) | (address & 0xfff), mem_mask); } else { - if(tlbval & VTLB_FLAG_FIXED) + if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBLOAD, address); } @@ -1338,7 +1357,7 @@ inline bool mips3_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint6 inline void mips3_device::WBYTE(offs_t address, uint8_t data) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_WRITE_ALLOWED) + if (tlbval & WRITE_ALLOWED) { const uint32_t tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) @@ -1350,15 +1369,15 @@ inline void mips3_device::WBYTE(offs_t address, uint8_t data) m_fastram[ramnum].offset_base8[tlbaddress ^ m_byte_xor] = data; return; } - (*m_memory.write_byte)(*m_program, tlbaddress, data); + m_program->write_byte(tlbaddress, data); } else { - if(tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { generate_tlb_exception(EXCEPTION_TLBMOD, address); } - else if(tlbval & VTLB_FLAG_FIXED) + else if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBSTORE, address); } @@ -1372,7 +1391,7 @@ inline void mips3_device::WBYTE(offs_t address, uint8_t data) inline void mips3_device::WHALF(offs_t address, uint16_t data) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_WRITE_ALLOWED) + if (tlbval & WRITE_ALLOWED) { const uint32_t tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) @@ -1384,15 +1403,15 @@ inline void mips3_device::WHALF(offs_t address, uint16_t data) m_fastram[ramnum].offset_base16[(tlbaddress ^ m_word_xor) >> 1] = data; return; } - (*m_memory.write_word)(*m_program, tlbaddress, data); + m_program->write_word(tlbaddress, data); } else { - if(tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { generate_tlb_exception(EXCEPTION_TLBMOD, address); } - else if(tlbval & VTLB_FLAG_FIXED) + else if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBSTORE, address); } @@ -1406,7 +1425,7 @@ inline void mips3_device::WHALF(offs_t address, uint16_t data) inline void mips3_device::WWORD(offs_t address, uint32_t data) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_WRITE_ALLOWED) + if (tlbval & WRITE_ALLOWED) { const uint32_t tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) @@ -1418,15 +1437,15 @@ inline void mips3_device::WWORD(offs_t address, uint32_t data) m_fastram[ramnum].offset_base32[(tlbaddress ^ m_dword_xor) >> 2] = data; return; } - (*m_memory.write_dword)(*m_program, tlbaddress, data); + m_program->write_dword(tlbaddress, data); } else { - if(tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { generate_tlb_exception(EXCEPTION_TLBMOD, address); } - else if(tlbval & VTLB_FLAG_FIXED) + else if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBSTORE, address); } @@ -1440,17 +1459,17 @@ inline void mips3_device::WWORD(offs_t address, uint32_t data) inline void mips3_device::WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_WRITE_ALLOWED) + if (tlbval & WRITE_ALLOWED) { - (*m_memory.write_dword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data, mem_mask); + m_program->write_dword((tlbval & ~0xfff) | (address & 0xfff), data, mem_mask); } else { - if(tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { generate_tlb_exception(EXCEPTION_TLBMOD, address); } - else if(tlbval & VTLB_FLAG_FIXED) + else if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBSTORE, address); } @@ -1464,17 +1483,17 @@ inline void mips3_device::WWORD_MASKED(offs_t address, uint32_t data, uint32_t m inline void mips3_device::WDOUBLE(offs_t address, uint64_t data) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_WRITE_ALLOWED) + if (tlbval & WRITE_ALLOWED) { - (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data); + m_program->write_qword((tlbval & ~0xfff) | (address & 0xfff), data); } else { - if(tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { generate_tlb_exception(EXCEPTION_TLBMOD, address); } - else if(tlbval & VTLB_FLAG_FIXED) + else if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBSTORE, address); } @@ -1488,17 +1507,17 @@ inline void mips3_device::WDOUBLE(offs_t address, uint64_t data) inline void mips3_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask) { const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_WRITE_ALLOWED) + if (tlbval & WRITE_ALLOWED) { - (*m_memory.write_qword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data, mem_mask); + m_program->write_qword((tlbval & ~0xfff) | (address & 0xfff), data, mem_mask); } else { - if(tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { generate_tlb_exception(EXCEPTION_TLBMOD, address); } - else if(tlbval & VTLB_FLAG_FIXED) + else if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBSTORE, address); } @@ -1509,38 +1528,211 @@ inline void mips3_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t } } -inline void r5900le_device::WBYTE(offs_t address, uint8_t data) +inline bool r4650_device::RBYTE(offs_t address, uint32_t *result) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = m_program->read_byte(address); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = m_program->read_byte(address + m_core->cpr[0][COP0_R4650_DBase]); + return true; +} + +inline bool r4650_device::RHALF(offs_t address, uint32_t *result) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = m_program->read_word(address); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = m_program->read_word(address + m_core->cpr[0][COP0_R4650_DBase]); + return true; +} + +inline bool r4650_device::RWORD(offs_t address, uint32_t *result, bool insn) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = m_program->read_dword(address); + return true; + } + + static const uint32_t BASE_INDICES[2] = { COP0_R4650_DBase, COP0_R4650_IBase }; + static const uint32_t BOUND_INDICES[2] = { COP0_R4650_DBound, COP0_R4650_IBound }; + const uint32_t base = m_core->cpr[0][BASE_INDICES[insn]]; + const uint32_t bound = m_core->cpr[0][BOUND_INDICES[insn]]; + if ((address & 0xfffff000) > bound) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = m_program->read_dword(address + base); + return true; +} + +inline bool r4650_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = m_program->read_dword(address, mem_mask); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = m_program->read_dword(address + m_core->cpr[0][COP0_R4650_DBase], mem_mask); + return true; +} + +inline bool r4650_device::RDOUBLE(offs_t address, uint64_t *result) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = m_program->read_qword(address); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = m_program->read_qword(address + m_core->cpr[0][COP0_R4650_DBase]); + return true; +} + +inline bool r4650_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = m_program->read_qword(address, mem_mask); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = m_program->read_qword(address + m_core->cpr[0][COP0_R4650_DBase], mem_mask); + return true; +} + +inline void r4650_device::WBYTE(offs_t address, uint8_t data) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + m_program->write_byte(address, data); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + m_program->write_byte(address + m_core->cpr[0][COP0_R4650_DBound], data); +} + +inline void r4650_device::WHALF(offs_t address, uint16_t data) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + m_program->write_word(address, data); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + m_program->write_word(address + m_core->cpr[0][COP0_R4650_DBound], data); +} + +inline void r4650_device::WWORD(offs_t address, uint32_t data) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + m_program->write_dword(address, data); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + m_program->write_dword(address + m_core->cpr[0][COP0_R4650_DBound], data); +} + +inline void r4650_device::WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + m_program->write_dword(address, data, mem_mask); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + m_program->write_dword(address + m_core->cpr[0][COP0_R4650_DBound], data, mem_mask); +} + +inline void r4650_device::WDOUBLE(offs_t address, uint64_t data) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + m_program->write_qword(address, data); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + m_program->write_qword(address + m_core->cpr[0][COP0_R4650_DBound], data); +} + +inline void r4650_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask) { - if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_byte)(*m_program, address, data); + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + m_program->write_qword(address, data, mem_mask); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + m_program->write_qword(address + m_core->cpr[0][COP0_R4650_DBound], data, mem_mask); +} + +inline void r5900_device::WBYTE(offs_t address, uint8_t data) +{ + if (address >= 0x70000000 && address < 0x70004000) m_program->write_byte(address, data); else mips3_device::WBYTE(address, data); } -inline void r5900le_device::WHALF(offs_t address, uint16_t data) +inline void r5900_device::WHALF(offs_t address, uint16_t data) { - if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_word)(*m_program, address, data); + if (address >= 0x70000000 && address < 0x70004000) m_program->write_word(address, data); else mips3_device::WHALF(address, data); } -inline void r5900le_device::WWORD(offs_t address, uint32_t data) +inline void r5900_device::WWORD(offs_t address, uint32_t data) { - if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_dword)(*m_program, address, data); + if (address >= 0x70000000 && address < 0x70004000) m_program->write_dword(address, data); else mips3_device::WWORD(address, data); } -inline void r5900le_device::WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask) +inline void r5900_device::WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask) { - if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_dword_masked)(*m_program, address, data, mem_mask); + if (address >= 0x70000000 && address < 0x70004000) m_program->write_dword(address, data, mem_mask); else mips3_device::WWORD_MASKED(address, data, mem_mask); } -inline void r5900le_device::WDOUBLE(offs_t address, uint64_t data) { - if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_qword)(*m_program, address, data); +inline void r5900_device::WDOUBLE(offs_t address, uint64_t data) +{ + if (address >= 0x70000000 && address < 0x70004000) m_program->write_qword(address, data); else mips3_device::WDOUBLE(address, data); } -inline void r5900le_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask) +inline void r5900_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask) { - if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_qword_masked)(*m_program, address, data, mem_mask); + if (address >= 0x70000000 && address < 0x70004000) m_program->write_qword(address, data, mem_mask); else mips3_device::WDOUBLE_MASKED(address, data, mem_mask); } @@ -1548,24 +1740,56 @@ inline void r5900le_device::WQUAD(offs_t address, uint64_t data_hi, uint64_t dat { if (address >= 0x70000000 && address < 0x70004000) { - (*m_memory.write_qword)(*m_program, address, data_lo); - (*m_memory.write_qword)(*m_program, address + 8, data_hi); + m_program->write_qword(address, data_lo); + m_program->write_qword(address + 8, data_hi); + return; + } + + const uint32_t tlbval = vtlb_table()[address >> 12]; + if (tlbval & WRITE_ALLOWED) + { + m_program->write_qword((tlbval & ~0xfff) | (address & 0xfff), data_lo); + m_program->write_qword((tlbval & ~0xfff) | ((address + 8) & 0xfff), data_hi); + } + else + { + if (tlbval & READ_ALLOWED) + { + generate_tlb_exception(EXCEPTION_TLBMOD, address); + } + else if (tlbval & FLAG_FIXED) + { + generate_tlb_exception(EXCEPTION_TLBSTORE, address); + } + else + { + generate_tlb_exception(EXCEPTION_TLBSTORE_FILL, address); + } + } +} + +inline void r5900be_device::WQUAD(offs_t address, uint64_t data_hi, uint64_t data_lo) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + m_program->write_qword(address, data_hi); + m_program->write_qword(address + 8, data_lo); return; } const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_WRITE_ALLOWED) + if (tlbval & WRITE_ALLOWED) { - (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data_lo); - (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff), data_hi); + m_program->write_qword((tlbval & ~0xfff) | (address & 0xfff), data_hi); + m_program->write_qword((tlbval & ~0xfff) | ((address + 8) & 0xfff), data_lo); } else { - if(tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { generate_tlb_exception(EXCEPTION_TLBMOD, address); } - else if(tlbval & VTLB_FLAG_FIXED) + else if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBSTORE, address); } @@ -1576,59 +1800,61 @@ inline void r5900le_device::WQUAD(offs_t address, uint64_t data_hi, uint64_t dat } } -inline bool r5900le_device::RBYTE(offs_t address, uint32_t *result) { - if (address >= 0x70000000 && address < 0x70004000) { - *result = (*m_memory.read_byte)(*m_program, address); +inline bool r5900_device::RBYTE(offs_t address, uint32_t *result) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + *result = m_program->read_byte(address); return true; } return mips3_device::RBYTE(address, result); } -inline bool r5900le_device::RHALF(offs_t address, uint32_t *result) +inline bool r5900_device::RHALF(offs_t address, uint32_t *result) { if (address >= 0x70000000 && address < 0x70004000) { - *result = (*m_memory.read_word)(*m_program, address); + *result = m_program->read_word(address); return true; } return mips3_device::RHALF(address, result); } -inline bool r5900le_device::RWORD(offs_t address, uint32_t *result, bool insn) +inline bool r5900_device::RWORD(offs_t address, uint32_t *result, bool insn) { if (address >= 0x70000000 && address < 0x70004000) { - *result = (*m_memory.read_dword)(*m_program, address); + *result = m_program->read_dword(address); return true; } return mips3_device::RWORD(address, result, insn); } -inline bool r5900le_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask) +inline bool r5900_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask) { if (address >= 0x70000000 && address < 0x70004000) { - *result = (*m_memory.read_dword_masked)(*m_program, address, mem_mask); + *result = m_program->read_dword(address, mem_mask); return true; } return mips3_device::RWORD_MASKED(address, result, mem_mask); } -inline bool r5900le_device::RDOUBLE(offs_t address, uint64_t *result) +inline bool r5900_device::RDOUBLE(offs_t address, uint64_t *result) { if (address >= 0x70000000 && address < 0x70004000) { - *result = (*m_memory.read_qword)(*m_program, address); + *result = m_program->read_qword(address); return true; } return mips3_device::RDOUBLE(address, result); } -inline bool r5900le_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask) +inline bool r5900_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask) { if (address >= 0x70000000 && address < 0x70004000) { - *result = (*m_memory.read_qword_masked)(*m_program, address, mem_mask); + *result = m_program->read_qword(address, mem_mask); return true; } return mips3_device::RDOUBLE_MASKED(address, result, mem_mask); @@ -1638,20 +1864,52 @@ inline bool r5900le_device::RQUAD(offs_t address, uint64_t *result_hi, uint64_t { if (address >= 0x70000000 && address < 0x70004000) { - *result_lo = (*m_memory.read_qword)(*m_program, address); - *result_hi = (*m_memory.read_qword)(*m_program, address + 8); + *result_lo = m_program->read_qword(address); + *result_hi = m_program->read_qword(address + 8); return true; } const uint32_t tlbval = vtlb_table()[address >> 12]; - if (tlbval & VTLB_READ_ALLOWED) + if (tlbval & READ_ALLOWED) { - *result_lo = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff)); - *result_hi = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff)); + *result_lo = m_program->read_qword((tlbval & ~0xfff) | (address & 0xfff)); + *result_hi = m_program->read_qword((tlbval & ~0xfff) | ((address + 8) & 0xfff)); } else { - if(tlbval & VTLB_FLAG_FIXED) + if (tlbval & FLAG_FIXED) + { + generate_tlb_exception(EXCEPTION_TLBLOAD, address); + } + else + { + generate_tlb_exception(EXCEPTION_TLBLOAD_FILL, address); + } + *result_hi = 0; + *result_lo = 0; + return false; + } + return true; +} + +inline bool r5900be_device::RQUAD(offs_t address, uint64_t *result_hi, uint64_t *result_lo) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + *result_hi = m_program->read_qword(address); + *result_lo = m_program->read_qword(address + 8); + return true; + } + + const uint32_t tlbval = vtlb_table()[address >> 12]; + if (tlbval & READ_ALLOWED) + { + *result_hi = m_program->read_qword((tlbval & ~0xfff) | (address & 0xfff)); + *result_lo = m_program->read_qword((tlbval & ~0xfff) | ((address + 8) & 0xfff)); + } + else + { + if (tlbval & FLAG_FIXED) { generate_tlb_exception(EXCEPTION_TLBLOAD, address); } @@ -1695,23 +1953,40 @@ uint64_t mips3_device::get_cop0_reg(int idx) } else if (idx == COP0_Random) { - int wired = m_core->cpr[0][COP0_Wired] & 0x3f; - int range = 48 - wired; - if (range > 0) - return ((total_cycles() - m_core->count_zero_time) % range + wired) & 0x3f; - else - return 47; + uint32_t wired = m_core->cpr[0][COP0_Wired] & 0x3f; + uint32_t unwired = m_tlbentries - wired; + + if (unwired == 0) + return m_tlbentries - 1; + + return (generate_tlb_index() % unwired) + wired; } return m_core->cpr[0][idx]; } +void r4650_device::set_cop0_reg(int idx, uint64_t val) +{ + switch (idx) + { + case COP0_R4650_IBase: + case COP0_R4650_IBound: + case COP0_R4650_DBase: + case COP0_R4650_DBound: + m_core->cpr[0][idx] = val; + break; + default: + mips3_device::set_cop0_reg(idx, val); + break; + } +} + void mips3_device::set_cop0_reg(int idx, uint64_t val) { switch (idx) { case COP0_Cause: CAUSE = (CAUSE & 0xfc00) | (val & ~0xfc00); - if (CAUSE & 0x300) + if ((CAUSE & SR & 0x300) && (SR & SR_IE) && !(SR & (SR_EXL | SR_ERL))) { /* if we're in a delay slot, propogate the target PC before generating the exception */ if (m_nextpc != ~0) @@ -1802,8 +2077,8 @@ void mips3_device::handle_cop0(uint32_t op) case 0x08: /* BC */ switch (RTREG) { - case 0x00: /* BCzF */ if (!m_cf[0]) ADDPC(SIMMVAL); break; - case 0x01: /* BCzF */ if (m_cf[0]) ADDPC(SIMMVAL); break; + case 0x00: /* BCzF */ if (!m_cf[0][0]) ADDPC(SIMMVAL); break; + case 0x01: /* BCzF */ if (m_cf[0][0]) ADDPC(SIMMVAL); break; case 0x02: /* BCzFL */ invalid_instruction(op); break; case 0x03: /* BCzTL */ invalid_instruction(op); break; default: invalid_instruction(op); break; @@ -1980,25 +2255,31 @@ void mips3_device::handle_cop1_fr0(uint32_t op) break; case 0x03: - if (IS_SINGLE(op)) { /* DIV.S */ - if (FTVALW_FR0 == 0 && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0)))) { + if (IS_SINGLE(op)) /* DIV.S */ + { + if (FTVALW_FR0 == 0 && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0)))) + { COP1_FCR31 |= (1 << (FCR31_FLAGS + FPE_DIV0)); // Set flag COP1_FCR31 |= (1 << (FCR31_CAUSE + FPE_DIV0)); // Set cause generate_exception(EXCEPTION_FPE, 1); //machine().debug_break(); } - else { + else + { FDVALS_FR0 = FSVALS_FR0 / FTVALS_FR0; } } - else { /* DIV.D */ - if (FTVALL_FR0 == 0ull && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0)))) { + else /* DIV.D */ + { + if (FTVALL_FR0 == 0ull && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0)))) + { COP1_FCR31 |= (1 << (FCR31_FLAGS + FPE_DIV0)); // Set flag COP1_FCR31 |= (1 << (FCR31_CAUSE + FPE_DIV0)); // Set cause generate_exception(EXCEPTION_FPE, 1); //machine().debug_break(); } - else { + else + { FDVALD_FR0 = FSVALD_FR0 / FTVALD_FR0; } } @@ -2866,7 +3147,7 @@ inline void mips3_device::set_cop2_creg(int idx, uint64_t val) m_core->vfr[idx][0] = val; } -inline void r5900le_device::handle_dmfc2(uint32_t op) +inline void r5900_device::handle_dmfc2(uint32_t op) { // QMFC2 if (!RTREG) @@ -2884,7 +3165,7 @@ inline void r5900le_device::handle_dmfc2(uint32_t op) m_core->rh[rt] = ((uint64_t)rtval[3] << 32) | rtval[2]; } -inline void r5900le_device::handle_dmtc2(uint32_t op) +inline void r5900_device::handle_dmtc2(uint32_t op) { // QMTC2 uint32_t rt = RTREG; @@ -2896,23 +3177,23 @@ inline void r5900le_device::handle_dmtc2(uint32_t op) } } -inline uint64_t r5900le_device::get_cop2_reg(int idx) +inline uint64_t r5900_device::get_cop2_reg(int idx) { return reinterpret_cast<uint32_t*>(m_core->vfr[idx])[0]; } -inline void r5900le_device::set_cop2_reg(int idx, uint64_t val) +inline void r5900_device::set_cop2_reg(int idx, uint64_t val) { reinterpret_cast<uint32_t*>(m_core->vfr[idx])[0] = (uint32_t)val; } -inline uint64_t r5900le_device::get_cop2_creg(int idx) +inline uint64_t r5900_device::get_cop2_creg(int idx) { logerror("%s: CFC2: Getting ccr[%d] (%08x)\n", machine().describe_context(), idx, m_core->vcr[idx]); return m_core->vcr[idx]; } -inline void r5900le_device::set_cop2_creg(int idx, uint64_t val) +inline void r5900_device::set_cop2_creg(int idx, uint64_t val) { if (idx < 16) { @@ -3003,8 +3284,8 @@ void mips3_device::handle_cop2(uint32_t op) case 0x08: /* BC */ switch (RTREG) { - case 0x00: /* BCzF */ if (!m_cf[2]) ADDPC(SIMMVAL); break; - case 0x01: /* BCzT */ if (m_cf[2]) ADDPC(SIMMVAL); break; + case 0x00: /* BCzF */ if (!m_cf[2][0]) ADDPC(SIMMVAL); break; + case 0x01: /* BCzT */ if (m_cf[2][0]) ADDPC(SIMMVAL); break; case 0x02: /* BCzFL */ invalid_instruction(op); break; case 0x03: /* BCzTL */ invalid_instruction(op); break; default: invalid_instruction(op); break; @@ -3024,7 +3305,7 @@ void mips3_device::handle_extra_cop2(uint32_t op) VU0/1 (COP2) EXECUTION HANDLING (R5900) ***************************************************************************/ -void r5900le_device::handle_extra_cop2(uint32_t op) +void r5900_device::handle_extra_cop2(uint32_t op) { // TODO: Flags, rounding... const int rd = (op >> 6) & 31; @@ -3481,13 +3762,13 @@ void mips3_device::handle_regimm(uint32_t op) void mips3_device::handle_mult(uint32_t op) { - uint64_t temp64 = (int64_t)(int32_t)RSVAL32 * (int64_t)(int32_t)RTVAL32; + uint64_t temp64 = mul_32x32(RSVAL32, RTVAL32); LOVAL64 = (int32_t)temp64; HIVAL64 = (int32_t)(temp64 >> 32); m_core->icount -= 3; } -void r5900le_device::handle_mult(uint32_t op) +void r5900_device::handle_mult(uint32_t op) { mips3_device::handle_mult(op); if (RDREG) RDVAL64 = LOVAL64; @@ -3495,13 +3776,13 @@ void r5900le_device::handle_mult(uint32_t op) void mips3_device::handle_multu(uint32_t op) { - uint64_t temp64 = (uint64_t)RSVAL32 * (uint64_t)RTVAL32; + uint64_t temp64 = mulu_32x32(RSVAL32, RTVAL32); LOVAL64 = (int32_t)temp64; HIVAL64 = (int32_t)(temp64 >> 32); m_core->icount -= 3; } -void r5900le_device::handle_multu(uint32_t op) +void r5900_device::handle_multu(uint32_t op) { mips3_device::handle_multu(op); if (RDREG) RDVAL64 = LOVAL64; @@ -3551,11 +3832,11 @@ void mips3_device::handle_special(uint32_t op) m_core->icount -= 35; break; case 0x1c: /* DMULT */ - LOVAL64 = mul_64x64(RSVAL64, RTVAL64, reinterpret_cast<s64 *>(&HIVAL64)); + LOVAL64 = mul_64x64(RSVAL64, RTVAL64, *reinterpret_cast<s64 *>(&HIVAL64)); m_core->icount -= 7; break; case 0x1d: /* DMULTU */ - LOVAL64 = mulu_64x64(RSVAL64, RTVAL64, &HIVAL64); + LOVAL64 = mulu_64x64(RSVAL64, RTVAL64, HIVAL64); m_core->icount -= 7; break; case 0x1e: /* DDIV */ @@ -3631,8 +3912,28 @@ void mips3_device::handle_idt(uint32_t op) { switch (op & 0x1f) { + case 0: /* MAD */ + if (RSREG != 0 && RTREG != 0) + { + int64_t temp64 = mul_32x32(RSVAL32, RTVAL32); + temp64 += ((int64_t)m_core->r[REG_HI] << 32) | m_core->r[REG_LO]; + m_core->r[REG_LO] = (int32_t)temp64; + m_core->r[REG_HI] = (int32_t)(temp64 >> 32); + } + m_core->icount -= 3; + break; + case 1: /* MADU */ + if (RSREG != 0 && RTREG != 0) + { + uint64_t temp64 = mulu_32x32(RSVAL32, RTVAL32); + temp64 += ((uint64_t)m_core->r[REG_HI] << 32) | m_core->r[REG_LO]; + m_core->r[REG_LO] = (uint32_t)temp64; + m_core->r[REG_HI] = (uint32_t)(temp64 >> 32); + } + m_core->icount -= 3; + break; case 2: /* MUL */ - RDVAL64 = (int32_t)((int32_t)RSVAL32 * (int32_t)RTVAL32); + if (RDREG) RDVAL64 = (int32_t)((int32_t)RSVAL32 * (int32_t)RTVAL32); m_core->icount -= 3; break; default: @@ -3641,7 +3942,7 @@ void mips3_device::handle_idt(uint32_t op) } } -void r5900le_device::handle_extra_base(uint32_t op) +void r5900_device::handle_extra_base(uint32_t op) { const int rs = (op >> 21) & 31; const int rt = (op >> 16) & 31; @@ -3670,7 +3971,7 @@ void r5900le_device::handle_extra_base(uint32_t op) } } -void r5900le_device::handle_extra_special(uint32_t op) +void r5900_device::handle_extra_special(uint32_t op) { const int rs = (op >> 21) & 31; const int rd = (op >> 11) & 31; @@ -3689,7 +3990,7 @@ void r5900le_device::handle_extra_special(uint32_t op) } } -void r5900le_device::handle_extra_regimm(uint32_t op) +void r5900_device::handle_extra_regimm(uint32_t op) { switch (op & 63) { @@ -3705,7 +4006,7 @@ void r5900le_device::handle_extra_regimm(uint32_t op) } } -void r5900le_device::handle_extra_cop0(uint32_t op) +void r5900_device::handle_extra_cop0(uint32_t op) { switch (op & 0x01ffffff) { @@ -3723,7 +4024,7 @@ void r5900le_device::handle_extra_cop0(uint32_t op) } } -void r5900le_device::handle_extra_cop1(uint32_t op) +void r5900_device::handle_extra_cop1(uint32_t op) { switch (op & 0x3f) { @@ -3738,7 +4039,7 @@ void r5900le_device::handle_extra_cop1(uint32_t op) } } -void r5900le_device::handle_idt(uint32_t op) +void r5900_device::handle_idt(uint32_t op) { const int rs = (op >> 21) & 31; const int rt = (op >> 16) & 31; @@ -3749,7 +4050,7 @@ void r5900le_device::handle_idt(uint32_t op) { case 0x00: /* MADD */ { - uint64_t temp64 = (int64_t)(int32_t)RSVAL32 * (int64_t)(int32_t)RTVAL32; + uint64_t temp64 = mul_32x32(RSVAL32, RTVAL32); m_core->r[REG_LO] += (int32_t)temp64; m_core->r[REG_HI] += (int32_t)(temp64 >> 32); if (rd) @@ -3803,7 +4104,7 @@ void r5900le_device::handle_idt(uint32_t op) break; case 0x18: /* MULT1 */ { - uint64_t temp64 = (int64_t)(int32_t)RSVAL32 * (int64_t)(int32_t)RTVAL32; + uint64_t temp64 = mul_32x32(RSVAL32, RTVAL32); m_core->rh[REG_LO] = (int32_t)temp64; m_core->rh[REG_HI] = (int32_t)(temp64 >> 32); if (rd) @@ -3962,7 +4263,7 @@ void r5900le_device::handle_idt(uint32_t op) } } -void r5900le_device::handle_mmi0(uint32_t op) +void r5900_device::handle_mmi0(uint32_t op) { const int rs = (op >> 21) & 31; const int rt = (op >> 16) & 31; @@ -4421,7 +4722,7 @@ void r5900le_device::handle_mmi0(uint32_t op) } } -void r5900le_device::handle_mmi1(uint32_t op) +void r5900_device::handle_mmi1(uint32_t op) { const int rs = (op >> 21) & 31; const int rt = (op >> 16) & 31; @@ -4785,7 +5086,7 @@ void r5900le_device::handle_mmi1(uint32_t op) } } -void r5900le_device::handle_mmi2(uint32_t op) +void r5900_device::handle_mmi2(uint32_t op) { const int rs = (op >> 21) & 31; const int rt = (op >> 16) & 31; @@ -4912,7 +5213,7 @@ void r5900le_device::handle_mmi2(uint32_t op) } } -void r5900le_device::handle_mmi3(uint32_t op) +void r5900_device::handle_mmi3(uint32_t op) { const int rs = (op >> 21) & 31; const int rt = (op >> 16) & 31; @@ -5011,7 +5312,7 @@ void mips3_device::handle_sdc2(uint32_t op) WDOUBLE(SIMMVAL+RSVAL32, get_cop2_reg(RTREG)); } -void r5900le_device::handle_ldc2(uint32_t op) +void r5900_device::handle_ldc2(uint32_t op) { /* LQC2 */ const uint32_t base = SIMMVAL + RSVAL32; @@ -5023,7 +5324,7 @@ void r5900le_device::handle_ldc2(uint32_t op) } } -void r5900le_device::handle_sdc2(uint32_t op) +void r5900_device::handle_sdc2(uint32_t op) { /* SQC2 */ const uint32_t base = SIMMVAL + RSVAL32; @@ -5034,15 +5335,6 @@ void r5900le_device::handle_sdc2(uint32_t op) } } -void mips3_device::burn_cycles(int32_t cycles) -{ - execute_burn(cycles); -} - -#if ENABLE_O2_DPRINTF -#include "o2dprintf.hxx" -#endif - void mips3_device::execute_run() { if (m_isdrc) @@ -5200,12 +5492,12 @@ void mips3_device::execute_run() { // Should actually use physical address m_core->cpr[0][COP0_LLAddr] = SIMMVAL + RSVAL32; - RTVAL64 = temp; + RTVAL64 = int64_t(int32_t(temp)); m_core->llbit = 1; if LL_BREAK machine().debug_break(); - break; } + break; case 0x31: /* LWC1 */ if (!(SR & SR_COP1)) { @@ -5226,18 +5518,18 @@ void mips3_device::execute_run() m_core->llbit = 1; if LL_BREAK machine().debug_break(); - break; } + break; case 0x35: /* LDC1 */ - if (!(SR & SR_COP1)) - { - m_badcop_value = 1; - generate_exception(EXCEPTION_BADCOP, 1); + if (!(SR & SR_COP1)) + { + m_badcop_value = 1; + generate_exception(EXCEPTION_BADCOP, 1); + break; + } + if (RDOUBLE(SIMMVAL+RSVAL32, &temp64)) + set_cop1_reg64(RTREG, temp64); break; - } - if (RDOUBLE(SIMMVAL+RSVAL32, &temp64)) - set_cop1_reg64(RTREG, temp64); - break; case 0x36: handle_ldc2(op); break; case 0x37: /* LD */ if (RDOUBLE(SIMMVAL+RSVAL32, &temp64) && RTREG) RTVAL64 = temp64; break; case 0x38: /* SC */ @@ -5293,12 +5585,10 @@ void mips3_device::execute_run() m_delayslot = false; m_core->icount--; -#if ENABLE_O2_DPRINTF - if (m_core->pc == 0xbfc04d74) + if (ENABLE_O2_DPRINTF && m_core->pc == 0xbfc04d74) { do_o2_dprintf((uint32_t)m_core->r[4], (uint32_t)m_core->r[5], (uint32_t)m_core->r[6], (uint32_t)m_core->r[7], (uint32_t)m_core->r[29] + 16); } -#endif #if ENABLE_EE_ELF_LOADER static bool elf_loaded = false; |