From ff84740ea608b9cd8e3e81211fb2d2f5e7f24864 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Wed, 1 Aug 2018 15:25:40 +0100 Subject: [PATCH] testenv: Make code_mem mobile --- tests/A64/a64.cpp | 106 ++++++++++++++++---------------- tests/A64/fuzz_with_unicorn.cpp | 18 +++--- tests/A64/testenv.h | 24 +++++--- tests/A64/verify_unicorn.cpp | 13 ++-- 4 files changed, 86 insertions(+), 75 deletions(-) diff --git a/tests/A64/a64.cpp b/tests/A64/a64.cpp index 8e505f99..ce3df9bc 100644 --- a/tests/A64/a64.cpp +++ b/tests/A64/a64.cpp @@ -14,8 +14,8 @@ TEST_CASE("A64: ADD", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x8b020020; // ADD X0, X1, X2 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x8b020020); // ADD X0, X1, X2 + env.code_mem.emplace_back(0x14000000); // B . jit.SetRegister(0, 0); jit.SetRegister(1, 1); @@ -35,9 +35,9 @@ TEST_CASE("A64: REV", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0xdac00c00; // REV X0, X0 - env.code_mem[1] = 0x5ac00821; // REV W1, W1 - env.code_mem[2] = 0x14000000; // B . + env.code_mem.emplace_back(0xdac00c00); // REV X0, X0 + env.code_mem.emplace_back(0x5ac00821); // REV W1, W1 + env.code_mem.emplace_back(0x14000000); // B . jit.SetRegister(0, 0xaabbccddeeff1100); jit.SetRegister(1, 0xaabbccdd); @@ -55,8 +55,8 @@ TEST_CASE("A64: REV32", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0xdac00800; // REV32 X0, X0 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0xdac00800); // REV32 X0, X0 + env.code_mem.emplace_back(0x14000000); // B . jit.SetRegister(0, 0xaabbccddeeff1100); jit.SetPC(0); @@ -71,9 +71,9 @@ TEST_CASE("A64: REV16", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0xdac00400; // REV16 X0, X0 - env.code_mem[1] = 0x5ac00421; // REV16 W1, W1 - env.code_mem[2] = 0x14000000; // B . + env.code_mem.emplace_back(0xdac00400); // REV16 X0, X0 + env.code_mem.emplace_back(0x5ac00421); // REV16 W1, W1 + env.code_mem.emplace_back(0x14000000); // B . jit.SetRegister(0, 0xaabbccddeeff1100); jit.SetRegister(1, 0xaabbccdd); @@ -91,8 +91,8 @@ TEST_CASE("A64: AND", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x8a020020; // AND X0, X1, X2 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x8a020020); // AND X0, X1, X2 + env.code_mem.emplace_back(0x14000000); // B . jit.SetRegister(0, 0); jit.SetRegister(1, 1); @@ -112,10 +112,10 @@ TEST_CASE("A64: Bitmasks", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x3200c3e0; // ORR W0, WZR, #0x01010101 - env.code_mem[1] = 0x320c8fe1; // ORR W1, WZR, #0x00F000F0 - env.code_mem[2] = 0x320003e2; // ORR W2, WZR, #1 - env.code_mem[3] = 0x14000000; // B . + env.code_mem.emplace_back(0x3200c3e0); // ORR W0, WZR, #0x01010101 + env.code_mem.emplace_back(0x320c8fe1); // ORR W1, WZR, #0x00F000F0 + env.code_mem.emplace_back(0x320003e2); // ORR W2, WZR, #1 + env.code_mem.emplace_back(0x14000000); // B . jit.SetPC(0); @@ -132,8 +132,8 @@ TEST_CASE("A64: ANDS NZCV", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x6a020020; // ANDS W0, W1, W2 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x6a020020); // ANDS W0, W1, W2 + env.code_mem.emplace_back(0x14000000); // B . SECTION("N=1, Z=0") { jit.SetRegister(0, 0); @@ -187,11 +187,11 @@ TEST_CASE("A64: CBZ", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x34000060; // CBZ X0, label - env.code_mem[1] = 0x320003e2; // MOV X2, 1 - env.code_mem[2] = 0x14000000; // B. - env.code_mem[3] = 0x321f03e2; // label: MOV X2, 2 - env.code_mem[4] = 0x14000000; // B . + env.code_mem.emplace_back(0x34000060); // 0x00 : CBZ X0, label + env.code_mem.emplace_back(0x320003e2); // 0x04 : MOV X2, 1 + env.code_mem.emplace_back(0x14000000); // 0x08 : B. + env.code_mem.emplace_back(0x321f03e2); // 0x0C : label: MOV X2, 2 + env.code_mem.emplace_back(0x14000000); // 0x10 : B . SECTION("no branch") { jit.SetPC(0); @@ -220,11 +220,11 @@ TEST_CASE("A64: TBZ", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x36180060; // TBZ X0, 3, label - env.code_mem[1] = 0x320003e2; // MOV X2, 1 - env.code_mem[2] = 0x14000000; // B . - env.code_mem[3] = 0x321f03e2; // label: MOV X2, 2 - env.code_mem[4] = 0x14000000; // B . + env.code_mem.emplace_back(0x36180060); // 0x00 : TBZ X0, 3, label + env.code_mem.emplace_back(0x320003e2); // 0x04 : MOV X2, 1 + env.code_mem.emplace_back(0x14000000); // 0x08 : B . + env.code_mem.emplace_back(0x321f03e2); // 0x0C : label: MOV X2, 2 + env.code_mem.emplace_back(0x14000000); // 0x10 : B . SECTION("no branch") { jit.SetPC(0); @@ -264,8 +264,8 @@ TEST_CASE("A64: FABD", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x6eb5d556; // FABD.4S V22, V10, V21 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x6eb5d556); // FABD.4S V22, V10, V21 + env.code_mem.emplace_back(0x14000000); // B . jit.SetPC(0); jit.SetVector(10, {0xb4858ac77ff39a87, 0x9fce5e14c4873176}); @@ -294,9 +294,9 @@ TEST_CASE("A64: 128-bit exclusive read/write", "[a64]") { Dynarmic::A64::Jit jit{conf}; - env.code_mem[0] = 0xc87f0861; // LDXP X1, X2, [X3] - env.code_mem[1] = 0xc8241865; // STXP W4, X5, X6, [X3] - env.code_mem[2] = 0x14000000; // B . + env.code_mem.emplace_back(0xc87f0861); // LDXP X1, X2, [X3] + env.code_mem.emplace_back(0xc8241865); // STXP W4, X5, X6, [X3] + env.code_mem.emplace_back(0x14000000); // B . jit.SetPC(0); jit.SetRegister(3, 0x1234567812345678); @@ -318,16 +318,16 @@ TEST_CASE("A64: CNTPCT_EL0", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0xd53be021; // MRS X1, CNTPCT_EL0 - env.code_mem[1] = 0xd503201f; // NOP - env.code_mem[2] = 0xd503201f; // NOP - env.code_mem[3] = 0xd503201f; // NOP - env.code_mem[4] = 0xd503201f; // NOP - env.code_mem[5] = 0xd503201f; // NOP - env.code_mem[6] = 0xd503201f; // NOP - env.code_mem[7] = 0xd53be022; // MRS X2, CNTPCT_EL0 - env.code_mem[8] = 0xcb010043; // SUB X3, X2, X1 - env.code_mem[9] = 0x14000000; // B . + env.code_mem.emplace_back(0xd53be021); // MRS X1, CNTPCT_EL0 + env.code_mem.emplace_back(0xd503201f); // NOP + env.code_mem.emplace_back(0xd503201f); // NOP + env.code_mem.emplace_back(0xd503201f); // NOP + env.code_mem.emplace_back(0xd503201f); // NOP + env.code_mem.emplace_back(0xd503201f); // NOP + env.code_mem.emplace_back(0xd503201f); // NOP + env.code_mem.emplace_back(0xd53be022); // MRS X2, CNTPCT_EL0 + env.code_mem.emplace_back(0xcb010043); // SUB X3, X2, X1 + env.code_mem.emplace_back(0x14000000); // B . env.ticks_left = 10; jit.Run(); @@ -339,8 +339,8 @@ TEST_CASE("A64: FNMSUB 1", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x1f618a9c; // FNMSUB D28, D20, D1, D2 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x1f618a9c); // FNMSUB D28, D20, D1, D2 + env.code_mem.emplace_back(0x14000000); // B . jit.SetPC(0); jit.SetVector(20, {0xe73a51346164bd6c, 0x8080000000002b94}); @@ -357,8 +357,8 @@ TEST_CASE("A64: FNMSUB 2", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x1f2ab88e; // FNMSUB S14, S4, S10, S14 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x1f2ab88e); // FNMSUB S14, S4, S10, S14 + env.code_mem.emplace_back(0x14000000); // B . jit.SetPC(0); jit.SetVector(4, {0x3c9623b101398437, 0x7ff0abcd0ba98d27}); @@ -376,8 +376,8 @@ TEST_CASE("A64: FMADD", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x1f5e0e4a; // FMADD D10, D18, D30, D3 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x1f5e0e4a); // FMADD D10, D18, D30, D3 + env.code_mem.emplace_back(0x14000000); // B . jit.SetPC(0); jit.SetVector(18, {0x8000007600800000, 0x7ff812347f800000}); @@ -395,8 +395,8 @@ TEST_CASE("A64: FMLA.4S (denormal)", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x4e2fcccc; // FMLA.4S V12, V6, V15 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x4e2fcccc); // FMLA.4S V12, V6, V15 + env.code_mem.emplace_back(0x14000000); // B . jit.SetPC(0); jit.SetVector(12, {0x3c9623b17ff80000, 0xbff0000080000076}); @@ -414,8 +414,8 @@ TEST_CASE("A64: FMLA.4S (0x80800000)", "[a64]") { TestEnv env; Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}}; - env.code_mem[0] = 0x4e38cc2b; // FMLA.4S V11, V1, V24 - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x4e38cc2b); // FMLA.4S V11, V1, V24 + env.code_mem.emplace_back(0x14000000); // B . jit.SetPC(0); jit.SetVector(11, {0xc79b271efff05678, 0xffc0000080800000}); diff --git a/tests/A64/fuzz_with_unicorn.cpp b/tests/A64/fuzz_with_unicorn.cpp index 84b17c30..ed21a6fe 100644 --- a/tests/A64/fuzz_with_unicorn.cpp +++ b/tests/A64/fuzz_with_unicorn.cpp @@ -158,15 +158,17 @@ static u32 GenFloatInst(u64 pc, bool is_last_inst) { } } -static void RunTestInstance(const Unicorn::RegisterArray& regs, const Unicorn::VectorArray& vecs, const size_t instructions_offset, +static void RunTestInstance(const Unicorn::RegisterArray& regs, const Unicorn::VectorArray& vecs, const size_t instructions_start, const std::vector& instructions, const u32 pstate, const u32 fpcr) { static TestEnv jit_env{}; static TestEnv uni_env{}; - std::copy(instructions.begin(), instructions.end(), jit_env.code_mem.begin() + instructions_offset); - std::copy(instructions.begin(), instructions.end(), uni_env.code_mem.begin() + instructions_offset); - jit_env.code_mem[instructions.size() + instructions_offset] = 0x14000000; // B . - uni_env.code_mem[instructions.size() + instructions_offset] = 0x14000000; // B . + jit_env.code_mem = instructions; + uni_env.code_mem = instructions; + jit_env.code_mem.emplace_back(0x14000000); // B . + uni_env.code_mem.emplace_back(0x14000000); // B . + jit_env.code_mem_start_address = instructions_start; + uni_env.code_mem_start_address = instructions_start; jit_env.modified_memory.clear(); uni_env.modified_memory.clear(); jit_env.interrupts.clear(); @@ -182,7 +184,7 @@ static void RunTestInstance(const Unicorn::RegisterArray& regs, const Unicorn::V jit.SetRegisters(regs); jit.SetVectors(vecs); - jit.SetPC(instructions_offset * 4); + jit.SetPC(instructions_start); jit.SetSP(0x08000000); jit.SetFpcr(fpcr); jit.SetFpsr(0); @@ -190,7 +192,7 @@ static void RunTestInstance(const Unicorn::RegisterArray& regs, const Unicorn::V jit.ClearCache(); uni.SetRegisters(regs); uni.SetVectors(vecs); - uni.SetPC(instructions_offset * 4); + uni.SetPC(instructions_start); uni.SetSP(0x08000000); uni.SetFpcr(fpcr); uni.SetFpsr(0); @@ -215,7 +217,7 @@ static void RunTestInstance(const Unicorn::RegisterArray& regs, const Unicorn::V for (size_t i = 0; i < vecs.size(); ++i) fmt::print("{:3s}: {}\n", static_cast(i), vecs[i]); fmt::print("sp : 08000000\n"); - fmt::print("pc : {:016x}\n", instructions_offset * 4); + fmt::print("pc : {:016x}\n", instructions_start); fmt::print("p : {:08x}\n", pstate); fmt::print("fpcr {:08x}\n", fpcr); fmt::print("fpcr.AHP {}\n", FP::FPCR{fpcr}.AHP()); diff --git a/tests/A64/testenv.h b/tests/A64/testenv.h index 5c2bb29e..a8b6e10c 100644 --- a/tests/A64/testenv.h +++ b/tests/A64/testenv.h @@ -19,22 +19,30 @@ using Vector = Dynarmic::A64::Vector; class TestEnv final : public Dynarmic::A64::UserCallbacks { public: u64 ticks_left = 0; + bool code_mem_modified_by_guest = false; - std::array code_mem{}; + u64 code_mem_start_address = 0; + std::vector code_mem; + std::map modified_memory; std::vector interrupts; + bool IsInCodeMem(u64 vaddr) const { + return vaddr >= code_mem_start_address && vaddr < code_mem_start_address + code_mem.size() * 4; + } + std::uint32_t MemoryReadCode(u64 vaddr) override { - if (vaddr < code_mem.size() * sizeof(u32)) { - size_t index = vaddr / sizeof(u32); - return code_mem[index]; + if (!IsInCodeMem(vaddr)) { + return 0x14000000; // B . } - return 0x14000000; // B . + + const size_t index = (vaddr - code_mem_start_address) / 4; + return code_mem[index]; } std::uint8_t MemoryRead8(u64 vaddr) override { - if (vaddr < 4 * code_mem.size()) { - return reinterpret_cast(code_mem.data())[vaddr]; + if (IsInCodeMem(vaddr)) { + return reinterpret_cast(code_mem.data())[vaddr - code_mem_start_address]; } if (auto iter = modified_memory.find(vaddr); iter != modified_memory.end()) { return iter->second; @@ -55,7 +63,7 @@ public: } void MemoryWrite8(u64 vaddr, std::uint8_t value) override { - if (vaddr < code_mem.size() * sizeof(u32)) { + if (IsInCodeMem(vaddr)) { code_mem_modified_by_guest = true; } modified_memory[vaddr] = value; diff --git a/tests/A64/verify_unicorn.cpp b/tests/A64/verify_unicorn.cpp index d005ff29..da675f9b 100644 --- a/tests/A64/verify_unicorn.cpp +++ b/tests/A64/verify_unicorn.cpp @@ -16,8 +16,9 @@ using namespace Dynarmic; TEST_CASE("Unicorn: Sanity test", "[a64]") { TestEnv env; - env.code_mem[0] = 0x8b020020; // ADD X0, X1, X2 - env.code_mem[1] = 0x14000000; // B . + + env.code_mem.emplace_back(0x8b020020); // ADD X0, X1, X2 + env.code_mem.emplace_back(0x14000000); // B . constexpr Unicorn::RegisterArray regs{ 0, 1, 2, 0, 0, 0, 0, 0, @@ -43,8 +44,8 @@ TEST_CASE("Unicorn: Sanity test", "[a64]") { TEST_CASE("Unicorn: Ensure 0xFFFF'FFFF'FFFF'FFFF is readable", "[a64]") { TestEnv env; - env.code_mem[0] = 0x385fed99; // LDRB W25, [X12, #0xfffffffffffffffe]! - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0x385fed99); // LDRB W25, [X12, #0xfffffffffffffffe]! + env.code_mem.emplace_back(0x14000000); // B . Unicorn::RegisterArray regs{}; regs[12] = 1; @@ -63,8 +64,8 @@ TEST_CASE("Unicorn: Ensure 0xFFFF'FFFF'FFFF'FFFF is readable", "[a64]") { TEST_CASE("Unicorn: Ensure is able to read across page boundaries", "[a64]") { TestEnv env; - env.code_mem[0] = 0xb85f93d9; // LDUR W25, [X30, #0xfffffffffffffff9] - env.code_mem[1] = 0x14000000; // B . + env.code_mem.emplace_back(0xb85f93d9); // LDUR W25, [X30, #0xfffffffffffffff9] + env.code_mem.emplace_back(0x14000000); // B . Unicorn::RegisterArray regs{}; regs[30] = 4;