tests/A64: Test memory writes
This commit is contained in:
parent
94383fd934
commit
a8ed248a13
4 changed files with 32 additions and 5 deletions
|
@ -52,7 +52,7 @@ restart:
|
||||||
if (!should_continue && !is_last_inst)
|
if (!should_continue && !is_last_inst)
|
||||||
goto restart;
|
goto restart;
|
||||||
for (const auto& ir_inst : block)
|
for (const auto& ir_inst : block)
|
||||||
if (ir_inst.IsMemoryWrite() || ir_inst.GetOpcode() == IR::Opcode::A64ExceptionRaised || ir_inst.GetOpcode() == IR::Opcode::A64CallSupervisor)
|
if (ir_inst.GetOpcode() == IR::Opcode::A64ExceptionRaised || ir_inst.GetOpcode() == IR::Opcode::A64CallSupervisor)
|
||||||
goto restart;
|
goto restart;
|
||||||
|
|
||||||
return instruction;
|
return instruction;
|
||||||
|
@ -87,11 +87,12 @@ static void RunTestInstance(const std::array<u64, 31>& regs, const std::array<Ve
|
||||||
uni_env.ticks_left = instructions.size();
|
uni_env.ticks_left = instructions.size();
|
||||||
uni.Run();
|
uni.Run();
|
||||||
|
|
||||||
|
REQUIRE(uni.GetPC() == jit.GetPC());
|
||||||
REQUIRE(uni.GetRegisters() == jit.GetRegisters());
|
REQUIRE(uni.GetRegisters() == jit.GetRegisters());
|
||||||
REQUIRE(uni.GetVectors() == jit.GetVectors());
|
REQUIRE(uni.GetVectors() == jit.GetVectors());
|
||||||
REQUIRE(uni.GetPC() == jit.GetPC());
|
|
||||||
REQUIRE(uni.GetSP() == jit.GetSP());
|
REQUIRE(uni.GetSP() == jit.GetSP());
|
||||||
REQUIRE((uni.GetPstate() & 0xF0000000) == (jit.GetPstate() & 0xF0000000));
|
REQUIRE((uni.GetPstate() & 0xF0000000) == (jit.GetPstate() & 0xF0000000));
|
||||||
|
REQUIRE(uni_env.modified_memory == jit_env.modified_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("A64: Single random instruction", "[a64]") {
|
TEST_CASE("A64: Single random instruction", "[a64]") {
|
||||||
|
|
|
@ -74,7 +74,7 @@ public:
|
||||||
}
|
}
|
||||||
void MemoryWrite128(u64 vaddr, Vector value) override {
|
void MemoryWrite128(u64 vaddr, Vector value) override {
|
||||||
MemoryWrite64(vaddr, value[0]);
|
MemoryWrite64(vaddr, value[0]);
|
||||||
MemoryWrite64(vaddr + 4, value[1]);
|
MemoryWrite64(vaddr + 8, value[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterpreterFallback(u64 pc, size_t num_instructions) override { ASSERT_MSG(false, "InterpreterFallback(%" PRIx64 ", %zu)", pc, num_instructions); }
|
void InterpreterFallback(u64 pc, size_t num_instructions) override { ASSERT_MSG(false, "InterpreterFallback(%" PRIx64 ", %zu)", pc, num_instructions); }
|
||||||
|
|
|
@ -24,6 +24,7 @@ Unicorn::Unicorn(TestEnv& testenv) : testenv(testenv) {
|
||||||
CHECKED(uc_reg_write(uc, UC_ARM64_REG_CPACR_EL1, &fpv));
|
CHECKED(uc_reg_write(uc, UC_ARM64_REG_CPACR_EL1, &fpv));
|
||||||
CHECKED(uc_hook_add(uc, &intr_hook, UC_HOOK_INTR, (void*)InterruptHook, this, BEGIN_ADDRESS, END_ADDRESS));
|
CHECKED(uc_hook_add(uc, &intr_hook, UC_HOOK_INTR, (void*)InterruptHook, this, BEGIN_ADDRESS, END_ADDRESS));
|
||||||
CHECKED(uc_hook_add(uc, &mem_invalid_hook, UC_HOOK_MEM_INVALID, (void*)UnmappedMemoryHook, this, BEGIN_ADDRESS, END_ADDRESS));
|
CHECKED(uc_hook_add(uc, &mem_invalid_hook, UC_HOOK_MEM_INVALID, (void*)UnmappedMemoryHook, this, BEGIN_ADDRESS, END_ADDRESS));
|
||||||
|
CHECKED(uc_hook_add(uc, &mem_write_prot_hook, UC_HOOK_MEM_WRITE, (void*)MemoryWriteHook, this, BEGIN_ADDRESS, END_ADDRESS));
|
||||||
}
|
}
|
||||||
|
|
||||||
Unicorn::~Unicorn() {
|
Unicorn::~Unicorn() {
|
||||||
|
@ -173,10 +174,10 @@ bool Unicorn::UnmappedMemoryHook(uc_engine* uc, uc_mem_type /*type*/, u64 start_
|
||||||
const auto generate_page = [&](u64 base_address) {
|
const auto generate_page = [&](u64 base_address) {
|
||||||
// printf("generate_page(%" PRIx64 ")\n", base_address);
|
// printf("generate_page(%" PRIx64 ")\n", base_address);
|
||||||
|
|
||||||
const u32 permissions = [&]{
|
const u32 permissions = [&]() -> u32 {
|
||||||
if (base_address < this_->testenv.code_mem.size() * 4)
|
if (base_address < this_->testenv.code_mem.size() * 4)
|
||||||
return UC_PROT_READ | UC_PROT_EXEC;
|
return UC_PROT_READ | UC_PROT_EXEC;
|
||||||
return UC_PROT_READ | UC_PROT_WRITE;
|
return UC_PROT_READ;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
auto page = std::make_unique<Page>();
|
auto page = std::make_unique<Page>();
|
||||||
|
@ -209,3 +210,26 @@ bool Unicorn::UnmappedMemoryHook(uc_engine* uc, uc_mem_type /*type*/, u64 start_
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Unicorn::MemoryWriteHook(uc_engine* /*uc*/, uc_mem_type /*type*/, u64 start_address, int size, u64 value, void* user_data) {
|
||||||
|
Unicorn* this_ = reinterpret_cast<Unicorn*>(user_data);
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
this_->testenv.MemoryWrite8(start_address, static_cast<u8>(value));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
this_->testenv.MemoryWrite16(start_address, static_cast<u16>(value));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
this_->testenv.MemoryWrite32(start_address, static_cast<u32>(value));
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
this_->testenv.MemoryWrite64(start_address, value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ public:
|
||||||
private:
|
private:
|
||||||
static void InterruptHook(uc_engine* uc, u32 interrupt, void* user_data);
|
static void InterruptHook(uc_engine* uc, u32 interrupt, void* user_data);
|
||||||
static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value, void* user_data);
|
static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value, void* user_data);
|
||||||
|
static bool MemoryWriteHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value, void* user_data);
|
||||||
|
|
||||||
struct Page {
|
struct Page {
|
||||||
u64 address;
|
u64 address;
|
||||||
|
@ -59,6 +60,7 @@ private:
|
||||||
uc_engine* uc{};
|
uc_engine* uc{};
|
||||||
uc_hook intr_hook{};
|
uc_hook intr_hook{};
|
||||||
uc_hook mem_invalid_hook{};
|
uc_hook mem_invalid_hook{};
|
||||||
|
uc_hook mem_write_prot_hook{};
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Page>> pages;
|
std::vector<std::unique_ptr<Page>> pages;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue