summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mips/mips1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mips/mips1.cpp')
-rw-r--r--src/devices/cpu/mips/mips1.cpp66
1 files changed, 36 insertions, 30 deletions
diff --git a/src/devices/cpu/mips/mips1.cpp b/src/devices/cpu/mips/mips1.cpp
index b2988470a94..a2a4f94ef06 100644
--- a/src/devices/cpu/mips/mips1.cpp
+++ b/src/devices/cpu/mips/mips1.cpp
@@ -39,12 +39,12 @@
#define UIMMVAL u16(op)
#define LIMMVAL (op & 0x03ffffff)
-#define ADDPC(x) do { m_nextpc = m_pc + ((x) << 2); } while (0)
-#define ADDPCL(x,l) do { m_nextpc = m_pc + ((x) << 2); m_r[l] = m_pc + 4; } while (0)
-#define ABSPC(x) do { m_nextpc = (m_pc & 0xf0000000) | ((x) << 2); } while (0)
-#define ABSPCL(x,l) do { m_nextpc = (m_pc & 0xf0000000) | ((x) << 2); m_r[l] = m_pc + 4; } while (0)
-#define SETPC(x) do { m_nextpc = (x); } while (0)
-#define SETPCL(x,l) do { m_nextpc = (x); m_r[l] = m_pc + 4; } while (0)
+#define ADDPC(x) do { m_branch_state = BRANCH; m_branch_target = m_pc + 4 + ((x) << 2); } while (0)
+#define ADDPCL(x,l) do { m_branch_state = BRANCH; m_branch_target = m_pc + 4 + ((x) << 2); m_r[l] = m_pc + 8; } while (0)
+#define ABSPC(x) do { m_branch_state = BRANCH; m_branch_target = ((m_pc + 4) & 0xf0000000) | ((x) << 2); } while (0)
+#define ABSPCL(x,l) do { m_branch_state = BRANCH; m_branch_target = ((m_pc + 4) & 0xf0000000) | ((x) << 2); m_r[l] = m_pc + 8; } while (0)
+#define SETPC(x) do { m_branch_state = BRANCH; m_branch_target = (x); } while (0)
+#define SETPCL(x,l) do { m_branch_state = BRANCH; m_branch_target = (x); m_r[l] = m_pc + 8; } while (0)
#define SR m_cpr[0][COP0_Status]
#define CAUSE m_cpr[0][COP0_Cause]
@@ -61,6 +61,8 @@ DEFINE_DEVICE_TYPE(R3071, r3071_device, "r3071", "IDT R3071")
DEFINE_DEVICE_TYPE(R3081, r3081_device, "r3081", "IDT R3081")
DEFINE_DEVICE_TYPE(SONYPS2_IOP, iop_device, "sonyiop", "Sony Playstation 2 IOP")
+ALLOW_SAVE_TYPE(mips1core_device_base::branch_state_t);
+
mips1core_device_base::mips1core_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size)
: cpu_device(mconfig, type, tag, owner, clock)
, m_program_config_be("program", ENDIANNESS_BIG, 32, 32)
@@ -71,9 +73,6 @@ mips1core_device_base::mips1core_device_base(const machine_config &mconfig, devi
, m_hasfpu(false)
, m_fpurev(0)
, m_endianness(ENDIANNESS_BIG)
- , m_pc(0)
- , m_nextpc(0)
- , m_ppc(0)
, m_icount(0)
, m_icache_size(icache_size)
, m_dcache_size(dcache_size)
@@ -177,7 +176,7 @@ void mips1core_device_base::device_start()
// register our state for the debugger
state_add(STATE_GENPC, "GENPC", m_pc).noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_ppc).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow();
state_add(STATE_GENSP, "GENSP", m_r[31]).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_cpr[0][COP0_Status]).noshow();
@@ -195,13 +194,13 @@ void mips1core_device_base::device_start()
// register our state for saving
save_item(NAME(m_pc));
- save_item(NAME(m_nextpc));
save_item(NAME(m_hi));
save_item(NAME(m_lo));
save_item(NAME(m_r));
save_item(NAME(m_cpr));
save_item(NAME(m_ccr));
- save_item(NAME(m_ppc));
+ save_item(NAME(m_branch_state));
+ save_item(NAME(m_branch_target));
// initialise cpu and fpu id registers
m_cpr[0][COP0_PRId] = m_cpurev;
@@ -239,7 +238,7 @@ void mips1core_device_base::device_reset()
{
// initialize the state
m_pc = 0xbfc00000;
- m_nextpc = ~0;
+ m_branch_state = NONE;
// non-tlb devices have tlb shut down
m_cpr[0][COP0_Status] = SR_BEV | SR_TS;
@@ -274,18 +273,18 @@ std::unique_ptr<util::disasm_interface> mips1core_device_base::create_disassembl
void mips1core_device_base::generate_exception(int exception)
{
// set the exception PC
- m_cpr[0][COP0_EPC] = (exception == EXCEPTION_INTERRUPT) ? m_pc : m_ppc;
+ m_cpr[0][COP0_EPC] = m_pc;
// put the cause in the low 8 bits and clear the branch delay flag
CAUSE = (CAUSE & ~0x800000ff) | (exception << 2);
- // if we were in a branch delay slot, adjust
- if (m_nextpc != ~0)
+ // if in a branch delay slot, restart the branch
+ if (m_branch_state == DELAY)
{
- m_nextpc = ~0;
m_cpr[0][COP0_EPC] -= 4;
CAUSE |= 0x80000000;
}
+ m_branch_state = NONE;
// shift the exception bits
SR = (SR & 0xffffffc0) | ((SR << 2) & 0x3c);
@@ -552,7 +551,6 @@ void mips1core_device_base::execute_run()
do
{
// debugging
- m_ppc = m_pc;
debugger_instruction_hook(m_pc);
#if ENABLE_IOP_KPUTS
@@ -575,16 +573,6 @@ void mips1core_device_base::execute_run()
// fetch and execute instruction
fetch(m_pc, [this](u32 const op)
{
- {
- // adjust for next PC
- if (m_nextpc != ~0)
- {
- m_pc = m_nextpc;
- m_nextpc = ~0;
- }
- else
- m_pc += 4;
-
// parse the instruction
switch (op >> 26)
{
@@ -784,11 +772,28 @@ void mips1core_device_base::execute_run()
case 0x3f: /* SDC3 */ generate_exception(EXCEPTION_INVALIDOP); break;
default: /* ??? */ generate_exception(EXCEPTION_INVALIDOP); break;
}
+
+ // update pc and branch state
+ switch (m_branch_state)
+ {
+ case NONE:
+ m_pc += 4;
+ break;
+
+ case DELAY:
+ m_branch_state = NONE;
+ m_pc = m_branch_target;
+ break;
+
+ case BRANCH:
+ m_branch_state = DELAY;
+ m_pc += 4;
+ break;
}
});
m_icount--;
- } while (m_icount > 0 || m_nextpc != ~0);
+ } while (m_icount > 0 || m_branch_state);
}
void mips1core_device_base::lwl(u32 const op)
@@ -995,7 +1000,8 @@ bool mips1_device_base::memory_translate(int spacenum, int intention, offs_t &ad
if (!(intention & TRANSLATE_DEBUG_MASK))
{
if ((VERBOSE & LOG_TLB) && !dirty)
- LOGMASKED(LOG_TLB, "tlb miss address 0x%08x\n", address);
+ LOGMASKED(LOG_TLB, "tlb miss %s address 0x%08x (%s)\n",
+ (intention & TRANSLATE_WRITE) ? "store" : "load", address, machine().describe_context());
// exception
m_cpr[0][COP0_BadVAddr] = address;