testenv: Make code_mem mobile
This commit is contained in:
parent
391e16be64
commit
ff84740ea6
4 changed files with 86 additions and 75 deletions
|
@ -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});
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
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<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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue