Write the results of an ALU operation before writing to register/memory (#13486)

Sega Rally has an instruction that calculates d += p and loads a value into d at the same time; it is the loaded value that should be used, not the result of the ALU operation

Also only test the d register when performing an ALU operation
This commit is contained in:
Matthew Daniels 2025-03-20 21:17:38 +00:00 committed by GitHub
parent bdfd419e21
commit 5363907b72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 19 additions and 19 deletions

View File

@ -256,18 +256,6 @@ void mb86233_device::pcs_pop()
m_pcs[i] = m_pcs[i+1];
}
void mb86233_device::testdz()
{
if(m_d)
m_st &= ~F_ZRD;
else
m_st |= F_ZRD;
if(m_d & 0x80000000)
m_st |= F_SGD;
else
m_st &= ~F_SGD;
}
void mb86233_device::stset_set_sz_int(u32 val)
{
m_alu_stset = val ? (val & 0x80000000 ? F_SGD : 0) : F_ZRD;
@ -324,7 +312,7 @@ void mb86233_device::alu_pre(u32 alu)
}
case 0x06: {
// fmad
// fadd
m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
m_alu_r1 = f2u(u2f(m_d) + u2f(m_a));
stset_set_sz_fp(m_alu_r1);
@ -676,9 +664,9 @@ void mb86233_device::write_reg(u32 r, u32 v)
case 0x14: m_b = set_exp(m_b, v); break;
case 0x15: m_b = set_mant(m_b, v); break;
/* c */
case 0x19: m_d = v; testdz(); break;
case 0x1a: m_d = set_exp(m_d, v); testdz(); break;
case 0x1b: m_d = set_mant(m_d, v); testdz(); break;
case 0x19: m_d = v; break;
case 0x1a: m_d = set_exp(m_d, v); break;
case 0x1b: m_d = set_mant(m_d, v); break;
case 0x1c: m_p = v; break;
case 0x1d: m_p = set_exp(m_p, v); break;
case 0x1e: m_p = set_mant(m_p, v); break;
@ -812,6 +800,7 @@ void mb86233_device::execute_run()
u32 v = m_data.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_0(r1);
alu_post(alu);
write_mem_io_1(r2, v);
break;
}
@ -822,6 +811,7 @@ void mb86233_device::execute_run()
u32 v = m_data.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_0(r1);
alu_post(alu);
write_mem_io_1(r2, v);
break;
}
@ -832,6 +822,7 @@ void mb86233_device::execute_run()
u32 v = m_io.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_0(r1);
alu_post(alu);
write_mem_internal_1(r2, v, false);
break;
}
@ -842,6 +833,7 @@ void mb86233_device::execute_run()
u32 v = m_data.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_0(r1);
alu_post(alu);
write_mem_internal_1(r2, v, true);
break;
}
@ -852,6 +844,7 @@ void mb86233_device::execute_run()
u32 v = m_data.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_0(r1);
alu_post(alu);
write_mem_internal_1(r2, v, false);
break;
}
@ -862,6 +855,7 @@ void mb86233_device::execute_run()
u32 v = m_program.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_0(r1);
alu_post(alu);
write_mem_internal_1(r2, v, false);
break;
}
@ -872,6 +866,7 @@ void mb86233_device::execute_run()
// mov reg, mem
u32 v = read_reg(r2);
if(m_stall) goto do_stall;
alu_post(alu);
write_mem_internal_1(r1, v, false);
break;
}
@ -880,6 +875,7 @@ void mb86233_device::execute_run()
// mov reg, mem (e)
u32 v = read_reg(r2);
if(m_stall) goto do_stall;
alu_post(alu);
write_mem_io_1(r1, v);
break;
}
@ -890,6 +886,7 @@ void mb86233_device::execute_run()
u32 v = m_data.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_1(r1);
alu_post(alu);
write_reg(r2, v);
break;
}
@ -900,6 +897,7 @@ void mb86233_device::execute_run()
u32 v = m_data.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_1(r1);
alu_post(alu);
write_reg(r2, v);
break;
}
@ -910,6 +908,7 @@ void mb86233_device::execute_run()
u32 v = m_io.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_1(r1);
alu_post(alu);
write_reg(r2, v);
break;
}
@ -920,6 +919,7 @@ void mb86233_device::execute_run()
u32 v = m_program.read_dword(ea);
if(m_stall) goto do_stall;
ea_post_0(r1);
alu_post(alu);
write_reg(r2, v);
break;
}
@ -928,11 +928,13 @@ void mb86233_device::execute_run()
// mov reg, reg
u32 v = read_reg(r1);
if(m_stall) goto do_stall;
alu_post(alu);
write_reg(r2, v);
break;
}
default:
alu_post(alu);
logerror("unhandled ld/mov subop 7/%x (%x)\n", r2 >> 6, m_ppc);
break;
}
@ -940,11 +942,11 @@ void mb86233_device::execute_run()
}
default:
alu_post(alu);
logerror("unhandled ld/mov subop %x (%x)\n", op, m_ppc);
break;
}
alu_post(alu);
break;
}
@ -983,7 +985,6 @@ void mb86233_device::execute_run()
break;
case 3:
m_d = util::sext(opcode, 24);
testdz();
break;
}
break;

View File

@ -109,7 +109,6 @@ private:
static u32 get_exp(u32 val);
static u32 get_mant(u32 val);
void testdz();
void alu_update_st();
void alu_pre(u32 alu);
void alu_post(u32 alu);