diff --git a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterALU.hpp b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterALU.hpp index 769344f8..2fe07509 100644 --- a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterALU.hpp +++ b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterALU.hpp @@ -41,7 +41,7 @@ static void PPCInterpreter_ADD(PPCInterpreter_t* hCPU, uint32 opcode) static void PPCInterpreter_ADDO(PPCInterpreter_t* hCPU, uint32 opcode) { - // untested (Don't Starve Giant Edition uses this instruction + BSO) + // Don't Starve Giant Edition uses this instruction + BSO PPC_OPC_TEMPL3_XO(); uint32 result = hCPU->gpr[rA] + hCPU->gpr[rB]; PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(hCPU->gpr[rA], hCPU->gpr[rB], result)); @@ -113,7 +113,6 @@ static void PPCInterpreter_ADDEO(PPCInterpreter_t* hCPU, uint32 opcode) else hCPU->xer_ca = 0; PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(a, b, hCPU->gpr[rD])); - // update CR if (opHasRC()) ppc_update_cr0(hCPU, hCPU->gpr[rD]); PPCInterpreter_nextInstruction(hCPU); @@ -130,7 +129,7 @@ static void PPCInterpreter_ADDI(PPCInterpreter_t* hCPU, uint32 opcode) static void PPCInterpreter_ADDIC(PPCInterpreter_t* hCPU, uint32 opcode) { - int rD, rA; + sint32 rD, rA; uint32 imm; PPC_OPC_TEMPL_D_SImm(opcode, rD, rA, imm); uint32 a = hCPU->gpr[rA]; @@ -145,7 +144,7 @@ static void PPCInterpreter_ADDIC(PPCInterpreter_t* hCPU, uint32 opcode) static void PPCInterpreter_ADDIC_(PPCInterpreter_t* hCPU, uint32 opcode) { - int rD, rA; + sint32 rD, rA; uint32 imm; PPC_OPC_TEMPL_D_SImm(opcode, rD, rA, imm); uint32 a = hCPU->gpr[rA]; @@ -155,14 +154,13 @@ static void PPCInterpreter_ADDIC_(PPCInterpreter_t* hCPU, uint32 opcode) hCPU->xer_ca = 1; else hCPU->xer_ca = 0; - // update cr0 flags ppc_update_cr0(hCPU, hCPU->gpr[rD]); PPCInterpreter_nextInstruction(hCPU); } static void PPCInterpreter_ADDIS(PPCInterpreter_t* hCPU, uint32 opcode) { - int rD, rA; + sint32 rD, rA; uint32 imm; PPC_OPC_TEMPL_D_Shift16(opcode, rD, rA, imm); hCPU->gpr[rD] = (rA ? hCPU->gpr[rA] : 0) + imm; @@ -185,6 +183,23 @@ static void PPCInterpreter_ADDZE(PPCInterpreter_t* hCPU, uint32 opcode) PPCInterpreter_nextInstruction(hCPU); } +static void PPCInterpreter_ADDZEO(PPCInterpreter_t* hCPU, uint32 opcode) +{ + PPC_OPC_TEMPL3_XO(); + PPC_ASSERT(rB == 0); + uint32 a = hCPU->gpr[rA]; + uint32 ca = hCPU->xer_ca; + hCPU->gpr[rD] = a + ca; + PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(a, 0, hCPU->gpr[rD])); + if ((a == 0xffffffff) && ca) + hCPU->xer_ca = 1; + else + hCPU->xer_ca = 0; + if (opHasRC()) + ppc_update_cr0(hCPU, hCPU->gpr[rD]); + PPCInterpreter_nextInstruction(hCPU); +} + static void PPCInterpreter_ADDME(PPCInterpreter_t* hCPU, uint32 opcode) { PPC_OPC_TEMPL3_XO(); @@ -201,6 +216,23 @@ static void PPCInterpreter_ADDME(PPCInterpreter_t* hCPU, uint32 opcode) PPCInterpreter_nextInstruction(hCPU); } +static void PPCInterpreter_ADDMEO(PPCInterpreter_t* hCPU, uint32 opcode) +{ + PPC_OPC_TEMPL3_XO(); + PPC_ASSERT(rB == 0); + uint32 a = hCPU->gpr[rA]; + uint32 ca = hCPU->xer_ca; + hCPU->gpr[rD] = a + ca + 0xffffffff; + PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(a, 0xffffffff, hCPU->gpr[rD])); + if (a || ca) + hCPU->xer_ca = 1; + else + hCPU->xer_ca = 0; + if (opHasRC()) + ppc_update_cr0(hCPU, hCPU->gpr[rD]); + PPCInterpreter_nextInstruction(hCPU); +} + static void PPCInterpreter_SUBF(PPCInterpreter_t* hCPU, uint32 opcode) { PPC_OPC_TEMPL3_XO(); @@ -260,7 +292,7 @@ static void PPCInterpreter_SUBFCO(PPCInterpreter_t* hCPU, uint32 opcode) static void PPCInterpreter_SUBFIC(PPCInterpreter_t* hCPU, uint32 opcode) { - int rD, rA; + sint32 rD, rA; uint32 imm; PPC_OPC_TEMPL_D_SImm(opcode, rD, rA, imm); uint32 a = hCPU->gpr[rA]; @@ -284,7 +316,6 @@ static void PPCInterpreter_SUBFE(PPCInterpreter_t* hCPU, uint32 opcode) hCPU->xer_ca = 1; else hCPU->xer_ca = 0; - // update cr0 if (opHasRC()) ppc_update_cr0(hCPU, hCPU->gpr[rD]); PPCInterpreter_nextInstruction(hCPU); @@ -304,7 +335,6 @@ static void PPCInterpreter_SUBFEO(PPCInterpreter_t* hCPU, uint32 opcode) else hCPU->xer_ca = 0; PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~a, b, result)); - // update cr0 if (opHasRC()) ppc_update_cr0(hCPU, hCPU->gpr[rD]); PPCInterpreter_nextInstruction(hCPU); @@ -326,9 +356,25 @@ static void PPCInterpreter_SUBFZE(PPCInterpreter_t* hCPU, uint32 opcode) PPCInterpreter_nextInstruction(hCPU); } +static void PPCInterpreter_SUBFZEO(PPCInterpreter_t* hCPU, uint32 opcode) +{ + PPC_OPC_TEMPL3_XO(); + PPC_ASSERT(rB == 0); + uint32 a = hCPU->gpr[rA]; + uint32 ca = hCPU->xer_ca; + hCPU->gpr[rD] = ~a + ca; + PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~a, 0, hCPU->gpr[rD])); + if (a == 0 && ca) + hCPU->xer_ca = 1; + else + hCPU->xer_ca = 0; + if (opHasRC()) + ppc_update_cr0(hCPU, hCPU->gpr[rD]); + PPCInterpreter_nextInstruction(hCPU); +} + static void PPCInterpreter_SUBFME(PPCInterpreter_t* hCPU, uint32 opcode) { - // untested PPC_OPC_TEMPL3_XO(); PPC_ASSERT(rB == 0); uint32 a = hCPU->gpr[rA]; @@ -339,7 +385,24 @@ static void PPCInterpreter_SUBFME(PPCInterpreter_t* hCPU, uint32 opcode) hCPU->xer_ca = 1; else hCPU->xer_ca = 0; - // update cr0 + if (opcode & PPC_OPC_RC) + ppc_update_cr0(hCPU, hCPU->gpr[rD]); + PPCInterpreter_nextInstruction(hCPU); +} + +static void PPCInterpreter_SUBFMEO(PPCInterpreter_t* hCPU, uint32 opcode) +{ + PPC_OPC_TEMPL3_XO(); + PPC_ASSERT(rB == 0); + uint32 a = hCPU->gpr[rA]; + uint32 ca = hCPU->xer_ca; + hCPU->gpr[rD] = ~a + 0xFFFFFFFF + ca; + PPCInterpreter_setXerOV(hCPU, checkAdditionOverflow(~a, 0xFFFFFFFF, hCPU->gpr[rD])); + // update xer carry + if (ppc_carry_3(~a, 0xFFFFFFFF, ca)) + hCPU->xer_ca = 1; + else + hCPU->xer_ca = 0; if (opcode & PPC_OPC_RC) ppc_update_cr0(hCPU, hCPU->gpr[rD]); PPCInterpreter_nextInstruction(hCPU); @@ -352,13 +415,8 @@ static void PPCInterpreter_MULHW_(PPCInterpreter_t* hCPU, uint32 opcode) sint64 b = (sint32)hCPU->gpr[rB]; sint64 c = a * b; hCPU->gpr[rD] = ((uint64)c) >> 32; - if (opcode & PPC_OPC_RC) { - // update cr0 flags -#ifdef CEMU_DEBUG_ASSERT - assert_dbg(); -#endif + if (opHasRC()) ppc_update_cr0(hCPU, hCPU->gpr[rD]); - } PPCInterpreter_nextInstruction(hCPU); } @@ -409,14 +467,14 @@ static void PPCInterpreter_MULLI(PPCInterpreter_t* hCPU, uint32 opcode) static void PPCInterpreter_DIVW(PPCInterpreter_t* hCPU, uint32 opcode) { PPC_OPC_TEMPL3_XO(); - sint32 a = hCPU->gpr[rA]; - sint32 b = hCPU->gpr[rB]; + sint32 a = (sint32)hCPU->gpr[rA]; + sint32 b = (sint32)hCPU->gpr[rB]; if (b == 0) - { - cemuLog_logDebug(LogType::Force, "Error: Division by zero! [{:08x}]", (uint32)hCPU->instructionPointer); - b++; - } - hCPU->gpr[rD] = a / b; + hCPU->gpr[rD] = a < 0 ? 0xFFFFFFFF : 0; + else if (a == 0x80000000 && b == 0xFFFFFFFF) + hCPU->gpr[rD] = 0xFFFFFFFF; + else + hCPU->gpr[rD] = a / b; if (opHasRC()) ppc_update_cr0(hCPU, hCPU->gpr[rD]); PPCInterpreter_nextInstruction(hCPU); @@ -425,16 +483,23 @@ static void PPCInterpreter_DIVW(PPCInterpreter_t* hCPU, uint32 opcode) static void PPCInterpreter_DIVWO(PPCInterpreter_t* hCPU, uint32 opcode) { PPC_OPC_TEMPL3_XO(); - sint32 a = hCPU->gpr[rA]; - sint32 b = hCPU->gpr[rB]; + sint32 a = (sint32)hCPU->gpr[rA]; + sint32 b = (sint32)hCPU->gpr[rB]; if (b == 0) { PPCInterpreter_setXerOV(hCPU, true); - PPCInterpreter_nextInstruction(hCPU); - return; + hCPU->gpr[rD] = a < 0 ? 0xFFFFFFFF : 0; + } + else if(a == 0x80000000 && b == 0xFFFFFFFF) + { + PPCInterpreter_setXerOV(hCPU, true); + hCPU->gpr[rD] = 0xFFFFFFFF; + } + else + { + hCPU->gpr[rD] = a / b; + PPCInterpreter_setXerOV(hCPU, false); } - hCPU->gpr[rD] = a / b; - PPCInterpreter_setXerOV(hCPU, false); if (opHasRC()) ppc_update_cr0(hCPU, hCPU->gpr[rD]); PPCInterpreter_nextInstruction(hCPU); @@ -443,12 +508,14 @@ static void PPCInterpreter_DIVWO(PPCInterpreter_t* hCPU, uint32 opcode) static void PPCInterpreter_DIVWU(PPCInterpreter_t* hCPU, uint32 opcode) { PPC_OPC_TEMPL3_XO(); - if (hCPU->gpr[rB] == 0) - { - PPCInterpreter_nextInstruction(hCPU); - return; - } - hCPU->gpr[rD] = hCPU->gpr[rA] / hCPU->gpr[rB]; + uint32 a = hCPU->gpr[rA]; + uint32 b = hCPU->gpr[rB]; + if (b == 0) + hCPU->gpr[rD] = 0; + else if (a == 0x80000000 && b == 0xFFFFFFFF) + hCPU->gpr[rD] = 0; + else + hCPU->gpr[rD] = a / b; if (opHasRC()) ppc_update_cr0(hCPU, hCPU->gpr[rD]); PPCInterpreter_nextInstruction(hCPU); @@ -457,14 +524,23 @@ static void PPCInterpreter_DIVWU(PPCInterpreter_t* hCPU, uint32 opcode) static void PPCInterpreter_DIVWUO(PPCInterpreter_t* hCPU, uint32 opcode) { PPC_OPC_TEMPL3_XO(); - if (hCPU->gpr[rB] == 0) + uint32 a = hCPU->gpr[rA]; + uint32 b = hCPU->gpr[rB]; + if (b == 0) { PPCInterpreter_setXerOV(hCPU, true); - PPCInterpreter_nextInstruction(hCPU); - return; + hCPU->gpr[rD] = 0; + } + else if(a == 0x80000000 && b == 0xFFFFFFFF) + { + PPCInterpreter_setXerOV(hCPU, false); + hCPU->gpr[rD] = 0; + } + else + { + hCPU->gpr[rD] = a / b; + PPCInterpreter_setXerOV(hCPU, false); } - hCPU->gpr[rD] = hCPU->gpr[rA] / hCPU->gpr[rB]; - PPCInterpreter_setXerOV(hCPU, false); if (opHasRC()) ppc_update_cr0(hCPU, hCPU->gpr[rD]); PPCInterpreter_nextInstruction(hCPU); @@ -491,6 +567,13 @@ static void PPCInterpreter_CRANDC(PPCInterpreter_t* hCPU, uint32 opcode) PPCInterpreter_nextInstruction(hCPU); } +static void PPCInterpreter_CRNAND(PPCInterpreter_t* hCPU, uint32 opcode) +{ + PPC_OPC_TEMPL_X_CR(); + ppc_setCRBit(hCPU, crD, (ppc_getCRBit(hCPU, crA)&ppc_getCRBit(hCPU, crB)) ^ 1); + PPCInterpreter_nextInstruction(hCPU); +} + static void PPCInterpreter_CROR(PPCInterpreter_t* hCPU, uint32 opcode) { PPC_OPC_TEMPL_X_CR(); diff --git a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterImpl.cpp b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterImpl.cpp index cacfa4a9..547472ab 100644 --- a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterImpl.cpp +++ b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterImpl.cpp @@ -428,9 +428,6 @@ public: } }; -uint32 testIP[100]; -uint32 testIPC = 0; - template class PPCInterpreterContainer { @@ -466,6 +463,10 @@ public: case 1: // virtual HLE PPCInterpreter_virtualHLE(hCPU, opcode); break; + case 3: + cemuLog_logDebug(LogType::Force, "Unsupported TWI instruction executed at {:08x}", hCPU->instructionPointer); + PPCInterpreter_nextInstruction(hCPU); + break; case 4: switch (PPC_getBits(opcode, 30, 5)) { @@ -482,8 +483,9 @@ public: PPCInterpreter_PS_CMPU1(hCPU, opcode); break; default: - debug_printf("Unknown execute %04X as [4->0] at %08X\n", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer); + cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [4->0] at {:08x}", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer); cemu_assert_unimplemented(); + hCPU->instructionPointer += 4; break; } break; @@ -509,8 +511,9 @@ public: PPCInterpreter_PS_ABS(hCPU, opcode); break; default: - debug_printf("Unknown execute %04X as [4->8] at %08X\n", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer); + cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [4->8] at {:08x}", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer); cemu_assert_unimplemented(); + hCPU->instructionPointer += 4; break; } break; @@ -548,8 +551,9 @@ public: PPCInterpreter_PS_MERGE11(hCPU, opcode); break; default: - debug_printf("Unknown execute %04X as [4->16] at %08X\n", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer); - debugBreakpoint(); + cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [4->16] at {:08x}", PPC_getBits(opcode, 25, 5), hCPU->instructionPointer); + cemu_assert_unimplemented(); + hCPU->instructionPointer += 4; break; } break; @@ -590,8 +594,9 @@ public: PPCInterpreter_PS_NMADD(hCPU, opcode); break; default: - debug_printf("Unknown execute %04X as [4] at %08X\n", PPC_getBits(opcode, 30, 5), hCPU->instructionPointer); + cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [4] at {:08x}", PPC_getBits(opcode, 30, 5), hCPU->instructionPointer); cemu_assert_unimplemented(); + hCPU->instructionPointer += 4; break; } break; @@ -623,12 +628,15 @@ public: PPCInterpreter_BCX(hCPU, opcode); break; case 17: - if (PPC_getBits(opcode, 30, 1) == 1) { + if (PPC_getBits(opcode, 30, 1) == 1) + { PPCInterpreter_SC(hCPU, opcode); } - else { - debug_printf("Unsupported Opcode [0x17 --> 0x0]\n"); + else + { + cemuLog_logDebug(LogType::Force, "Unsupported Opcode [0x17 --> 0x0]"); cemu_assert_unimplemented(); + hCPU->instructionPointer += 4; } break; case 18: @@ -658,6 +666,9 @@ public: case 193: PPCInterpreter_CRXOR(hCPU, opcode); break; + case 225: + PPCInterpreter_CRNAND(hCPU, opcode); + break; case 257: PPCInterpreter_CRAND(hCPU, opcode); break; @@ -674,8 +685,9 @@ public: PPCInterpreter_BCCTR(hCPU, opcode); break; default: - debug_printf("Unknown execute %04X as [19] at %08X\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer); + cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [19] at {:08x}\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer); cemu_assert_unimplemented(); + hCPU->instructionPointer += 4; break; } break; @@ -713,9 +725,6 @@ public: PPCInterpreter_CMP(hCPU, opcode); break; case 4: - #ifdef CEMU_DEBUG_ASSERT - debug_printf("TW instruction executed at %08x\n", hCPU->instructionPointer); - #endif PPCInterpreter_TW(hCPU, opcode); break; case 8: @@ -895,6 +904,12 @@ public: case 522: PPCInterpreter_ADDCO(hCPU, opcode); break; + case 523: // 11 | OE + PPCInterpreter_MULHWU_(hCPU, opcode); // OE is ignored + break; + case 533: + PPCInterpreter_LSWX(hCPU, opcode); + break; case 534: PPCInterpreter_LWBRX(hCPU, opcode); break; @@ -913,6 +928,9 @@ public: case 567: PPCInterpreter_LFSUX(hCPU, opcode); break; + case 587: // 75 | OE + PPCInterpreter_MULHW_(hCPU, opcode); // OE is ignored for MULHW + break; case 595: PPCInterpreter_MFSR(hCPU, opcode); break; @@ -943,15 +961,30 @@ public: case 663: PPCInterpreter_STFSX(hCPU, opcode); break; + case 661: + PPCInterpreter_STSWX(hCPU, opcode); + break; case 695: PPCInterpreter_STFSUX(hCPU, opcode); break; + case 712: // 200 | OE + PPCInterpreter_SUBFZEO(hCPU, opcode); + break; + case 714: // 202 | OE + PPCInterpreter_ADDZEO(hCPU, opcode); + break; case 725: PPCInterpreter_STSWI(hCPU, opcode); break; case 727: PPCInterpreter_STFDX(hCPU, opcode); break; + case 744: // 232 | OE + PPCInterpreter_SUBFMEO(hCPU, opcode); + break; + case 746: // 234 | OE + PPCInterpreter_ADDMEO(hCPU, opcode); + break; case 747: PPCInterpreter_MULLWO(hCPU, opcode); break; @@ -998,10 +1031,8 @@ public: PPCInterpreter_DCBZ(hCPU, opcode); break; default: - debug_printf("Unknown execute %04X as [31] at %08X\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer); - #ifdef CEMU_DEBUG_ASSERT - assert_dbg(); - #endif + cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [31] at {:08x}\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer); + cemu_assert_unimplemented(); hCPU->instructionPointer += 4; break; } @@ -1084,7 +1115,7 @@ public: case 57: PPCInterpreter_PSQ_LU(hCPU, opcode); break; - case 59: //Opcode category + case 59: // opcode category switch (PPC_getBits(opcode, 30, 5)) { case 18: @@ -1115,8 +1146,9 @@ public: PPCInterpreter_FNMADDS(hCPU, opcode); break; default: - debug_printf("Unknown execute %04X as [59] at %08X\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer); + cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [59] at {:08x}\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer); cemu_assert_unimplemented(); + hCPU->instructionPointer += 4; break; } break; @@ -1195,18 +1227,19 @@ public: case 583: PPCInterpreter_MFFS(hCPU, opcode); break; - case 711: // IBM documentation has this wrong as 771? + case 711: PPCInterpreter_MTFSF(hCPU, opcode); break; default: - debug_printf("Unknown execute %04X as [63] at %08X\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer); + cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} as [63] at {:08x}\n", PPC_getBits(opcode, 30, 10), hCPU->instructionPointer); cemu_assert_unimplemented(); + PPCInterpreter_nextInstruction(hCPU); break; } } break; default: - debug_printf("Unknown execute %04X at %08X\n", PPC_getBits(opcode, 5, 6), (unsigned int)hCPU->instructionPointer); + cemuLog_logDebug(LogType::Force, "Unknown execute {:04x} at {:08x}\n", PPC_getBits(opcode, 5, 6), (unsigned int)hCPU->instructionPointer); cemu_assert_unimplemented(); } } diff --git a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp index 26467458..ea7bb038 100644 --- a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp +++ b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp @@ -31,7 +31,7 @@ static void PPCInterpreter_STW(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STWU(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS; + sint32 rA, rS; uint32 imm; PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm); ppcItpCtrl::ppcMem_writeDataU32(hCPU, hCPU->gpr[rA] + imm, hCPU->gpr[rS]); @@ -42,7 +42,7 @@ static void PPCInterpreter_STWU(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STWX(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS, rB; + sint32 rA, rS, rB; PPC_OPC_TEMPL_X(Opcode, rS, rA, rB); ppcItpCtrl::ppcMem_writeDataU32(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], hCPU->gpr[rS]); PPCInterpreter_nextInstruction(hCPU); @@ -103,7 +103,7 @@ static void PPCInterpreter_STWCX(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STWUX(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS, rB; + sint32 rA, rS, rB; PPC_OPC_TEMPL_X(Opcode, rS, rA, rB); ppcItpCtrl::ppcMem_writeDataU32(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], hCPU->gpr[rS]); if (rA) @@ -113,7 +113,7 @@ static void PPCInterpreter_STWUX(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STWBRX(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS, rB; + sint32 rA, rS, rB; PPC_OPC_TEMPL_X(Opcode, rS, rA, rB); ppcItpCtrl::ppcMem_writeDataU32(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], _swapEndianU32(hCPU->gpr[rS])); PPCInterpreter_nextInstruction(hCPU); @@ -121,7 +121,7 @@ static void PPCInterpreter_STWBRX(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STMW(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rS, rA; + sint32 rS, rA; uint32 imm; PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm); uint32 ea = (rA ? hCPU->gpr[rA] : 0) + imm; @@ -136,7 +136,7 @@ static void PPCInterpreter_STMW(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STH(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS; + sint32 rA, rS; uint32 imm; PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm); ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + imm, (uint16)hCPU->gpr[rS]); @@ -145,7 +145,7 @@ static void PPCInterpreter_STH(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STHU(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS; + sint32 rA, rS; uint32 imm; PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm); ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + imm, (uint16)hCPU->gpr[rS]); @@ -156,7 +156,7 @@ static void PPCInterpreter_STHU(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STHX(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS, rB; + sint32 rA, rS, rB; PPC_OPC_TEMPL_X(Opcode, rS, rA, rB); ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], (uint16)hCPU->gpr[rS]); PPCInterpreter_nextInstruction(hCPU); @@ -164,7 +164,7 @@ static void PPCInterpreter_STHX(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STHUX(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS, rB; + sint32 rA, rS, rB; PPC_OPC_TEMPL_X(Opcode, rS, rA, rB); ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], (uint16)hCPU->gpr[rS]); if (rA) @@ -174,7 +174,7 @@ static void PPCInterpreter_STHUX(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STHBRX(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS, rB; + sint32 rA, rS, rB; PPC_OPC_TEMPL_X(Opcode, rS, rA, rB); ppcItpCtrl::ppcMem_writeDataU16(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], _swapEndianU16((uint16)hCPU->gpr[rS])); PPCInterpreter_nextInstruction(hCPU); @@ -182,7 +182,7 @@ static void PPCInterpreter_STHBRX(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STB(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS; + sint32 rA, rS; uint32 imm; PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm); ppcItpCtrl::ppcMem_writeDataU8(hCPU, (rA ? hCPU->gpr[rA] : 0) + imm, (uint8)hCPU->gpr[rS]); @@ -191,7 +191,7 @@ static void PPCInterpreter_STB(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STBU(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS; + sint32 rA, rS; uint32 imm; PPC_OPC_TEMPL_D_SImm(Opcode, rS, rA, imm); ppcItpCtrl::ppcMem_writeDataU8(hCPU, hCPU->gpr[rA] + imm, (uint8)hCPU->gpr[rS]); @@ -201,7 +201,7 @@ static void PPCInterpreter_STBU(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STBX(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS, rB; + sint32 rA, rS, rB; PPC_OPC_TEMPL_X(Opcode, rS, rA, rB); ppcItpCtrl::ppcMem_writeDataU8(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], (uint8)hCPU->gpr[rS]); PPCInterpreter_nextInstruction(hCPU); @@ -209,7 +209,7 @@ static void PPCInterpreter_STBX(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STBUX(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS, rB; + sint32 rA, rS, rB; PPC_OPC_TEMPL_X(Opcode, rS, rA, rB); ppcItpCtrl::ppcMem_writeDataU8(hCPU, (rA ? hCPU->gpr[rA] : 0) + hCPU->gpr[rB], (uint8)hCPU->gpr[rS]); if (rA) @@ -219,7 +219,7 @@ static void PPCInterpreter_STBUX(PPCInterpreter_t* hCPU, uint32 Opcode) static void PPCInterpreter_STSWI(PPCInterpreter_t* hCPU, uint32 Opcode) { - int rA, rS, nb; + sint32 rA, rS, nb; PPC_OPC_TEMPL_X(Opcode, rS, rA, nb); if (nb == 0) nb = 32; uint32 ea = rA ? hCPU->gpr[rA] : 0; @@ -229,7 +229,39 @@ static void PPCInterpreter_STSWI(PPCInterpreter_t* hCPU, uint32 Opcode) { if (i == 0) { - r = hCPU->gpr[rS]; + r = rS < 32 ? hCPU->gpr[rS] : 0; // what happens if rS is out of bounds? + rS++; + rS %= 32; + i = 4; + } + ppcItpCtrl::ppcMem_writeDataU8(hCPU, ea, (r >> 24)); + r <<= 8; + ea++; + i--; + nb--; + } + PPCInterpreter_nextInstruction(hCPU); +} + +static void PPCInterpreter_STSWX(PPCInterpreter_t* hCPU, uint32 Opcode) +{ + sint32 rA, rS, rB; + PPC_OPC_TEMPL_X(Opcode, rS, rA, rB); + sint32 nb = hCPU->spr.XER&0x7F; + if (nb == 0) + { + PPCInterpreter_nextInstruction(hCPU); + return; + } + uint32 ea = rA ? hCPU->gpr[rA] : 0; + ea += hCPU->gpr[rB]; + uint32 r = 0; + int i = 0; + while (nb > 0) + { + if (i == 0) + { + r = rS < 32 ? hCPU->gpr[rS] : 0; // what happens if rS is out of bounds? rS++; rS %= 32; i = 4; @@ -460,7 +492,6 @@ static void PPCInterpreter_LSWI(PPCInterpreter_t* hCPU, uint32 Opcode) PPC_OPC_TEMPL_X(Opcode, rD, rA, nb); if (nb == 0) nb = 32; - uint32 ea = rA ? hCPU->gpr[rA] : 0; uint32 r = 0; int i = 4; @@ -470,7 +501,8 @@ static void PPCInterpreter_LSWI(PPCInterpreter_t* hCPU, uint32 Opcode) if (i == 0) { i = 4; - hCPU->gpr[rD] = r; + if(rD < 32) + hCPU->gpr[rD] = r; rD++; rD %= 32; r = 0; @@ -487,7 +519,52 @@ static void PPCInterpreter_LSWI(PPCInterpreter_t* hCPU, uint32 Opcode) r <<= 8; i--; } - hCPU->gpr[rD] = r; + if(rD < 32) + hCPU->gpr[rD] = r; + PPCInterpreter_nextInstruction(hCPU); +} + +static void PPCInterpreter_LSWX(PPCInterpreter_t* hCPU, uint32 Opcode) +{ + sint32 rA, rD, rB; + PPC_OPC_TEMPL_X(Opcode, rD, rA, rB); + // byte count comes from XER + uint32 nb = (hCPU->spr.XER>>0)&0x7F; + if (nb == 0) + { + PPCInterpreter_nextInstruction(hCPU); + return; // no-op + } + uint32 ea = rA ? hCPU->gpr[rA] : 0; + ea += hCPU->gpr[rB]; + uint32 r = 0; + int i = 4; + uint8 v; + while (nb>0) + { + if (i == 0) + { + i = 4; + if(rD < 32) + hCPU->gpr[rD] = r; + rD++; + rD %= 32; + r = 0; + } + v = ppcItpCtrl::ppcMem_readDataU8(hCPU, ea); + r <<= 8; + r |= v; + ea++; + i--; + nb--; + } + while (i) + { + r <<= 8; + i--; + } + if(rD < 32) + hCPU->gpr[rD] = r; PPCInterpreter_nextInstruction(hCPU); } diff --git a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterMain.cpp b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterMain.cpp index 08d6765a..4449f135 100644 --- a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterMain.cpp +++ b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterMain.cpp @@ -77,7 +77,8 @@ uint32 PPCInterpreter_getXER(PPCInterpreter_t* hCPU) void PPCInterpreter_setXER(PPCInterpreter_t* hCPU, uint32 v) { - hCPU->spr.XER = v; + const uint32 XER_MASK = 0xE0FFFFFF; // some bits are masked out. Figure out which ones exactly + hCPU->spr.XER = v & XER_MASK; hCPU->xer_ca = (v >> XER_BIT_CA) & 1; hCPU->xer_so = (v >> XER_BIT_SO) & 1; hCPU->xer_ov = (v >> XER_BIT_OV) & 1; diff --git a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterOPC.cpp b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterOPC.cpp index d6b643ee..7809a01d 100644 --- a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterOPC.cpp +++ b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterOPC.cpp @@ -93,7 +93,6 @@ void PPCInterpreter_MTCRF(PPCInterpreter_t* hCPU, uint32 Opcode) { // frequently used by GCC compiled code (e.g. SM64 port) // tested - uint32 rS; uint32 crfMask; PPC_OPC_TEMPL_XFX(Opcode, rS, crfMask); diff --git a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterOPC.hpp b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterOPC.hpp index 718162be..9bfcd53d 100644 --- a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterOPC.hpp +++ b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterOPC.hpp @@ -68,6 +68,8 @@ static void PPCInterpreter_TW(PPCInterpreter_t* hCPU, uint32 opcode) PPC_OPC_TEMPL_X(opcode, to, rA, rB); cemu_assert_debug(to == 0); + if(to != 0) + PPCInterpreter_nextInstruction(hCPU); if (rA == DEBUGGER_BP_T_DEBUGGER) debugger_enterTW(hCPU); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_OSScreen.cpp b/src/Cafe/OS/libs/coreinit/coreinit_OSScreen.cpp index 371ead3c..7b51629e 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_OSScreen.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_OSScreen.cpp @@ -96,7 +96,6 @@ namespace coreinit { ppcDefineParamU32(screenIndex, 0); cemu_assert(screenIndex < 2); - cemuLog_logDebug(LogType::Force, "OSScreenFlipBuffersEx {}", screenIndex); LatteGPUState.osScreen.screen[screenIndex].flipRequestCount++; _updateCurrentDrawScreen(screenIndex); osLib_returnFromFunction(hCPU, 0);