CPU: Implement more instructions in interpreter + various fixes
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 44s

All of the changes are verified against real hardware, except for the byte string instructions
This commit is contained in:
Exzap 2025-06-28 14:53:15 +02:00
parent 0a121c97c7
commit 7db2b77983
7 changed files with 281 additions and 87 deletions

View file

@ -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,13 +467,13 @@ 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 < 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]);
@ -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);
}
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;
}
hCPU->gpr[rD] = hCPU->gpr[rA] / hCPU->gpr[rB];
else if(a == 0x80000000 && b == 0xFFFFFFFF)
{
PPCInterpreter_setXerOV(hCPU, false);
hCPU->gpr[rD] = 0;
}
else
{
hCPU->gpr[rD] = a / b;
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();

View file

@ -428,9 +428,6 @@ public:
}
};
uint32 testIP[100];
uint32 testIPC = 0;
template <typename ppcItpCtrl>
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();
}
}

View file

@ -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,6 +501,7 @@ static void PPCInterpreter_LSWI(PPCInterpreter_t* hCPU, uint32 Opcode)
if (i == 0)
{
i = 4;
if(rD < 32)
hCPU->gpr[rD] = r;
rD++;
rD %= 32;
@ -487,6 +519,51 @@ static void PPCInterpreter_LSWI(PPCInterpreter_t* hCPU, uint32 Opcode)
r <<= 8;
i--;
}
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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);