ppcopcodes: Fix lswx.

- Remove invalid form check unless you know for sure it's supposed to cause an exception.
- Add register skip for 601 CPU. This needs testing.
This commit is contained in:
joevt 2024-01-10 05:54:51 -08:00 committed by Maxim Poliakovski
parent 1fc551fae0
commit 8764beba39

View File

@ -2118,38 +2118,41 @@ void dppc_interpreter::ppc_lswx() {
#endif #endif
ppc_grab_regsdab(); ppc_grab_regsdab();
/*
// Invalid instruction forms // Invalid instruction forms
if ((reg_d == 0 && reg_a == 0) || (reg_d == reg_a) || (reg_d == reg_b)) { if ((reg_d == 0 && reg_a == 0) || (reg_d == reg_a) || (reg_d == reg_b)) {
// UNTESTED! Does invalid form really cause exception?
// G4 doesn't do exception
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
} }
*/
ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b;
uint32_t grab_inb = ppc_state.spr[SPR::XER] & 0x7F; uint32_t grab_inb = ppc_state.spr[SPR::XER] & 0x7F;
while (grab_inb >= 4) { for (;;) {
ppc_state.gpr[reg_d] = mmu_read_vmem<uint32_t>(ppc_effective_address); if (is_601 && (reg_d == reg_b || (reg_a != 0 && reg_d == reg_a))) {
reg_d++; // UNTESTED! MPC601 manual is inconsistant on whether reg_b is skipped or not
if (reg_d >= 32) { // wrap around through GPR0 reg_d = (reg_d + 1) & 31; // wrap around through GPR0
reg_d = 0;
} }
ppc_effective_address += 4;
grab_inb -= 4;
}
// handle remaining bytes
switch (grab_inb) { switch (grab_inb) {
case 0:
return;
case 1: case 1:
ppc_state.gpr[reg_d] = mmu_read_vmem<uint8_t>(ppc_effective_address) << 24; ppc_state.gpr[reg_d] = mmu_read_vmem<uint8_t>(ppc_effective_address) << 24;
break; return;
case 2: case 2:
ppc_state.gpr[reg_d] = mmu_read_vmem<uint16_t>(ppc_effective_address) << 16; ppc_state.gpr[reg_d] = mmu_read_vmem<uint16_t>(ppc_effective_address) << 16;
break; return;
case 3: case 3:
ppc_state.gpr[reg_d] = mmu_read_vmem<uint16_t>(ppc_effective_address) << 16; ppc_state.gpr[reg_d] = (mmu_read_vmem<uint16_t>(ppc_effective_address) << 16)
ppc_state.gpr[reg_d] += mmu_read_vmem<uint8_t>(ppc_effective_address + 2) << 8; | (mmu_read_vmem<uint8_t>(ppc_effective_address + 2) << 8);
break; return;
default: }
break; ppc_state.gpr[reg_d] = mmu_read_vmem<uint32_t>(ppc_effective_address);
reg_d = (reg_d + 1) & 31; // wrap around through GPR0
ppc_effective_address += 4;
grab_inb -= 4;
} }
} }