From 130766a55c7626b80bfbf34f30b5c20ed84af5ef Mon Sep 17 00:00:00 2001 From: Ted Green Date: Wed, 1 Jun 2016 08:51:21 -0600 Subject: [PATCH] (nw) MIP3 DRC handle branches in delay slot properly. --- src/devices/cpu/drcfe.cpp | 11 ++++++++++- src/devices/cpu/drcfe.h | 5 +++++ src/devices/cpu/mips/mips3.cpp | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/devices/cpu/drcfe.cpp b/src/devices/cpu/drcfe.cpp index 87478de59e6..6eda93e95c7 100644 --- a/src/devices/cpu/drcfe.cpp +++ b/src/devices/cpu/drcfe.cpp @@ -55,7 +55,8 @@ drc_frontend::drc_frontend(device_t &cpu, UINT32 window_start, UINT32 window_end m_cpudevice(downcast(cpu)), m_program(m_cpudevice.space(AS_PROGRAM)), m_pageshift(m_cpudevice.space_config(AS_PROGRAM)->m_page_shift), - m_desc_array(window_end + window_start + 2, nullptr) + m_desc_array(window_end + window_start + 2, nullptr), + m_allow_branch_in_delay(false) { } @@ -196,6 +197,14 @@ opcode_desc *drc_frontend::describe_one(offs_t curpc, const opcode_desc *prevdes { // iterate over slots and describe them offs_t delaypc = curpc + desc->length; + + // If previous instruction is a branch use the target pc. Currently MIP3s only. + if (m_allow_branch_in_delay && prevdesc && (prevdesc->flags & OPFLAG_IS_BRANCH) && prevdesc->targetpc != BRANCH_TARGET_DYNAMIC) { + // We got here because the previous instruction is a branch and this instruction is a branch. + // So the PC of the delay slot for the this branch will be the target address of the previous branch. + delaypc = prevdesc->targetpc; + //printf("drc_frontend::describe_one: branch in delay slot. curpc=0x%08X, delaypc=0x%08X\n", curpc, delaypc); + } opcode_desc *prev = desc; for (UINT8 slotnum = 0; slotnum < desc->delayslots; slotnum++) { diff --git a/src/devices/cpu/drcfe.h b/src/devices/cpu/drcfe.h index 09d86b2bd99..c7458e87bdb 100644 --- a/src/devices/cpu/drcfe.h +++ b/src/devices/cpu/drcfe.h @@ -134,6 +134,9 @@ public: // describe a block const opcode_desc *describe_code(offs_t startpc); + // Set the allow branches in delay slot flag + void set_allow_branch_in_delay(bool flag) { m_allow_branch_in_delay = flag; } + protected: // required overrides virtual bool describe(opcode_desc &desc, const opcode_desc *prev) = 0; @@ -159,6 +162,8 @@ private: simple_list m_desc_live_list; // list of live descriptions fixed_allocator m_desc_allocator; // fixed allocator for descriptions std::vector m_desc_array; // array of descriptions in PC order + + bool m_allow_branch_in_delay; // Allow branches in delay slots }; diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index 7ae1fd1f337..dbc510771fc 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -386,6 +386,8 @@ void mips3_device::device_start() /* initialize the front-end helper */ m_drcfe = std::make_unique(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); + // Allow branches in delay slots + m_drcfe->set_allow_branch_in_delay(true); /* allocate memory for cache-local state and initialize it */ memcpy(m_fpmode, fpmode_source, sizeof(fpmode_source));