From 737b78ad49bbfd9b4cc3d74c3a828bae053d0f36 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Thu, 11 May 2017 15:09:43 -0500 Subject: [PATCH] Last stretch to get PPC native tests working --- src/xenia/base/filesystem_posix.cc | 5 +- src/xenia/base/threading_posix.cc | 3 +- .../ppc/testing/ppc_testing_native_main.cc | 31 ++--- .../ppc/testing/ppc_testing_native_thunks.s | 129 ++++++++++++++---- src/xenia/cpu/ppc/testing/premake5.lua | 12 +- ...ence_branch_carry.s => seq_branch_carry.s} | 0 ..._constants.s => seq_jumptable_constants.s} | 0 xenia-build | 3 +- 8 files changed, 131 insertions(+), 52 deletions(-) rename src/xenia/cpu/ppc/testing/{sequence_branch_carry.s => seq_branch_carry.s} (100%) rename src/xenia/cpu/ppc/testing/{jumptable_constants.s => seq_jumptable_constants.s} (100%) diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc index 21bcbfe4d..b9125e319 100644 --- a/src/xenia/base/filesystem_posix.cc +++ b/src/xenia/base/filesystem_posix.cc @@ -15,7 +15,6 @@ #include #include #include -#include namespace xe { namespace filesystem { @@ -44,7 +43,6 @@ std::vector ListFiles(const std::wstring& path) { while (auto ent = readdir(dir)) { FileInfo info; - std::memset(&info, 0, sizeof(info)); if (ent->d_type == DT_DIR) { info.type = FileInfo::Type::kDirectory; info.total_size = 0; @@ -53,6 +51,9 @@ std::vector ListFiles(const std::wstring& path) { info.total_size = 0; // TODO(DrChat): Find a way to get this } + info.create_timestamp = 0; + info.access_timestamp = 0; + info.write_timestamp = 0; info.name = xe::to_wstring(ent->d_name); result.push_back(info); } diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index c7015e7fe..c9f2ffdd4 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -36,7 +36,8 @@ void set_name(std::thread::native_handle_type handle, const std::string& name) { } void Sleep(std::chrono::microseconds duration) { - timespec rqtp = {duration.count() / 1000000, duration.count() % 1000}; + timespec rqtp = {time_t(duration.count() / 1000000), + time_t(duration.count() % 1000)}; nanosleep(&rqtp, nullptr); // TODO(benvanik): spin while rmtp >0? } diff --git a/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc b/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc index 691617f1b..d83f56b61 100644 --- a/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc +++ b/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc @@ -16,7 +16,6 @@ #include "xenia/base/memory.h" #include "xenia/base/platform.h" #include "xenia/base/string_util.h" -#include "xenia/cpu/ppc/ppc_context.h" #if XE_COMPILER_MSVC #include "xenia/base/platform_win.h" @@ -34,10 +33,10 @@ namespace cpu { namespace test { struct Context { - uint64_t r[32]; - double f[32]; - vec128_t v[32]; // For now, only support 32 vector registers. - uint32_t cr; // Condition register + uint64_t r[32]; // 0x000 + double f[32]; // 0x100 + vec128_t v[32]; // 0x200 For now, only support 32 vector registers. + uint32_t cr; // 0x400 Condition register }; typedef std::vector> AnnotationList; @@ -184,6 +183,7 @@ class TestRunner { memory::PageAccess::kExecuteReadWrite); context_ = memory::AlignedAlloc(32); + std::memset(context_, 0, sizeof(Context)); } ~TestRunner() { @@ -240,7 +240,6 @@ class TestRunner { std::snprintf(out_value, out_value_size, "%016" PRIX64, ctx->r[n]); return false; } - return true; } else if (sscanf(name, "f%d", &n) == 1) { if (std::strstr(value, "0x")) { // Special case: Treat float as integer. @@ -265,7 +264,6 @@ class TestRunner { return false; } } - return true; } else if (sscanf(name, "v%d", &n) == 1) { vec128_t expected = string_util::from_string(value); if (ctx->v[n] != expected) { @@ -274,22 +272,19 @@ class TestRunner { ctx->v[n].i32[3]); return false; } - return true; } else if (std::strcmp(name, "cr") == 0) { - // TODO(DrChat) - /* - uint64_t actual = ctx->cr(); + uint64_t actual = ctx->cr; uint64_t expected = string_util::from_string(value); if (actual != expected) { std::snprintf(out_value, out_value_size, "%016" PRIX64, actual); return false; } - */ - return false; // true; } else { assert_always("Unrecognized register name: %s\n", name); return false; } + + return true; } bool SetRegFromString(const char* name, const char* value, Context* ctx) { @@ -301,10 +296,13 @@ class TestRunner { } else if (sscanf(name, "v%d", &n) == 1) { ctx->v[n] = string_util::from_string(value); } else if (std::strcmp(name, "cr") == 0) { - // this->set_cr(string_util::from_string(value)); + ctx->cr = uint32_t(string_util::from_string(value)); } else { printf("Unrecognized register name: %s\n", name); + return false; } + + return true; } bool SetupTestState(TestCase& test_case) { @@ -480,9 +478,8 @@ bool RunTests(const std::wstring& test_name) { } test_suites.push_back(std::move(test_suite)); } - if (load_failed) { - return false; - } + + XELOGI("%d tests loaded successfully.", (int)test_suites.size()); TestRunner runner; for (auto& test_suite : test_suites) { diff --git a/src/xenia/cpu/ppc/testing/ppc_testing_native_thunks.s b/src/xenia/cpu/ppc/testing/ppc_testing_native_thunks.s index 00b251950..4559d21c4 100644 --- a/src/xenia/cpu/ppc/testing/ppc_testing_native_thunks.s +++ b/src/xenia/cpu/ppc/testing/ppc_testing_native_thunks.s @@ -7,14 +7,20 @@ ****************************************************************************** */ - // r3 = context - // this does not touch r1, r3, r4, r13 +# r3 = context +# this does not touch r1, r3, r4, r13 .load_registers_ctx: + lwz r2, 0x400(r3) # CR + mtcrf 0xFF, r2 + + li r2, 0 + mtxer r2 + ld r0, 0x00(r3) - // r1 cannot be used + # r1 cannot be used ld r2, 0x10(r3) - // r3 will be loaded before the call - // r4 will be loaded before the call + # r3 will be loaded before the call + # r4 will be loaded before the call ld r5, 0x28(r3) ld r6, 0x30(r3) ld r7, 0x38(r3) @@ -23,7 +29,7 @@ ld r10, 0x50(r3) ld r11, 0x58(r3) ld r12, 0x60(r3) - // r13 cannot be used (OS use only) + # r13 cannot be used (OS use only) ld r14, 0x70(r3) ld r15, 0x78(r3) ld r16, 0x80(r3) @@ -42,15 +48,48 @@ ld r29, 0xE8(r3) ld r30, 0xF0(r3) ld r31, 0xF8(r3) + + lfd f0, 0x100(r3) + lfd f1, 0x108(r3) + lfd f2, 0x110(r3) + lfd f3, 0x118(r3) + lfd f4, 0x120(r3) + lfd f5, 0x128(r3) + lfd f6, 0x130(r3) + lfd f7, 0x138(r3) + lfd f8, 0x140(r3) + lfd f9, 0x148(r3) + lfd f10, 0x150(r3) + lfd f11, 0x158(r3) + lfd f12, 0x160(r3) + lfd f13, 0x168(r3) + lfd f14, 0x170(r3) + lfd f15, 0x178(r3) + lfd f16, 0x180(r3) + lfd f17, 0x188(r3) + lfd f18, 0x190(r3) + lfd f19, 0x198(r3) + lfd f20, 0x1A0(r3) + lfd f21, 0x1A8(r3) + lfd f22, 0x1B0(r3) + lfd f23, 0x1B8(r3) + lfd f24, 0x1C0(r3) + lfd f25, 0x1C8(r3) + lfd f26, 0x1D0(r3) + lfd f27, 0x1D8(r3) + lfd f28, 0x1E0(r3) + lfd f29, 0x1E8(r3) + lfd f30, 0x1F0(r3) + lfd f31, 0x1F8(r3) blr -// r3 = context -// this does not save r1, r3, r13 +# r3 = context +# this does not save r1, r3, r13 .save_registers_ctx: std r0, 0x00(r3) - // r1 cannot be used + # r1 cannot be used std r2, 0x10(r3) - // r3 will be saved later + # r3 will be saved later std r4, 0x20(r3) std r5, 0x28(r3) std r6, 0x30(r3) @@ -60,7 +99,7 @@ std r10, 0x50(r3) std r11, 0x58(r3) std r12, 0x60(r3) - // r13 cannot be used (OS use only) + # r13 cannot be used (OS use only) std r14, 0x70(r3) std r15, 0x78(r3) std r16, 0x80(r3) @@ -79,18 +118,54 @@ std r29, 0xE8(r3) std r30, 0xF0(r3) std r31, 0xF8(r3) + + stfd f0, 0x100(r3) + stfd f1, 0x108(r3) + stfd f2, 0x110(r3) + stfd f3, 0x118(r3) + stfd f4, 0x120(r3) + stfd f5, 0x128(r3) + stfd f6, 0x130(r3) + stfd f7, 0x138(r3) + stfd f8, 0x140(r3) + stfd f9, 0x148(r3) + stfd f10, 0x150(r3) + stfd f11, 0x158(r3) + stfd f12, 0x160(r3) + stfd f13, 0x168(r3) + stfd f14, 0x170(r3) + stfd f15, 0x178(r3) + stfd f16, 0x180(r3) + stfd f17, 0x188(r3) + stfd f18, 0x190(r3) + stfd f19, 0x198(r3) + stfd f20, 0x1A0(r3) + stfd f21, 0x1A8(r3) + stfd f22, 0x1B0(r3) + stfd f23, 0x1B8(r3) + stfd f24, 0x1C0(r3) + stfd f25, 0x1C8(r3) + stfd f26, 0x1D0(r3) + stfd f27, 0x1D8(r3) + stfd f28, 0x1E0(r3) + stfd f29, 0x1E8(r3) + stfd f30, 0x1F0(r3) + stfd f31, 0x1F8(r3) + + mfcr r2 # CR + stw r2, 0x400(r3) blr -// void xe_call_native(Context* ctx, void* func) +# void xe_call_native(Context* ctx, void* func) .globl xe_call_native xe_call_native: mflr r12 stw r12, -0x8(r1) - stwu r1, -0x380(r1) // 0x200(gpr + fp) + 0x200(vr) + stwu r1, -0x380(r1) # 0x200(gpr + fp) + 0x200(vr) - // Save nonvolatile registers on the stack. + # Save nonvolatile registers on the stack. std r2, 0x110(r1) - std r3, 0x118(r1) // Store the context, this will be needed later. + std r3, 0x118(r1) # Store the context, this will be needed later. std r14, 0x170(r1) std r15, 0x178(r1) std r16, 0x180(r1) @@ -129,27 +204,27 @@ xe_call_native: stfd f30, 0x2F0(r1) stfd f31, 0x2F8(r1) - // Load registers from context - bl load_registers_ctx + # Load registers from context (except r3/r4) + bl .load_registers_ctx - // Call the test routine + # Call the test routine mtctr r4 - ld r4, 0x28(r3) - ld r3, 0x20(r3) + ld r4, 0x20(r3) + ld r3, 0x18(r3) bctrl - // Temporarily store r3 into the stack (in the place of r0) + # Temporarily store r3 into the stack (in the place of r0) std r3, 0x100(r1) - // Store registers into context + # Store registers into context (except r3) ld r3, 0x118(r1) - bl save_registers_ctx + bl .save_registers_ctx - // Now store r3 + # Now store r3 ld r4, 0x100(r1) - std r4, 0x20(r3) + std r4, 0x18(r3) - // Restore nonvolatile registers from the stack + # Restore nonvolatile registers from the stack ld r2, 0x110(r1) ld r14, 0x170(r1) ld r15, 0x178(r1) @@ -192,4 +267,4 @@ xe_call_native: addi r1, r1, 0x380 lwz r12, -0x8(r1) mtlr r12 - blr \ No newline at end of file + blr diff --git a/src/xenia/cpu/ppc/testing/premake5.lua b/src/xenia/cpu/ppc/testing/premake5.lua index 75fa68180..78874ecc4 100644 --- a/src/xenia/cpu/ppc/testing/premake5.lua +++ b/src/xenia/cpu/ppc/testing/premake5.lua @@ -52,14 +52,18 @@ project("xenia-cpu-ppc-nativetests") "../../../base/main_"..platform_suffix..".cc", }) files({ - "*.s", + "instr_*.s", + "seq_*.s", }) + filter("files:instr_*.s", "files:seq_*.s") + flags({"ExcludeFromBuild"}) + filter({}) includedirs({ project_root.."/third_party/gflags/src", }) - filter("files:*.s") - flags({"ExcludeFromBuild"}) - filter({}) + buildoptions({ + "-Wa,-mregnames", -- Tell GAS to accept register names. + }) files({ "ppc_testing_native_thunks.s", diff --git a/src/xenia/cpu/ppc/testing/sequence_branch_carry.s b/src/xenia/cpu/ppc/testing/seq_branch_carry.s similarity index 100% rename from src/xenia/cpu/ppc/testing/sequence_branch_carry.s rename to src/xenia/cpu/ppc/testing/seq_branch_carry.s diff --git a/src/xenia/cpu/ppc/testing/jumptable_constants.s b/src/xenia/cpu/ppc/testing/seq_jumptable_constants.s similarity index 100% rename from src/xenia/cpu/ppc/testing/jumptable_constants.s rename to src/xenia/cpu/ppc/testing/seq_jumptable_constants.s diff --git a/xenia-build b/xenia-build index 8aa8b50ca..643514fc7 100755 --- a/xenia-build +++ b/xenia-build @@ -850,7 +850,8 @@ class GenTestsCommand(Command): src_files = [os.path.join(root, name) for root, dirs, files in os.walk('src') for name in files - if name.endswith(('.s'))] + if (name.startswith('instr_') or name.startswith('seq_')) + and name.endswith(('.s'))] def make_unix_path(p): """Forces a unix path separator style, as required by binutils.