testenv: Make code_mem mobile

This commit is contained in:
MerryMage 2018-08-01 15:25:40 +01:00
parent 391e16be64
commit ff84740ea6
4 changed files with 86 additions and 75 deletions

View file

@ -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});

View file

@ -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<u32>& 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<A64::Vec>(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());

View file

@ -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<u32, 1024> code_mem{};
u64 code_mem_start_address = 0;
std::vector<u32> code_mem;
std::map<u64, u8> modified_memory;
std::vector<std::string> interrupts;
std::uint32_t MemoryReadCode(u64 vaddr) override {
if (vaddr < code_mem.size() * sizeof(u32)) {
size_t index = vaddr / sizeof(u32);
return code_mem[index];
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 (!IsInCodeMem(vaddr)) {
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<u8*>(code_mem.data())[vaddr];
if (IsInCodeMem(vaddr)) {
return reinterpret_cast<u8*>(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;

View file

@ -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;