Fix MT07823: nbagold (vegas) watchdog reset when select other game menu from service menu (#9560)

mips3: Add new DRC option to add extra validation to hash jumps
vegas: Use new MIPS DRC option
atlantis: Use new MIPS DRC option
This commit is contained in:
tedgreen99 2022-04-14 15:03:44 -06:00 committed by GitHub
parent f95883ac29
commit 30ec2aaaa7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 104 additions and 18 deletions

View File

@ -133,6 +133,8 @@ public:
// describe a block
opcode_desc const *describe_code(offs_t startpc);
// get last opcode of block
opcode_desc const* get_last() { return m_desc_live_list.last(); };
protected:
// required overrides

View File

@ -309,6 +309,7 @@ public:
void add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base);
void clear_fastram(uint32_t select_start);
void mips3drc_set_options(uint32_t options);
uint32_t mips3drc_get_options();
void mips3drc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles);
protected:
@ -623,7 +624,7 @@ private:
void generate_update_mode(drcuml_block &block);
void generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception);
void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast, const opcode_desc* codelast);
void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
void generate_delay_slot_and_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t linkreg);
@ -968,8 +969,6 @@ private:
/***************************************************************************
COMPILER-SPECIFIC OPTIONS
***************************************************************************/
/* fix me -- how do we make this work?? */
#define MIPS3DRC_STRICT_VERIFY 0x0001 /* verify all instructions */
#define MIPS3DRC_STRICT_COP0 0x0002 /* validate all COP0 instructions */
#define MIPS3DRC_STRICT_COP1 0x0004 /* validate all COP1 instructions */
@ -977,9 +976,13 @@ COMPILER-SPECIFIC OPTIONS
#define MIPS3DRC_DISABLE_INTRABLOCK 0x0010 /* disable intrablock branching */
#define MIPS3DRC_CHECK_OVERFLOWS 0x0020 /* actually check overflows on add/sub instructions */
#define MIPS3DRC_ACCURATE_DIVZERO 0x0040 /* load correct values into HI/LO on integer divide-by-zero */
#define MIPS3DRC_EXTRA_INSTR_CHECK 0x0080 /* adds the last instruction value to all validation entry locations, used with STRICT_VERIFY */
#define MIPS3DRC_COMPATIBLE_OPTIONS (MIPS3DRC_STRICT_VERIFY | MIPS3DRC_STRICT_COP1 | MIPS3DRC_STRICT_COP0 | MIPS3DRC_STRICT_COP2)
#define MIPS3DRC_FASTEST_OPTIONS (0)
/* 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
#endif // MAME_CPU_MIPS_MIPS3_H

View File

@ -155,6 +155,15 @@ void mips3_device::mips3drc_set_options(uint32_t options)
m_drcoptions = 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
@ -282,6 +291,7 @@ 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;
@ -289,6 +299,8 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc)
/* 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);
@ -340,7 +352,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)
@ -1097,7 +1109,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())
@ -1149,16 +1161,29 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &
uint32_t low_bits = (seqhead->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i0,base,0,dword
sum += seqhead->opptr.l[0];
if ((m_drcoptions & MIPS3DRC_EXTRA_INSTR_CHECK) && !(codelast->flags & OPFLAG_VIRTUAL_NOOP) && codelast->physpc != seqhead->physpc)
{
base = m_prptr(codelast->physpc);
assert(base != nullptr);
low_bits = (codelast->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 += codelast->opptr.l[0];
}
for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
{
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
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];
// Skip the last if it was already included above
if (!(m_drcoptions & MIPS3DRC_EXTRA_INSTR_CHECK) || curdesc->physpc != codelast->physpc)
{
base = m_prptr(curdesc->physpc);
assert(base != nullptr);
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)
@ -1166,7 +1191,7 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &
{
base = m_prptr(curdesc->delay.first()->physpc);
assert(base != nullptr);
uint32_t low_bits = (curdesc->delay.first()->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
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];
@ -1175,6 +1200,57 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &
}
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_passed, check_failed, check_second;
check_second = compiler.labelnum++;
check_failed = compiler.labelnum++;
check_passed = compiler.labelnum++;
// Check the last instruction
if (!(codelast->flags & OPFLAG_VIRTUAL_NOOP) && codelast->physpc != seqhead->physpc)
{
base = m_prptr(codelast->physpc);
assert(base != nullptr);
low_bits = (codelast->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), codelast->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)
&& codelast->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), codelast->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
}
}
@ -1189,7 +1265,6 @@ void mips3_device::generate_sequence_instruction(drcuml_block &block, compiler_s
{
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]);
@ -1334,7 +1409,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 (!(m_drcoptions & MIPS3DRC_DISABLE_INTRABLOCK) && 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
}

View File

@ -625,7 +625,7 @@ void atlantis_state::a2d_data_w(uint16_t data)
void atlantis_state::machine_start()
{
/* set the fastest DRC options */
m_maincpu->mips3drc_set_options(MIPS3DRC_FASTEST_OPTIONS);
m_maincpu->mips3drc_set_options(MIPS3DRC_FASTEST_OPTIONS | MIPS3DRC_STRICT_VERIFY | MIPS3DRC_EXTRA_INSTR_CHECK);
// Allocate adc timer
m_adc_ready_timer = timer_alloc(0);

View File

@ -485,7 +485,10 @@ private:
void vegas_state::machine_start()
{
/* set the fastest DRC options, but strict verification */
m_maincpu->mips3drc_set_options(MIPS3DRC_FASTEST_OPTIONS + MIPS3DRC_STRICT_VERIFY);
/* need to check the current options since some drivers add options in their init */
uint32_t new_options = m_maincpu->mips3drc_get_options();
new_options |= MIPS3DRC_FASTEST_OPTIONS | MIPS3DRC_STRICT_VERIFY;
m_maincpu->mips3drc_set_options(new_options);
m_system_led.resolve();
m_wheel_driver.resolve();
@ -2034,14 +2037,14 @@ void vegas_state::denver(machine_config &config)
m_uart2->out_rts_callback().set("ttys02", FUNC(rs232_port_device::write_rts));
m_uart2->out_int_callback().set("duart_irq", FUNC(input_merger_device::in_w<1>));
rs232_port_device &ttys01(RS232_PORT(config, "ttys01", 0));
rs232_port_device &ttys01(RS232_PORT(config, "ttys01", default_rs232_devices, nullptr));
ttys01.rxd_handler().set(m_uart1, FUNC(ins8250_uart_device::rx_w));
ttys01.dcd_handler().set(m_uart1, FUNC(ins8250_uart_device::dcd_w));
ttys01.dsr_handler().set(m_uart1, FUNC(ins8250_uart_device::dsr_w));
ttys01.ri_handler().set(m_uart1, FUNC(ins8250_uart_device::ri_w));
ttys01.cts_handler().set(m_uart1, FUNC(ins8250_uart_device::cts_w));
rs232_port_device &ttys02(RS232_PORT(config, "ttys02", 0));
rs232_port_device &ttys02(RS232_PORT(config, "ttys02", default_rs232_devices, nullptr));
ttys02.rxd_handler().set(m_uart2, FUNC(ins8250_uart_device::rx_w));
ttys02.dcd_handler().set(m_uart2, FUNC(ins8250_uart_device::dcd_w));
ttys02.dsr_handler().set(m_uart2, FUNC(ins8250_uart_device::dsr_w));
@ -2621,11 +2624,13 @@ void vegas_state::init_roadburn()
void vegas_state::init_nbashowt()
{
m_maincpu->mips3drc_set_options(MIPS3DRC_FASTEST_OPTIONS | MIPS3DRC_STRICT_VERIFY | MIPS3DRC_EXTRA_INSTR_CHECK);
}
void vegas_state::init_nbanfl()
{
m_maincpu->mips3drc_set_options(MIPS3DRC_FASTEST_OPTIONS | MIPS3DRC_STRICT_VERIFY | MIPS3DRC_EXTRA_INSTR_CHECK);
// The first three bytes of the blitz00_nov30_1999.u27 ROM are FF's which breaks the reset vector.
// These bytes are from blitz00_sep22_1999.u27 which allows the other ROM to start.
// The last byte which is part of the checksum is also FF. By changing it to 0x01 the 4 byte checksum matches with the other 3 changes.
@ -2639,6 +2644,7 @@ void vegas_state::init_nbanfl()
void vegas_state::init_nbagold()
{
m_maincpu->mips3drc_set_options(MIPS3DRC_FASTEST_OPTIONS | MIPS3DRC_STRICT_VERIFY | MIPS3DRC_EXTRA_INSTR_CHECK);
}