mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-02 13:01:18 +12:00
CPU: Implement more instructions in interpreter + various fixes
All of the changes are verified against real hardware, except for the byte string instructions
This commit is contained in:
parent
0a121c97c7
commit
7db2b77983
7 changed files with 281 additions and 87 deletions
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue