summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mips/mips3drc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mips/mips3drc.cpp')
-rw-r--r--src/devices/cpu/mips/mips3drc.cpp565
1 files changed, 362 insertions, 203 deletions
diff --git a/src/devices/cpu/mips/mips3drc.cpp b/src/devices/cpu/mips/mips3drc.cpp
index 0f1cd0a29d4..f682da6b212 100644
--- a/src/devices/cpu/mips/mips3drc.cpp
+++ b/src/devices/cpu/mips/mips3drc.cpp
@@ -24,7 +24,6 @@
***************************************************************************/
#include "emu.h"
-#include "debugger.h"
#include "mips3com.h"
#include "mips3fe.h"
#include "mips3dsm.h"
@@ -34,6 +33,11 @@
#include "cpu/drcumlsh.h"
+/* Use with STRICT_VERIFY to print debug info to console for extra validation checks */
+/* Set to 1 to activate and use MIPS3DRC_STRICT_VERIFY in the drc options */
+#define DEBUG_STRICT_VERIFY 0
+
+
/***************************************************************************
MACROS
***************************************************************************/
@@ -120,7 +124,7 @@ inline void mips3_device::load_fast_iregs(drcuml_block &block)
{
int regnum;
- for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+ for (regnum = 0; regnum < std::size(m_regmap); regnum++)
if (m_regmap[regnum].is_int_register())
UML_DMOV(block, ireg(m_regmap[regnum].ireg() - REG_I0), mem(&m_core->r[regnum]));
}
@@ -135,7 +139,7 @@ inline void mips3_device::save_fast_iregs(drcuml_block &block)
{
int regnum;
- for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+ for (regnum = 0; regnum < std::size(m_regmap); regnum++)
if (m_regmap[regnum].is_int_register())
UML_DMOV(block, mem(&m_core->r[regnum]), ireg(m_regmap[regnum].ireg() - REG_I0));
}
@@ -157,6 +161,15 @@ void mips3_device::mips3drc_set_options(uint32_t options)
}
/*-------------------------------------------------
+ mips3drc_get_options - return current DRC options
+-------------------------------------------------*/
+
+uint32_t mips3_device::mips3drc_get_options()
+{
+ return m_drcoptions;
+}
+
+/*-------------------------------------------------
mips3drc_clears_fastram - clears fastram
region starting at index select_start
-------------------------------------------------*/
@@ -174,7 +187,7 @@ void mips3_device::clear_fastram(uint32_t select_start)
void mips3_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base)
{
- if (m_fastram_select < ARRAY_LENGTH(m_fastram))
+ if (m_fastram_select < std::size(m_fastram))
{
m_fastram[m_fastram_select].start = start;
m_fastram[m_fastram_select].end = end;
@@ -197,7 +210,7 @@ void mips3_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void
void mips3_device::mips3drc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles)
{
if (!allow_drc()) return;
- if (m_hotspot_select < ARRAY_LENGTH(m_hotspot))
+ if (m_hotspot_select < std::size(m_hotspot))
{
m_hotspot[m_hotspot_select].pc = pc;
m_hotspot[m_hotspot_select].opcode = opcode;
@@ -226,45 +239,55 @@ void mips3_device::code_flush_cache()
try
{
- /* generate the entry point and out-of-cycles handlers */
- static_generate_entry_point();
- static_generate_nocode_handler();
- static_generate_out_of_cycles();
- static_generate_tlb_mismatch();
-
- /* append exception handlers for various types */
- static_generate_exception(EXCEPTION_INTERRUPT, true, "exception_interrupt");
- static_generate_exception(EXCEPTION_INTERRUPT, false, "exception_interrupt_norecover");
- static_generate_exception(EXCEPTION_TLBMOD, true, "exception_tlbmod");
- static_generate_exception(EXCEPTION_TLBLOAD, true, "exception_tlbload");
- static_generate_exception(EXCEPTION_TLBSTORE, true, "exception_tlbstore");
- static_generate_exception(EXCEPTION_TLBLOAD_FILL, true, "exception_tlbload_fill");
- static_generate_exception(EXCEPTION_TLBSTORE_FILL, true, "exception_tlbstore_fill");
- static_generate_exception(EXCEPTION_ADDRLOAD, true, "exception_addrload");
- static_generate_exception(EXCEPTION_ADDRSTORE, true, "exception_addrstore");
- static_generate_exception(EXCEPTION_SYSCALL, true, "exception_syscall");
- static_generate_exception(EXCEPTION_BREAK, true, "exception_break");
- static_generate_exception(EXCEPTION_INVALIDOP, true, "exception_invalidop");
- static_generate_exception(EXCEPTION_BADCOP, true, "exception_badcop");
- static_generate_exception(EXCEPTION_OVERFLOW, true, "exception_overflow");
- static_generate_exception(EXCEPTION_TRAP, true, "exception_trap");
- static_generate_exception(EXCEPTION_FPE, true, "exception_fpe");
+ {
+ drcuml_block &block(m_drcuml->begin_block(1024));
+ int label = 1;
+
+ /* generate the entry point and out-of-cycles handlers */
+ static_generate_entry_point(block, label);
+ static_generate_nocode_handler(block, label);
+ static_generate_out_of_cycles(block, label);
+ static_generate_tlb_mismatch(block, label);
+
+ /* append exception handlers for various types */
+ static_generate_exception(block, label, EXCEPTION_INTERRUPT, true, "exception_interrupt");
+ static_generate_exception(block, label, EXCEPTION_INTERRUPT, false, "exception_interrupt_norecover");
+ static_generate_exception(block, label, EXCEPTION_TLBMOD, true, "exception_tlbmod");
+ static_generate_exception(block, label, EXCEPTION_TLBLOAD, true, "exception_tlbload");
+ static_generate_exception(block, label, EXCEPTION_TLBSTORE, true, "exception_tlbstore");
+ static_generate_exception(block, label, EXCEPTION_TLBLOAD_FILL, true, "exception_tlbload_fill");
+ static_generate_exception(block, label, EXCEPTION_TLBSTORE_FILL, true, "exception_tlbstore_fill");
+ static_generate_exception(block, label, EXCEPTION_ADDRLOAD, true, "exception_addrload");
+ static_generate_exception(block, label, EXCEPTION_ADDRSTORE, true, "exception_addrstore");
+ static_generate_exception(block, label, EXCEPTION_SYSCALL, true, "exception_syscall");
+ static_generate_exception(block, label, EXCEPTION_BREAK, true, "exception_break");
+ static_generate_exception(block, label, EXCEPTION_INVALIDOP, true, "exception_invalidop");
+ static_generate_exception(block, label, EXCEPTION_BADCOP, true, "exception_badcop");
+ static_generate_exception(block, label, EXCEPTION_OVERFLOW, true, "exception_overflow");
+ static_generate_exception(block, label, EXCEPTION_TRAP, true, "exception_trap");
+ static_generate_exception(block, label, EXCEPTION_FPE, true, "exception_fpe");
+
+ block.end();
+ }
/* add subroutines for memory accesses */
for (mode = 0; mode < 3; mode++)
{
- static_generate_memory_accessor(mode, 1, false, false, "read8", m_read8[mode]);
- static_generate_memory_accessor(mode, 1, true, false, "write8", m_write8[mode]);
- static_generate_memory_accessor(mode, 2, false, false, "read16", m_read16[mode]);
- static_generate_memory_accessor(mode, 2, true, false, "write16", m_write16[mode]);
- static_generate_memory_accessor(mode, 4, false, false, "read32", m_read32[mode]);
- static_generate_memory_accessor(mode, 4, false, true, "read32mask", m_read32mask[mode]);
- static_generate_memory_accessor(mode, 4, true, false, "write32", m_write32[mode]);
- static_generate_memory_accessor(mode, 4, true, true, "write32mask", m_write32mask[mode]);
- static_generate_memory_accessor(mode, 8, false, false, "read64", m_read64[mode]);
- static_generate_memory_accessor(mode, 8, false, true, "read64mask", m_read64mask[mode]);
- static_generate_memory_accessor(mode, 8, true, false, "write64", m_write64[mode]);
- static_generate_memory_accessor(mode, 8, true, true, "write64mask", m_write64mask[mode]);
+ drcuml_block &block(m_drcuml->begin_block(1024));
+ int label = 1;
+ static_generate_memory_accessor(block, label, mode, 1, false, false, "read8", m_read8[mode]);
+ static_generate_memory_accessor(block, label, mode, 1, true, false, "write8", m_write8[mode]);
+ static_generate_memory_accessor(block, label, mode, 2, false, false, "read16", m_read16[mode]);
+ static_generate_memory_accessor(block, label, mode, 2, true, false, "write16", m_write16[mode]);
+ static_generate_memory_accessor(block, label, mode, 4, false, false, "read32", m_read32[mode]);
+ static_generate_memory_accessor(block, label, mode, 4, false, true, "read32mask", m_read32mask[mode]);
+ static_generate_memory_accessor(block, label, mode, 4, true, false, "write32", m_write32[mode]);
+ static_generate_memory_accessor(block, label, mode, 4, true, true, "write32mask", m_write32mask[mode]);
+ static_generate_memory_accessor(block, label, mode, 8, false, false, "read64", m_read64[mode]);
+ static_generate_memory_accessor(block, label, mode, 8, false, true, "read64mask", m_read64mask[mode]);
+ static_generate_memory_accessor(block, label, mode, 8, true, false, "write64", m_write64[mode]);
+ static_generate_memory_accessor(block, label, mode, 8, true, true, "write64mask", m_write64mask[mode]);
+ block.end();
}
}
catch (drcuml_block::abort_compilation &)
@@ -283,13 +306,16 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc)
{
compiler_state compiler = { 0 };
const opcode_desc *seqhead, *seqlast;
+ const opcode_desc *codelast;
const opcode_desc *desclist;
bool override = false;
- g_profiler.start(PROFILER_DRC_COMPILE);
+ auto profile = g_profiler.start(PROFILER_DRC_COMPILE);
/* get a description of this sequence */
desclist = m_drcfe->describe_code(pc);
+ /* get last instruction of the code (potentially used in generate_checksum) */
+ codelast = m_drcfe->get_last();
if (m_drcuml->logging() || m_drcuml->logging_native())
log_opcode_desc(desclist, 0);
@@ -341,7 +367,7 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc)
/* validate this code block if we're not pointing into ROM */
if (m_program->get_write_ptr(seqhead->physpc) != nullptr)
- generate_checksum_block(block, compiler, seqhead, seqlast);
+ generate_checksum_block(block, compiler, seqhead, seqlast, codelast);
/* label this instruction, if it may be jumped to locally */
if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
@@ -379,7 +405,6 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc)
/* end the sequence */
block.end();
- g_profiler.stop();
succeeded = true;
}
catch (drcuml_block::abort_compilation &)
@@ -570,44 +595,40 @@ static void cfunc_unimplemented(void *param)
static entry point
-------------------------------------------------*/
-void mips3_device::static_generate_entry_point()
+void mips3_device::static_generate_entry_point(drcuml_block &block, int &label)
{
- uml::code_label const skip = 1;
-
- drcuml_block &block(m_drcuml->begin_block(20));
+ uml::code_label const skip = label++;
/* forward references */
alloc_handle(*m_drcuml, m_exception_norecover[EXCEPTION_INTERRUPT], "interrupt_norecover");
alloc_handle(*m_drcuml, m_nocode, "nocode");
alloc_handle(*m_drcuml, m_entry, "entry");
- UML_HANDLE(block, *m_entry); // handle entry
+ UML_HANDLE(block, *m_entry); // handle entry
/* reset the FPU mode */
- UML_AND(block, I0, CCR132(31), 3); // and i0,ccr1[31],3
- UML_LOAD(block, I0, &m_fpmode[0], I0, SIZE_BYTE, SCALE_x1);// load i0,fpmode,i0,byte
- UML_SETFMOD(block, I0); // setfmod i0
+ UML_AND(block, I0, CCR132(31), 3); // and i0,ccr1[31],3
+ UML_LOAD(block, I0, &m_fpmode[0], I0, SIZE_BYTE, SCALE_x1); // load i0,fpmode,i0,byte
+ UML_SETFMOD(block, I0); // setfmod i0
/* load fast integer registers */
load_fast_iregs(block);
/* check for interrupts */
UML_AND(block, I0, CPR032(COP0_Cause), CPR032(COP0_Status)); // and i0,[Cause],[Status]
- UML_AND(block, I0, I0, 0xfc00); // and i0,i0,0xfc00,Z
- UML_JMPc(block, COND_Z, skip); // jmp skip,Z
+ UML_AND(block, I0, I0, 0xfc00); // and i0,i0,0xfc00,Z
+ UML_JMPc(block, COND_Z, skip); // jmp skip,Z
UML_TEST(block, CPR032(COP0_Status), SR_IE); // test [Status],SR_IE
- UML_JMPc(block, COND_Z, skip); // jmp skip,Z
+ UML_JMPc(block, COND_Z, skip); // jmp skip,Z
UML_TEST(block, CPR032(COP0_Status), SR_EXL | SR_ERL); // test [Status],SR_EXL | SR_ERL
- UML_JMPc(block, COND_NZ, skip); // jmp skip,NZ
- UML_MOV(block, I0, mem(&m_core->pc)); // mov i0,pc
- UML_MOV(block, I1, 0); // mov i1,0
- UML_CALLH(block, *m_exception_norecover[EXCEPTION_INTERRUPT]); // callh exception_norecover
+ UML_JMPc(block, COND_NZ, skip); // jmp skip,NZ
+ UML_MOV(block, I0, mem(&m_core->pc)); // mov i0,pc
+ UML_MOV(block, I1, 0); // mov i1,0
+ UML_CALLH(block, *m_exception_norecover[EXCEPTION_INTERRUPT]); // callh exception_norecover
UML_LABEL(block, skip); // skip:
/* generate a hash jump via the current mode and PC */
- UML_HASHJMP(block, mem(&m_core->mode), mem(&m_core->pc), *m_nocode);
- // hashjmp <mode>,<pc>,nocode
- block.end();
+ UML_HASHJMP(block, mem(&m_core->mode), mem(&m_core->pc), *m_nocode); // hashjmp <mode>,<pc>,nocode
}
@@ -616,11 +637,8 @@ void mips3_device::static_generate_entry_point()
exception handler for "out of code"
-------------------------------------------------*/
-void mips3_device::static_generate_nocode_handler()
+void mips3_device::static_generate_nocode_handler(drcuml_block &block, int &label)
{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(10));
-
/* generate a hash jump via the current mode and PC */
alloc_handle(*m_drcuml, m_nocode, "nocode");
UML_HANDLE(block, *m_nocode); // handle nocode
@@ -628,8 +646,6 @@ void mips3_device::static_generate_nocode_handler()
UML_MOV(block, mem(&m_core->pc), I0); // mov [pc],i0
save_fast_iregs(block);
UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE
-
- block.end();
}
@@ -638,11 +654,8 @@ void mips3_device::static_generate_nocode_handler()
out of cycles exception handler
-------------------------------------------------*/
-void mips3_device::static_generate_out_of_cycles()
+void mips3_device::static_generate_out_of_cycles(drcuml_block &block, int &label)
{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(10));
-
/* generate a hash jump via the current mode and PC */
alloc_handle(*m_drcuml, m_out_of_cycles, "out_of_cycles");
UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles
@@ -650,8 +663,6 @@ void mips3_device::static_generate_out_of_cycles()
UML_MOV(block, mem(&m_core->pc), I0); // mov <pc>,i0
save_fast_iregs(block);
UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES
-
- block.end();
}
@@ -660,15 +671,14 @@ void mips3_device::static_generate_out_of_cycles()
TLB mismatch handler
-------------------------------------------------*/
-void mips3_device::static_generate_tlb_mismatch()
+void mips3_device::static_generate_tlb_mismatch(drcuml_block &block, int &label)
{
+ uml::code_label const skip = label++;
+
/* forward references */
alloc_handle(*m_drcuml, m_exception[EXCEPTION_TLBLOAD], "exception_tlbload");
alloc_handle(*m_drcuml, m_exception[EXCEPTION_TLBLOAD_FILL], "exception_tlbload_fill");
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(20));
-
/* generate a hash jump via the current mode and PC */
alloc_handle(*m_drcuml, m_tlb_mismatch, "tlb_mismatch");
UML_HANDLE(block, *m_tlb_mismatch); // handle tlb_mismatch
@@ -687,12 +697,12 @@ void mips3_device::static_generate_tlb_mismatch()
UML_MOV(block, mem(&m_core->arg1), I1); // mov [arg1],i1
UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
}
- UML_TEST(block, I1, VTLB_FETCH_ALLOWED); // test i1,VTLB_FETCH_ALLOWED
- UML_JMPc(block, COND_NZ, 1); // jmp 1,nz
- UML_TEST(block, I1, VTLB_FLAG_FIXED); // test i1,VTLB_FLAG_FIXED
+ UML_TEST(block, I1, FETCH_ALLOWED); // test i1,FETCH_ALLOWED
+ UML_JMPc(block, COND_NZ, skip); // jmp skip,nz
+ UML_TEST(block, I1, FLAG_FIXED); // test i1,FLAG_FIXED
UML_EXHc(block, COND_NZ, *m_exception[EXCEPTION_TLBLOAD], I0); // exh exception[TLBLOAD],i0,nz
UML_EXH(block, *m_exception[EXCEPTION_TLBLOAD_FILL], I0); // exh exception[TLBLOAD_FILL],i0
- UML_LABEL(block, 1); // 1:
+ UML_LABEL(block, skip); // skip:
save_fast_iregs(block);
// the saved PC may be set 1 instruction back with the low bit set to indicate
@@ -702,8 +712,6 @@ void mips3_device::static_generate_tlb_mismatch()
UML_MOV(block, mem(&m_core->pc), I0); // mov i0,[pc]
UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE
-
- block.end();
}
@@ -712,12 +720,12 @@ void mips3_device::static_generate_tlb_mismatch()
exception handler
-------------------------------------------------*/
-void mips3_device::static_generate_exception(uint8_t exception, int recover, const char *name)
+void mips3_device::static_generate_exception(drcuml_block &block, int &label, uint8_t exception, int recover, const char *name)
{
uml::code_handle *&exception_handle = recover ? m_exception[exception] : m_exception_norecover[exception];
uint32_t offset = 0x180;
- uml::code_label const next = 1;
- uml::code_label const skip = 2;
+ uml::code_label const next = label++;
+ uml::code_label const skip = label++;
/* translate our fake fill exceptions into real exceptions */
if (exception == EXCEPTION_TLBLOAD_FILL || exception == EXCEPTION_TLBSTORE_FILL)
@@ -726,9 +734,6 @@ void mips3_device::static_generate_exception(uint8_t exception, int recover, con
exception = (exception - EXCEPTION_TLBLOAD_FILL) + EXCEPTION_TLBLOAD;
}
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(1024));
-
/* add a global entry for this */
alloc_handle(*m_drcuml, exception_handle, name);
UML_HANDLE(block, *exception_handle); // handle name
@@ -741,7 +746,7 @@ void mips3_device::static_generate_exception(uint8_t exception, int recover, con
UML_MOV(block, CPR032(COP0_BadVAddr), I0); // mov [BadVAddr],i0
}
- if (exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE)
+ if (exception == EXCEPTION_TLBMOD || exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE)
{
/* set the upper bits of EntryHi and the lower bits of Context to the fault page */
UML_ROLINS(block, CPR032(COP0_EntryHi), I0, 0, 0xffffe000); // rolins [EntryHi],i0,0,0xffffe000
@@ -783,7 +788,7 @@ void mips3_device::static_generate_exception(uint8_t exception, int recover, con
}
/* set EXL in the SR */
- UML_OR(block, I0, CPR032(COP0_Status), SR_EXL); // or i0,[Status],SR_EXL
+ UML_OR(block, I0, CPR032(COP0_Status), SR_EXL); // or i0,[Status],SR_EXL
UML_MOV(block, CPR032(COP0_Status), I0); // mov [Status],i0
generate_update_mode(block);
@@ -791,142 +796,126 @@ void mips3_device::static_generate_exception(uint8_t exception, int recover, con
if ((PRINTF_EXCEPTIONS && exception != EXCEPTION_INTERRUPT && exception != EXCEPTION_SYSCALL) ||
(PRINTF_MMU && (exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE)))
{
- UML_CALLC(block, cfunc_printf_exception, this); // callc cfunc_printf_exception,nullptr
+ UML_CALLC(block, cfunc_printf_exception, this); // callc cfunc_printf_exception,nullptr
//UML_CALLC(block, cfunc_debug_break, this); // callc cfunc_debug_break,nullptr
}
/* choose our target PC */
- UML_ADD(block, I0, I3, 0xbfc00200); // add i0,i3,0xbfc00200
- UML_TEST(block, CPR032(COP0_Status), SR_BEV); // test CPR032(COP0_Status),SR_BEV
- UML_JMPc(block, COND_NZ, skip); // jnz <skip>
- UML_ADD(block, I0, I3, 0x80000000); // add i0,i3,0x80000000,z
+ UML_ADD(block, I0, I3, 0xbfc00200); // add i0,i3,0xbfc00200
+ UML_TEST(block, CPR032(COP0_Status), SR_BEV); // test CPR032(COP0_Status),SR_BEV
+ UML_JMPc(block, COND_NZ, skip); // jnz <skip>
+ UML_ADD(block, I0, I3, 0x80000000); // add i0,i3,0x80000000,z
UML_LABEL(block, skip); // <skip>:
/* adjust cycles */
- UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I1); // sub icount,icount,cycles,S
- UML_EXHc(block, COND_S, *m_out_of_cycles, I0); // exh out_of_cycles,i0
-
- UML_HASHJMP(block, mem(&m_core->mode), I0, *m_nocode);// hashjmp <mode>,i0,nocode
+ UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I1); // sub icount,icount,cycles,S
+ UML_EXHc(block, COND_S, *m_out_of_cycles, I0); // exh out_of_cycles,i0
- block.end();
+ UML_HASHJMP(block, mem(&m_core->mode), I0, *m_nocode); // hashjmp <mode>,i0,nocode
}
/*------------------------------------------------------------------
- static_generate_memory_accessor
+ static_generate_memory_mode_checks
------------------------------------------------------------------*/
-void mips3_device::static_generate_memory_accessor(int mode, int size, int iswrite, int ismasked, const char *name, uml::code_handle *&handleptr)
+void mips3_device::static_generate_memory_mode_checks(drcuml_block &block, uml::code_handle &exception_addrerr, int &label, int mode)
{
- /* on entry, address is in I0; data for writes is in I1; mask for accesses is in I2 */
- /* on exit, read result is in I0 */
- /* routine trashes I0-I3 */
- uml::code_handle &exception_tlb = *m_exception[iswrite ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD];
- uml::code_handle &exception_tlbfill = *m_exception[iswrite ? EXCEPTION_TLBSTORE_FILL : EXCEPTION_TLBLOAD_FILL];
- uml::code_handle &exception_addrerr = *m_exception[iswrite ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD];
- int tlbmiss = 0;
- int label = 1;
- int ramnum;
-
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(1024));
-
- /* add a global entry for this */
- alloc_handle(*m_drcuml, handleptr, name);
- UML_HANDLE(block, *handleptr); // handle handleptr
-
/* user mode? generate address exception if top bit is set */
if (mode == MODE_USER)
{
- UML_TEST(block, I0, 0x80000000); // test i0,0x80000000
- UML_EXHc(block, COND_NZ, exception_addrerr, I0); // exh addrerr,i0,nz
+ UML_TEST(block, I0, 0x80000000); // test i0,0x80000000
+ UML_EXHc(block, COND_NZ, exception_addrerr, I0); // exh addrerr,i0,nz
}
/* supervisor mode? generate address exception if not in user space or in $C0000000-DFFFFFFF */
if (mode == MODE_SUPER)
{
int addrok;
- UML_TEST(block, I0, 0x80000000); // test i0,0x80000000
+ UML_TEST(block, I0, 0x80000000); // test i0,0x80000000
UML_JMPc(block, COND_Z, addrok = label++); // jz addrok
- UML_SHR(block, I3, I0, 29); // shr i3,i0,29
- UML_CMP(block, I3, 6); // cmp i3,6
+ UML_SHR(block, I3, I0, 29); // shr i3,i0,29
+ UML_CMP(block, I3, 6); // cmp i3,6
UML_EXHc(block, COND_NE, exception_addrerr, I0); // exh addrerr,i0,ne
- UML_LABEL(block, addrok); // addrok:
+ UML_LABEL(block, addrok); // addrok:
}
+}
- /* general case: assume paging and perform a translation */
- UML_SHR(block, I3, I0, 12); // shr i3,i0,12
- UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb_table],i3,dword
- UML_TEST(block, I3, iswrite ? VTLB_WRITE_ALLOWED : VTLB_READ_ALLOWED);// test i3,iswrite ? VTLB_WRITE_ALLOWED : VTLB_READ_ALLOWED
- UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
- UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
- for (ramnum = 0; ramnum < m_fastram_select; ramnum++)
+/*------------------------------------------------------------------
+ static_generate_fastram_accessor
+------------------------------------------------------------------*/
+
+void mips3_device::static_generate_fastram_accessor(drcuml_block &block, int &label, int size, bool iswrite, bool ismasked)
+{
+ if (!debugger_enabled())
+ {
+ for (int ramnum = 0; ramnum < m_fastram_select; ramnum++)
+ {
if (!(iswrite && m_fastram[ramnum].readonly))
{
void *fastbase = (uint8_t *)m_fastram[ramnum].base - m_fastram[ramnum].start;
uint32_t skip = label++;
if (m_fastram[ramnum].end != 0xffffffff)
{
- UML_CMP(block, I0, m_fastram[ramnum].end); // cmp i0,end
- UML_JMPc(block, COND_A, skip); // ja skip
+ UML_CMP(block, I0, m_fastram[ramnum].end); // cmp i0,end
+ UML_JMPc(block, COND_A, skip); // ja skip
}
if (m_fastram[ramnum].start != 0x00000000)
{
- UML_CMP(block, I0, m_fastram[ramnum].start);// cmp i0,fastram_start
- UML_JMPc(block, COND_B, skip); // jb skip
+ UML_CMP(block, I0, m_fastram[ramnum].start); // cmp i0,fastram_start
+ UML_JMPc(block, COND_B, skip); // jb skip
}
if (!iswrite)
{
if (size == 1)
{
UML_XOR(block, I0, I0, m_bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0));
- // xor i0,i0,bytexor
- UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte
+ // xor i0,i0,bytexor
+ UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte
}
else if (size == 2)
{
UML_XOR(block, I0, I0, m_bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0));
- // xor i0,i0,wordxor
- UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1
+ // xor i0,i0,wordxor
+ UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1
}
else if (size == 4)
{
- UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1
+ UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1
}
else if (size == 8)
{
- UML_DLOAD(block, I0, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i0,fastbase,i0,qword_x1
+ UML_DLOAD(block, I0, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i0,fastbase,i0,qword_x1
UML_DROR(block, I0, I0, 32 * (m_bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0)));
- // dror i0,i0,32*bytexor
+ // dror i0,i0,32*bytexor
}
- UML_RET(block); // ret
+ UML_RET(block); // ret
}
else
{
if (size == 1)
{
UML_XOR(block, I0, I0, m_bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0));
- // xor i0,i0,bytexor
- UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1);// store fastbase,i0,i1,byte
+ // xor i0,i0,bytexor
+ UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1); // store fastbase,i0,i1,byte
}
else if (size == 2)
{
UML_XOR(block, I0, I0, m_bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0));
- // xor i0,i0,wordxor
- UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1);// store fastbase,i0,i1,word_x1
+ // xor i0,i0,wordxor
+ UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1); // store fastbase,i0,i1,word_x1
}
else if (size == 4)
{
if (ismasked)
{
- UML_LOAD(block, I3, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i3,fastbase,i0,dword_x1
- UML_ROLINS(block, I3, I1, 0, I2); // rolins i3,i1,0,i2
- UML_STORE(block, fastbase, I0, I3, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i3,dword_x1
+ UML_LOAD(block, I3, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i3,fastbase,i0,dword_x1
+ UML_ROLINS(block, I3, I1, 0, I2); // rolins i3,i1,0,i2
+ UML_STORE(block, fastbase, I0, I3, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i3,dword_x1
}
else
- UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1
+ UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1
}
else if (size == 8)
{
@@ -936,8 +925,8 @@ void mips3_device::static_generate_memory_accessor(int mode, int size, int iswri
{
UML_DROR(block, I2, I2, 32 * (m_bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0)));
// dror i2,i2,32*bytexor
- UML_DLOAD(block, I3, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i3,fastbase,i0,qword_x1
- UML_DROLINS(block, I3, I1, 0, I2); // drolins i3,i1,0,i2
+ UML_DLOAD(block, I3, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i3,fastbase,i0,qword_x1
+ UML_DROLINS(block, I3, I1, 0, I2); // drolins i3,i1,0,i2
UML_DSTORE(block, fastbase, I0, I3, SIZE_QWORD, SCALE_x1); // dstore fastbase,i0,i3,qword_x1
}
else
@@ -946,9 +935,19 @@ void mips3_device::static_generate_memory_accessor(int mode, int size, int iswri
UML_RET(block); // ret
}
- UML_LABEL(block, skip); // skip:
+ UML_LABEL(block, skip); // skip:
}
+ }
+ }
+}
+
+
+/*------------------------------------------------------------------
+ static_generate_memory_rw
+------------------------------------------------------------------*/
+void mips3_device::static_generate_memory_rw(drcuml_block &block, int size, bool iswrite, bool ismasked)
+{
switch (size)
{
case 1:
@@ -969,9 +968,9 @@ void mips3_device::static_generate_memory_accessor(int mode, int size, int iswri
if (iswrite)
{
if (!ismasked)
- UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write i0,i1,program_dword
+ UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write i0,i1,program_dword
else
- UML_WRITEM(block, I0, I1, I2, SIZE_DWORD, SPACE_PROGRAM); // writem i0,i1,i2,program_dword
+ UML_WRITEM(block, I0, I1, I2, SIZE_DWORD, SPACE_PROGRAM); // writem i0,i1,i2,program_dword
}
else
{
@@ -986,38 +985,90 @@ void mips3_device::static_generate_memory_accessor(int mode, int size, int iswri
if (iswrite)
{
if (!ismasked)
- UML_DWRITE(block, I0, I1, SIZE_QWORD, SPACE_PROGRAM); // dwrite i0,i1,program_qword
+ UML_DWRITE(block, I0, I1, SIZE_QWORD, SPACE_PROGRAM); // dwrite i0,i1,program_qword
else
- UML_DWRITEM(block, I0, I1, I2, SIZE_QWORD, SPACE_PROGRAM); // dwritem i0,i1,i2,program_qword
+ UML_DWRITEM(block, I0, I1, I2, SIZE_QWORD, SPACE_PROGRAM); // dwritem i0,i1,i2,program_qword
}
else
{
if (!ismasked)
- UML_DREAD(block, I0, I0, SIZE_QWORD, SPACE_PROGRAM); // dread i0,i0,program_qword
+ UML_DREAD(block, I0, I0, SIZE_QWORD, SPACE_PROGRAM); // dread i0,i0,program_qword
else
- UML_DREADM(block, I0, I0, I2, SIZE_QWORD, SPACE_PROGRAM); // dreadm i0,i0,i2,program_qword
+ UML_DREADM(block, I0, I0, I2, SIZE_QWORD, SPACE_PROGRAM); // dreadm i0,i0,i2,program_qword
}
break;
}
UML_RET(block); // ret
+}
- if (tlbmiss != 0)
+
+/*------------------------------------------------------------------
+ static_generate_memory_accessor
+------------------------------------------------------------------*/
+
+void mips3_device::static_generate_memory_accessor(drcuml_block &block, int &label, int mode, int size, bool iswrite, bool ismasked, const char *name, uml::code_handle *&handleptr)
+{
+ /* on entry, address is in I0; data for writes is in I1; mask for accesses is in I2 */
+ /* on exit, read result is in I0 */
+ /* routine trashes I0-I3 */
+ uml::code_handle &exception_tlb = *m_exception[iswrite ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD];
+ uml::code_handle &exception_tlbfill = *m_exception[iswrite ? EXCEPTION_TLBSTORE_FILL : EXCEPTION_TLBLOAD_FILL];
+ uml::code_handle &exception_addrerr = *m_exception[iswrite ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD];
+ int tlbmiss = 0;
+
+ /* add a global entry for this */
+ alloc_handle(*m_drcuml, handleptr, name);
+ UML_HANDLE(block, *handleptr); // handle handleptr
+
+ static_generate_memory_mode_checks(block, exception_addrerr, label, mode);
+
+ /* general case: assume paging and perform a translation */
+ UML_SHR(block, I3, I0, 12); // shr i3,i0,12
+ UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4); // load i3,[vtlb_table],i3,dword
+ UML_TEST(block, I3, iswrite ? WRITE_ALLOWED : READ_ALLOWED); // test i3,iswrite ? WRITE_ALLOWED : READ_ALLOWED
+ UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
+ UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
+
+ static_generate_fastram_accessor(block, label, size, iswrite, ismasked);
+ static_generate_memory_rw(block, size, iswrite, ismasked);
+
+ UML_LABEL(block, tlbmiss); // tlbmiss:
+ if (iswrite)
{
- UML_LABEL(block, tlbmiss); // tlbmiss:
- if (iswrite)
- {
- UML_TEST(block, I3, VTLB_READ_ALLOWED); // test i3,VTLB_READ_ALLOWED
- UML_EXHc(block, COND_NZ, *m_exception[EXCEPTION_TLBMOD], I0);
- // exh tlbmod,i0,nz
- }
- UML_TEST(block, I3, VTLB_FLAG_FIXED); // test i3,VTLB_FLAG_FIXED
- UML_EXHc(block, COND_NZ, exception_tlb, I0); // exh tlb,i0,nz
- UML_EXH(block, exception_tlbfill, I0); // exh tlbfill,i0
+ UML_TEST(block, I3, READ_ALLOWED); // test i3,READ_ALLOWED
+ UML_EXHc(block, COND_NZ, *m_exception[EXCEPTION_TLBMOD], I0); // exh tlbmod,i0,nz
}
-
- block.end();
+ UML_TEST(block, I3, FLAG_FIXED); // test i3,FLAG_FIXED
+ UML_EXHc(block, COND_NZ, exception_tlb, I0); // exh tlb,i0,nz
+ UML_EXH(block, exception_tlbfill, I0); // exh tlbfill,i0
}
+void r4650_device::static_generate_memory_accessor(drcuml_block &block, int &label, int mode, int size, bool iswrite, bool ismasked, const char *name, uml::code_handle *&handleptr)
+{
+ /* on entry, address is in I0; data for writes is in I1; mask for accesses is in I2 */
+ /* on exit, read result is in I0 */
+ /* routine trashes I0-I3 */
+ uml::code_handle &exception_addrerr = *m_exception[iswrite ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD];
+
+ /* add a global entry for this */
+ alloc_handle(*m_drcuml, handleptr, name);
+ UML_HANDLE(block, *handleptr); // handle handleptr
+
+ static_generate_memory_mode_checks(block, exception_addrerr, label, mode);
+
+ if (mode == MODE_USER)
+ {
+ int addrok;
+ UML_CMP(block, I0, CPR032(COP0_R4650_DBound)); // cmp i0,CPR0[DBound]
+ UML_JMPc(block, COND_LE, addrok = label++); // jle addrok
+ UML_EXHc(block, COND_G, exception_addrerr, I0); // exh addrerr,i0,ne
+ UML_LABEL(block, addrok); // addrok:
+ UML_ADD(block, I0, I0, CPR032(COP0_R4650_DBase)); // add i0,i0,CPR0[DBase]
+ }
+
+ static_generate_fastram_accessor(block, label, size, iswrite, ismasked);
+ static_generate_memory_rw(block, size, iswrite, ismasked);
+}
/***************************************************************************
@@ -1098,7 +1149,7 @@ void mips3_device::generate_update_cycles(drcuml_block &block, compiler_state &c
validate a sequence of opcodes
-------------------------------------------------*/
-void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast)
+void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast, const opcode_desc *codelast)
{
const opcode_desc *curdesc;
if (m_drcuml->logging())
@@ -1147,35 +1198,130 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &
#else
uint32_t sum = 0;
const void *base = m_prptr(seqhead->physpc);
- uint32_t low_bits = (seqhead->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
+ const uint32_t data_bits_mask = (m_data_bits == 64 ? 4 : 0);
+ const uint32_t last_physpc = codelast->physpc;
+ uint32_t low_bits = (seqhead->physpc & data_bits_mask) ^ m_dword_xor;
UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i0,base,0,dword
sum += seqhead->opptr.l[0];
- for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
+ if ((m_drcoptions & MIPS3DRC_EXTRA_INSTR_CHECK) && !(codelast->flags & OPFLAG_VIRTUAL_NOOP) && last_physpc != seqhead->physpc)
{
- if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
+ base = m_prptr(last_physpc);
+ assert(base != nullptr);
+ low_bits = (last_physpc & data_bits_mask) ^ m_dword_xor;
+ UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ UML_ADD(block, I0, I0, I1); // add i0,i0,i1
+ sum += codelast->opptr.l[0];
+ }
+ if (!(m_drcoptions & MIPS3DRC_EXTRA_INSTR_CHECK))
+ {
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
{
- base = m_prptr(curdesc->physpc);
- assert(base != nullptr);
- uint32_t low_bits = (curdesc->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
- UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
- UML_ADD(block, I0, I0, I1); // add i0,i0,i1
- sum += curdesc->opptr.l[0];
-
- if (curdesc->delay.first() != nullptr
- && !(curdesc->delay.first()->flags & OPFLAG_VIRTUAL_NOOP)
- && (curdesc == seqlast || (curdesc->next() != nullptr && curdesc->next()->physpc != curdesc->delay.first()->physpc)))
+ if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
- base = m_prptr(curdesc->delay.first()->physpc);
+ base = m_prptr(curdesc->physpc);
assert(base != nullptr);
- uint32_t low_bits = (curdesc->delay.first()->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
- UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
- UML_ADD(block, I0, I0, I1); // add i0,i0,i1
- sum += curdesc->delay.first()->opptr.l[0];
+ low_bits = (curdesc->physpc & data_bits_mask) ^ m_dword_xor;
+ UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ UML_ADD(block, I0, I0, I1); // add i0,i0,i1
+ sum += curdesc->opptr.l[0];
+
+ if (curdesc->delay.first() != nullptr
+ && !(curdesc->delay.first()->flags & OPFLAG_VIRTUAL_NOOP)
+ && (curdesc == seqlast || (curdesc->next() != nullptr && curdesc->next()->physpc != curdesc->delay.first()->physpc)))
+ {
+ base = m_prptr(curdesc->delay.first()->physpc);
+ assert(base != nullptr);
+ low_bits = (curdesc->delay.first()->physpc & data_bits_mask) ^ m_dword_xor;
+ UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ UML_ADD(block, I0, I0, I1); // add i0,i0,i1
+ sum += curdesc->delay.first()->opptr.l[0];
+ }
+ }
+ }
+ }
+ else
+ {
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
+ {
+ if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ // Skip the last if it was already included above
+ if (curdesc->physpc != last_physpc)
+ {
+ base = m_prptr(curdesc->physpc);
+ assert(base != nullptr);
+ low_bits = (curdesc->physpc & data_bits_mask) ^ m_dword_xor;
+ UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ UML_ADD(block, I0, I0, I1); // add i0,i0,i1
+ sum += curdesc->opptr.l[0];
+ }
+
+ if (curdesc->delay.first() != nullptr
+ && !(curdesc->delay.first()->flags & OPFLAG_VIRTUAL_NOOP)
+ && (curdesc == seqlast || (curdesc->next() != nullptr && curdesc->next()->physpc != curdesc->delay.first()->physpc)))
+ {
+ base = m_prptr(curdesc->delay.first()->physpc);
+ assert(base != nullptr);
+ low_bits = (curdesc->delay.first()->physpc & data_bits_mask) ^ m_dword_xor;
+ UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ UML_ADD(block, I0, I0, I1); // add i0,i0,i1
+ sum += curdesc->delay.first()->opptr.l[0];
+ }
}
}
}
UML_CMP(block, I0, sum); // cmp i0,sum
UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc
+ if (DEBUG_STRICT_VERIFY)
+ {
+ // This code will do additional checks on the last instruction and last delay slot and indicate if the check failed
+ uml::code_label check_second = compiler.labelnum++;
+ uml::code_label check_failed = compiler.labelnum++;
+ uml::code_label check_passed = compiler.labelnum++;
+ // Check the last instruction
+ if (!(codelast->flags & OPFLAG_VIRTUAL_NOOP) && last_physpc != seqhead->physpc)
+ {
+ base = m_prptr(last_physpc);
+ assert(base != nullptr);
+ low_bits = (last_physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
+ UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ sum = codelast->opptr.l[0];
+ UML_CMP(block, I0, sum); // cmp i0,sum
+ UML_JMPc(block, COND_E, check_second);
+ static const char text[] = "Last instr validation fail seq: %08X end: %08x\n";
+ UML_DMOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ UML_MOV(block, mem(&m_core->arg0), seqhead->pc);
+ UML_MOV(block, mem(&m_core->arg1), last_physpc); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
+ //UML_CALLC(block, cfunc_debug_break, this);
+ // Skip delay slot check
+ UML_JMP(block, check_failed);
+ // Check the last instruction delay slot
+ UML_LABEL(block, check_second);
+ if (codelast->delay.first() != nullptr && !(codelast->delay.first()->flags & OPFLAG_VIRTUAL_NOOP)
+ && last_physpc != seqhead->physpc)
+ {
+ base = m_prptr(codelast->delay.first()->physpc);
+ assert(base != nullptr);
+ low_bits = (codelast->delay.first()->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
+ UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ sum = codelast->delay.first()->opptr.l[0];
+ UML_CMP(block, I0, sum); // cmp i0,sum
+ UML_JMPc(block, COND_E, check_passed);
+ static const char text[] = "Last delay slot validation fail seq: %08X end: %08x\n";
+ UML_DMOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ UML_MOV(block, mem(&m_core->arg0), seqhead->pc);
+ UML_MOV(block, mem(&m_core->arg1), last_physpc); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
+ //UML_CALLC(block, cfunc_debug_break, this);
+ UML_JMP(block, check_failed);
+ }
+ }
+ UML_JMP(block, check_passed);
+ UML_LABEL(block, check_failed);
+ UML_EXH(block, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc
+ UML_LABEL(block, check_passed);
+ }
#endif
}
}
@@ -1188,22 +1334,19 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &
void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
{
- offs_t expc;
- int hotnum;
-
/* add an entry for the log */
if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]);
/* set the PC map variable */
- expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 3 : desc->pc;
+ offs_t expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 3 : desc->pc;
UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc
/* accumulate total cycles */
compiler.cycles += desc->cycles;
/* is this a hotspot? */
- for (hotnum = 0; hotnum < MIPS3_MAX_HOTSPOTS; hotnum++)
+ for (int hotnum = 0; hotnum < MIPS3_MAX_HOTSPOTS; hotnum++)
if (m_hotspot[hotnum].pc != 0 && desc->pc == m_hotspot[hotnum].pc && desc->opptr.l[0] == m_hotspot[hotnum].opcode)
{
compiler.cycles += m_hotspot[hotnum].cycles;
@@ -1221,7 +1364,7 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s
}
/* if we are debugging, call the debugger */
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ if (debugger_enabled())
{
UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc
save_fast_iregs(block);
@@ -1247,6 +1390,8 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s
UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
}
UML_EXH(block, *m_tlb_mismatch, 0); // exh tlb_mismatch,0
+ // Unconditional tlb exception, no point going further
+ return;
}
/* validate our TLB entry at this PC; if we fail, we need to handle it */
@@ -1255,7 +1400,7 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s
const vtlb_entry *tlbtable = vtlb_table();
/* if we currently have a valid TLB read entry, we just verify */
- if (tlbtable[desc->pc >> 12] & VTLB_FETCH_ALLOWED)
+ if (tlbtable[desc->pc >> 12] & FETCH_ALLOWED)
{
if (PRINTF_MMU)
{
@@ -1280,6 +1425,8 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s
UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
}
UML_EXH(block, *m_tlb_mismatch, 0); // exh tlb_mismatch,0
+ // Unconditional tlb exception, no point going further
+ return;
}
}
@@ -1331,7 +1478,7 @@ void mips3_device::generate_delay_slot_and_branch(drcuml_block &block, compiler_
if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
{
generate_update_cycles(block, compiler_temp, desc->targetpc, true); // <subtract cycles>
- if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
+ if (!(m_drcoptions & MIPS3DRC_DISABLE_INTRABLOCK) && (desc->flags & OPFLAG_INTRABLOCK_BRANCH))
{
UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc | 0x80000000
}
@@ -2456,6 +2603,11 @@ bool mips3_device::generate_set_cop0_reg(drcuml_block &block, compiler_state &co
return true;
case COP0_Count:
+ // don't count the cycle for this instruction yet; we need a non-zero cycle
+ // count in case we are in a delay slot, otherwise the test for negative cycles
+ // won't be generated (due to compiler.cycles == 0); see the loop during early
+ // boot of gauntdl, @BFC01A24
+ compiler.cycles--;
generate_update_cycles(block, compiler, desc->pc, !in_delay_slot); // <subtract cycles>
UML_MOV(block, CPR032(COP0_Count), I0); // mov [Count],i0
UML_CALLC(block, cfunc_get_cycles, this); // callc cfunc_get_cycles,mips3
@@ -2464,6 +2616,7 @@ bool mips3_device::generate_set_cop0_reg(drcuml_block &block, compiler_state &co
UML_DSUB(block, mem(&m_core->count_zero_time), mem(&m_core->numcycles), I0);
// dsub [count_zero_time],[m_numcycles],i0
UML_CALLC(block, cfunc_mips3com_update_cycle_counting, this); // callc mips3com_update_cycle_counting,mips.core
+ compiler.cycles++;
return true;
case COP0_Compare:
@@ -2509,12 +2662,18 @@ bool mips3_device::generate_get_cop0_reg(drcuml_block &block, compiler_state &co
switch (reg)
{
case COP0_Count:
+ // don't count the cycle for this instruction yet; we need a non-zero cycle
+ // count in case we are in a delay slot, otherwise the test for negative cycles
+ // won't be generated (due to compiler.cycles == 0); see the loop during early
+ // boot of gauntdl, @BFC01A24
+ compiler.cycles--;
generate_update_cycles(block, compiler, desc->pc, false); // <subtract cycles>
UML_CALLC(block, cfunc_get_cycles, this); // callc cfunc_get_cycles,mips3
UML_DSUB(block, I0, mem(&m_core->numcycles), mem(&m_core->count_zero_time));
// dsub i0,[numcycles],[count_zero_time]
UML_DSHR(block, I0, I0, 1); // dshr i0,i0,1
UML_DSEXT(block, I0, I0, SIZE_DWORD); // dsext i0,i0,dword
+ compiler.cycles++;
return true;
case COP0_Random: