mirror of
https://github.com/decaf-emu/decaf-emu.git
synced 2025-04-02 10:42:13 -04:00
109 lines
3.9 KiB
C++
109 lines
3.9 KiB
C++
#include <common/decaf_assert.h>
|
|
#include <common/log.h>
|
|
#include <fstream>
|
|
#include <libcpu/cpu.h>
|
|
#include <libcpu/cpu_config.h>
|
|
#include <libcpu/espresso/espresso_disassembler.h>
|
|
#include <libcpu/mem.h>
|
|
#include <memory>
|
|
#include <spdlog/spdlog.h>
|
|
#include <spdlog/sinks/stdout_sinks.h>
|
|
|
|
int
|
|
runTests()
|
|
{
|
|
// Built From http://achurch.org/cpu-tests/ppc750cl.s
|
|
// powerpc-eabi-as ppc750cl.S -o ppc750cl.o --defsym TEST_SC=0 --defsym HAVE_UGQR=1 --defsym TEST_TRAP=0
|
|
// powerpc-eabi-ld ppc750cl.o -o ppc750cl --oformat=binary
|
|
std::ifstream file { "data/achurch.bin", std::ifstream::in | std::ifstream::binary };
|
|
|
|
if (!file.is_open()) {
|
|
gLog->error("Could not open data/achurch.bin");
|
|
return -1;
|
|
}
|
|
|
|
// Calculate the total size of the file
|
|
file.seekg(0, std::ios::end);
|
|
auto file_size = file.tellg();
|
|
file.seekg(0, std::ios::beg);
|
|
|
|
// Allocate code memory
|
|
auto baseCodeAddress = cpu::VirtualAddress { 0x01000000u };
|
|
auto baseCodePhysicalAddress = cpu::PhysicalAddress { 0x50000000u };
|
|
auto codeSize = align_up(static_cast<uint32_t>(file_size), cpu::PageSize);
|
|
cpu::allocateVirtualAddress(baseCodeAddress, codeSize);
|
|
cpu::mapMemory(baseCodeAddress, baseCodePhysicalAddress, codeSize, cpu::MapPermission::ReadWrite);
|
|
|
|
// Allocate data memory
|
|
auto baseDataAddress = cpu::VirtualAddress { 0x03000000u };
|
|
auto baseDataPhysicalAddress = cpu::PhysicalAddress { 0x52000000u };
|
|
auto dataSize = 0x02000000u;
|
|
cpu::allocateVirtualAddress(baseDataAddress, dataSize);
|
|
cpu::mapMemory(baseDataAddress, baseDataPhysicalAddress, dataSize, cpu::MapPermission::ReadWrite);
|
|
|
|
// Read the file directly into PPC memory
|
|
file.read(mem::translate<char>(baseCodeAddress.getAddress()), file_size);
|
|
|
|
auto core = cpu::this_core::state();
|
|
auto scratchMemAddr = baseDataAddress.getAddress() + (dataSize / 2);
|
|
auto failResultsAddr = baseDataAddress.getAddress();
|
|
std::memset(mem::translate<void>(scratchMemAddr), 0, 32 * 1024u);
|
|
|
|
core->nia = baseCodeAddress.getAddress();
|
|
core->gpr[3] = 0;
|
|
core->gpr[4] = scratchMemAddr;
|
|
core->gpr[5] = failResultsAddr;
|
|
core->fpr[1].paired0 = 1.0;
|
|
cpu::this_core::executeSub();
|
|
|
|
auto failedTests = core->gpr[3];
|
|
|
|
if (failedTests) {
|
|
for (uint32_t i = 0; i < failedTests; ++i) {
|
|
uint32_t failedInstr = mem::read<uint32_t>(failResultsAddr + (i * 4 * 8) + 0);
|
|
uint32_t failedAddr = mem::read<uint32_t>(failResultsAddr + (i * 4 * 8) + 4);
|
|
uint32_t failedAux[] = {
|
|
mem::read<uint32_t>(failResultsAddr + (i * 4 * 8) + 8),
|
|
mem::read<uint32_t>(failResultsAddr + (i * 4 * 8) + 12),
|
|
mem::read<uint32_t>(failResultsAddr + (i * 4 * 8) + 16),
|
|
mem::read<uint32_t>(failResultsAddr + (i * 4 * 8) + 20)
|
|
};
|
|
|
|
espresso::Disassembly disassembly;
|
|
espresso::disassemble(failedInstr, disassembly, failedAddr);
|
|
gLog->warn(" {:08x} = {:08x} failed - {}", failedAddr, failedInstr, espresso::disassemblyToText(disassembly));
|
|
gLog->warn(" {:08x} {:08x} {:08x} {:08x}", failedAux[0], failedAux[1], failedAux[2], failedAux[3]);
|
|
}
|
|
|
|
gLog->error("Failed {} tests.", failedTests);
|
|
return static_cast<int>(failedTests);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int runResult;
|
|
auto logger = std::make_shared<spdlog::logger>("logger", std::make_shared<spdlog::sinks::stdout_sink_st>());
|
|
logger->set_level(spdlog::level::debug);
|
|
gLog = logger;
|
|
|
|
auto cpuConfig = cpu::Settings { };
|
|
cpuConfig.jit.enabled = true;
|
|
cpu::setConfig(cpuConfig);
|
|
cpu::initialise();
|
|
|
|
// We need to run the tests on a core.
|
|
cpu::setCoreEntrypointHandler(
|
|
[&runResult](cpu::Core *core) {
|
|
if (cpu::this_core::id() == 1) {
|
|
// Run the tests on only a single core.
|
|
runResult = runTests();
|
|
}
|
|
});
|
|
|
|
cpu::start();
|
|
cpu::join();
|
|
return runResult;
|
|
}
|