mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-06 15:01:18 +12:00
245 lines
6.4 KiB
C++
245 lines
6.4 KiB
C++
|
|
struct PPCInterpreterLLEContext_t
|
|
{
|
|
uint8 padding[1024 * 128]; // reserved memory for stack (for recompiler mode)
|
|
PPCInterpreter_t cores[3];
|
|
};
|
|
|
|
PPCInterpreterGlobal_t globalCPUState = { 0 };
|
|
|
|
void PPCCoreLLE_initCore(PPCInterpreter_t* hCPU, uint32 coreIndex)
|
|
{
|
|
hCPU->spr.UPIR = coreIndex;
|
|
hCPU->global = &globalCPUState;
|
|
}
|
|
|
|
#define SCR_C2 (0x200000) // enable core 2
|
|
#define SCR_C1 (0x400000) // enable core 1
|
|
|
|
typedef struct
|
|
{
|
|
uint32be ukn000;
|
|
uint32be ukn004;
|
|
uint32be ukn008;
|
|
uint32be ukn00C;
|
|
uint32be ukn010;
|
|
uint32be ukn014;
|
|
uint32be busFreq;
|
|
uint32be ukn01C;
|
|
uint32be ukn020[4];
|
|
uint32be ukn030[4];
|
|
uint32be ukn040[4];
|
|
uint32be ukn050[4];
|
|
uint32be ukn060[4];
|
|
uint32be ukn070[4];
|
|
uint32be ukn080[4];
|
|
uint32be ukn090[4];
|
|
uint32be ukn0A0[4];
|
|
uint32be ukn0B0[4];
|
|
uint32be ukn0C0;
|
|
struct
|
|
{
|
|
uint32be id;
|
|
uint32be baseAddress;
|
|
uint32be size;
|
|
}ramInfo[3];
|
|
uint32 ukn0E8;
|
|
uint32 ukn0EC;
|
|
uint32 ukn0F0[4];
|
|
uint32 ukn100[8];
|
|
uint32 ukn120[8];
|
|
uint32 ukn140[8];
|
|
uint32 ukn160[8];
|
|
uint32 ukn180[8];
|
|
uint32 ukn1A0[8];
|
|
uint32 ukn1C0[8];
|
|
uint32 ukn1E0[8];
|
|
uint32 ukn200[8];
|
|
uint32 ukn220[8];
|
|
uint32 ukn240[8];
|
|
uint32 ukn260[8];
|
|
uint32 ukn280[8];
|
|
uint32 ukn2A0[8];
|
|
uint32 ukn2C0[8];
|
|
uint32 ukn2E0[8];
|
|
uint32 ukn300[8];
|
|
uint32 ukn320[8];
|
|
uint32 ukn340[8];
|
|
uint32 ukn360[8];
|
|
uint32 ukn380[8];
|
|
uint32be ukn3A0;
|
|
uint32be ukn3A4;
|
|
uint32be ukn3A8;
|
|
uint32be ukn3AC;
|
|
uint32be ukn3B0;
|
|
uint32be smdpAreaPtr;
|
|
uint32be ukn3B8;
|
|
uint32be ukn3BC;
|
|
uint32 ukn3C0[8];
|
|
uint32 ukn3E0[8];
|
|
uint32 ukn400;
|
|
uint32 ukn404;
|
|
uint32 ukn408;
|
|
}ppcBootParamBlock_t; // for kernel 5.5.2
|
|
|
|
static_assert(offsetof(ppcBootParamBlock_t, ramInfo) == 0xC4, "");
|
|
static_assert(offsetof(ppcBootParamBlock_t, busFreq) == 0x18, "");
|
|
static_assert(offsetof(ppcBootParamBlock_t, smdpAreaPtr) == 0x3B4, "");
|
|
static_assert(offsetof(ppcBootParamBlock_t, ukn400) == 0x400, "");
|
|
|
|
void PPCCoreLLE_setupBootParamBlock()
|
|
{
|
|
ppcBootParamBlock_t* bootParamBlock = (ppcBootParamBlock_t*)memory_getPointerFromPhysicalOffset(0x01FFF000);
|
|
memset(bootParamBlock, 0, sizeof(ppcBootParamBlock_t));
|
|
|
|
// setup RAM info
|
|
//PPCBaseAddress 0x8000000 0x00000000 0x28000000
|
|
//PPCSize 0x120000 0x2000000 0xA8000000
|
|
|
|
bootParamBlock->ukn004 = 0x40C;
|
|
|
|
bootParamBlock->busFreq = ESPRESSO_BUS_CLOCK;
|
|
|
|
bootParamBlock->ramInfo[0].id = 0;
|
|
bootParamBlock->ramInfo[0].baseAddress = 0x8000000;
|
|
bootParamBlock->ramInfo[0].size = 0x120000;
|
|
bootParamBlock->ramInfo[1].id = 1;
|
|
bootParamBlock->ramInfo[1].baseAddress = 0x00000000;
|
|
bootParamBlock->ramInfo[1].size = 0x2000000;
|
|
bootParamBlock->ramInfo[2].id = 2;
|
|
bootParamBlock->ramInfo[2].baseAddress = 0x28000000;
|
|
bootParamBlock->ramInfo[2].size = 0xA8000000;
|
|
|
|
}
|
|
typedef struct
|
|
{
|
|
uint32be magic;
|
|
uint32be count;
|
|
uint32 _padding08[14];
|
|
/* +0x0040 */ uint32be commandsReadIndex; // written by IOSU
|
|
uint32 _padding44[15];
|
|
/* +0x0080 */ uint32be commandsWriteIndex;
|
|
uint32 _padding84[15];
|
|
/* +0x00C0 */ uint32be resultsReadIndex;
|
|
uint32 _paddingC4[15];
|
|
/* +0x0100 */ uint32be resultsWriteIndex; // written by IOSU
|
|
uint32 _padding104[15];
|
|
/* +0x0140 */ uint32be commandPtrs[0xC00];
|
|
/* +0x3140 */ uint32be resultPtrs[0xC00];
|
|
}smdpArea_t;
|
|
|
|
static_assert(offsetof(smdpArea_t, commandsReadIndex) == 0x0040, "");
|
|
static_assert(offsetof(smdpArea_t, commandsWriteIndex) == 0x0080, "");
|
|
static_assert(offsetof(smdpArea_t, resultsReadIndex) == 0x00C0, "");
|
|
static_assert(offsetof(smdpArea_t, resultsWriteIndex) == 0x0100, "");
|
|
static_assert(offsetof(smdpArea_t, resultPtrs) == 0x3140, "");
|
|
|
|
typedef struct
|
|
{
|
|
uint32be type;
|
|
uint32be ukn04;
|
|
uint32be ukn08;
|
|
uint32be ukn0C;
|
|
uint32be ukn10;
|
|
uint32be ukn14;
|
|
uint32be ukn18;
|
|
uint32be ukn1C;
|
|
uint32be ukn20;
|
|
uint32be ukn24;
|
|
uint32be ukn28;
|
|
uint32be ukn2C;
|
|
}smdpCommand_t;
|
|
|
|
void smdpArea_pushResult(smdpArea_t* smdpArea, MPTR result)
|
|
{
|
|
//smdpArea.
|
|
smdpArea->resultPtrs[(uint32)smdpArea->resultsWriteIndex] = result;
|
|
smdpArea->resultsWriteIndex = ((uint32)smdpArea->resultsWriteIndex + 1)%(uint32)smdpArea->count;
|
|
}
|
|
|
|
void smdpArea_processCommand(smdpArea_t* smdpArea, smdpCommand_t* cmd)
|
|
{
|
|
if (cmd->type == 1)
|
|
{
|
|
cmd->ukn08 = 1;
|
|
// cmd->ukn2C ?
|
|
cemuLog_logDebug(LogType::Force, "SMDP command received - todo");
|
|
smdpArea_pushResult(smdpArea, memory_getVirtualOffsetFromPointer(cmd));
|
|
}
|
|
else
|
|
{
|
|
assert_dbg();
|
|
}
|
|
}
|
|
|
|
void smdpArea_thread()
|
|
{
|
|
while (true)
|
|
{
|
|
ppcBootParamBlock_t* bootParamBlock = (ppcBootParamBlock_t*)memory_getPointerFromPhysicalOffset(0x01FFF000);
|
|
if(bootParamBlock->smdpAreaPtr != MPTR_NULL)
|
|
{
|
|
smdpArea_t* smdpArea = (smdpArea_t*)memory_getPointerFromPhysicalOffset(bootParamBlock->smdpAreaPtr);
|
|
if (smdpArea->magic == 'smdp')
|
|
{
|
|
uint32 cmdReadIndex = smdpArea->commandsReadIndex;
|
|
uint32 cmdWriteIndex = smdpArea->commandsWriteIndex;
|
|
if (cmdReadIndex != cmdWriteIndex)
|
|
{
|
|
// new command
|
|
smdpArea_processCommand(smdpArea, (smdpCommand_t*)memory_getPointerFromPhysicalOffset(smdpArea->commandPtrs[cmdReadIndex]));
|
|
// increment read counter
|
|
cmdReadIndex = (cmdReadIndex + 1) % (uint32)smdpArea->count;
|
|
smdpArea->commandsReadIndex = cmdReadIndex;
|
|
}
|
|
}
|
|
}
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
}
|
|
}
|
|
|
|
void PPCCoreLLE_startSingleCoreScheduler(uint32 entrypoint)
|
|
{
|
|
PPCInterpreterLLEContext_t* cpuContext = (PPCInterpreterLLEContext_t*)malloc(sizeof(PPCInterpreterLLEContext_t));
|
|
memset(cpuContext, 0, sizeof(PPCInterpreterLLEContext_t));
|
|
|
|
PPCCoreLLE_setupBootParamBlock();
|
|
|
|
PPCCoreLLE_initCore(cpuContext->cores + 0, 0);
|
|
PPCCoreLLE_initCore(cpuContext->cores + 1, 1);
|
|
PPCCoreLLE_initCore(cpuContext->cores + 2, 2);
|
|
|
|
cpuContext->cores[0].instructionPointer = entrypoint;
|
|
cpuContext->cores[1].instructionPointer = 0xFFF00100;
|
|
cpuContext->cores[2].instructionPointer = 0xFFF00100;
|
|
// todo - calculate instruction pointer when core 1/2 is enabled (because entry point is determined by MSR exception vector bit)
|
|
std::thread(smdpArea_thread).detach();
|
|
|
|
while (true)
|
|
{
|
|
for (uint32 coreIndex = 0; coreIndex < 3; coreIndex++)
|
|
{
|
|
PPCInterpreter_t* hCPU = cpuContext->cores+coreIndex;
|
|
PPCInterpreter_setCurrentInstance(hCPU);
|
|
if (coreIndex == 1)
|
|
{
|
|
// check SCR core 1 enable bit
|
|
if ((globalCPUState.sprGlobal.scr&SCR_C1) == 0)
|
|
continue;
|
|
}
|
|
else if (coreIndex == 2)
|
|
{
|
|
// check SCR core 2 enable bit
|
|
if ((globalCPUState.sprGlobal.scr&SCR_C2) == 0)
|
|
continue;
|
|
}
|
|
|
|
hCPU->remainingCycles = 10000;
|
|
while ((--hCPU->remainingCycles) >= 0)
|
|
{
|
|
PPCInterpreterFull_executeInstruction(hCPU);
|
|
};
|
|
}
|
|
}
|
|
assert_dbg();
|
|
}
|