a32_unicorn: Halt when PC leaves code_mem

This commit is contained in:
MerryMage 2021-02-06 22:15:02 +00:00
parent 331a02e02e
commit b252636dc3
3 changed files with 13 additions and 18 deletions

View file

@ -215,6 +215,8 @@ static void RunTestInstance(Dynarmic::A32::Jit& jit,
jit_env.code_mem.resize(code_mem_size);
uni_env.code_mem.resize(code_mem_size);
std::fill(jit_env.code_mem.begin(), jit_env.code_mem.end(), TestEnv::infinite_loop);
std::fill(uni_env.code_mem.begin(), uni_env.code_mem.end(), TestEnv::infinite_loop);
std::copy(instructions.begin(), instructions.end(), jit_env.code_mem.begin() + num_words);
std::copy(instructions.begin(), instructions.end(), uni_env.code_mem.begin() + num_words);
@ -240,20 +242,7 @@ static void RunTestInstance(Dynarmic::A32::Jit& jit,
jit_env.ticks_left = ticks_left;
jit.Run();
uni_env.ticks_left = [&]{
if constexpr (std::is_same_v<TestEnv, ThumbTestEnv>) {
// Unicorn counts thumb instructions weirdly:
// A 32-bit thumb instruction counts as two.
// Except for branch instructions which count as one???
if (instructions.size() <= 1)
return ticks_left;
if ((instructions[instructions.size() - 2] & 0xF800) <= 0xE800)
return instructions.size();
return instructions.size() - 1;
} else {
return ticks_left;
}
}();
uni_env.ticks_left = instructions.size(); // Unicorn counts thumb instructions weirdly.
uni.Run();
SCOPE_FAIL {

View file

@ -37,18 +37,21 @@ public:
} while (code_mem.size() % 2 != 0);
}
bool IsInCodeMem(u32 vaddr) const {
return vaddr < sizeof(InstructionType) * code_mem.size();
}
std::uint32_t MemoryReadCode(u32 vaddr) override {
const size_t index = vaddr / sizeof(InstructionType);
if (index < code_mem.size()) {
if (IsInCodeMem(vaddr)) {
u32 value;
std::memcpy(&value, &code_mem[index], sizeof(u32));
std::memcpy(&value, &code_mem[vaddr / sizeof(InstructionType)], sizeof(u32));
return value;
}
return infinite_loop_u32; // B .
}
std::uint8_t MemoryRead8(u32 vaddr) override {
if (vaddr < sizeof(InstructionType) * code_mem.size()) {
if (IsInCodeMem(vaddr)) {
return reinterpret_cast<u8*>(code_mem.data())[vaddr];
}
if (auto iter = modified_memory.find(vaddr); iter != modified_memory.end()) {

View file

@ -44,6 +44,9 @@ void A32Unicorn<TestEnvironment>::Run() {
constexpr u64 pc_mask = std::is_same_v<TestEnvironment, ArmTestEnv> ? 0 : 1;
while (testenv.ticks_left > 0) {
const u32 pc = GetPC() | pc_mask;
if (!testenv.IsInCodeMem(pc)) {
return;
}
if (auto cerr_ = uc_emu_start(uc, pc, END_ADDRESS, 0, 1)) {
ASSERT_MSG(false, "uc_emu_start failed @ {:08x} (code = {:08x}) with error {} ({})", pc, testenv.MemoryReadCode(pc), cerr_, uc_strerror(cerr_));
}