From 6c4fa780e078705c1d8b44dc894b3ead1d07bd03 Mon Sep 17 00:00:00 2001 From: merry Date: Sun, 27 Feb 2022 19:54:35 +0000 Subject: [PATCH] {a32,a64}_emit_x64_memory: Ensure return value of fastmem callback are zero-extended --- .../backend/x64/a32_emit_x64_memory.cpp | 1 + .../backend/x64/a64_emit_x64_memory.cpp | 1 + src/dynarmic/backend/x64/block_of_code.h | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp b/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp index e9c14725..35588758 100644 --- a/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp +++ b/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp @@ -53,6 +53,7 @@ void A32EmitX64::GenFastmemFallbacks() { code.mov(Xbyak::Reg64{value_idx}, code.ABI_RETURN); } ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocRegIdx(value_idx)); + code.ZeroExtendFrom(bitsize, Xbyak::Reg64{value_idx}); code.ret(); PerfMapRegister(read_fallbacks[std::make_tuple(bitsize, vaddr_idx, value_idx)], code.getCurr(), fmt::format("a32_read_fallback_{}", bitsize)); } diff --git a/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp b/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp index c472a7c1..d86bdf3f 100644 --- a/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp +++ b/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp @@ -141,6 +141,7 @@ void A64EmitX64::GenFastmemFallbacks() { code.mov(Xbyak::Reg64{value_idx}, code.ABI_RETURN); } ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocRegIdx(value_idx)); + code.ZeroExtendFrom(bitsize, Xbyak::Reg64{value_idx}); code.ret(); PerfMapRegister(read_fallbacks[std::make_tuple(bitsize, vaddr_idx, value_idx)], code.getCurr(), fmt::format("a64_read_fallback_{}", bitsize)); } diff --git a/src/dynarmic/backend/x64/block_of_code.h b/src/dynarmic/backend/x64/block_of_code.h index 97b8930a..17aa9cd7 100644 --- a/src/dynarmic/backend/x64/block_of_code.h +++ b/src/dynarmic/backend/x64/block_of_code.h @@ -96,6 +96,24 @@ public: CallFunction(Common::FptrCast(l)); } + void ZeroExtendFrom(size_t bitsize, Xbyak::Reg64 reg) { + switch (bitsize) { + case 8: + movzx(reg.cvt32(), reg.cvt8()); + return; + case 16: + movzx(reg.cvt32(), reg.cvt16()); + return; + case 32: + mov(reg.cvt32(), reg.cvt32()); + return; + case 64: + return; + default: + UNREACHABLE(); + } + } + Xbyak::Address MConst(const Xbyak::AddressFrame& frame, u64 lower, u64 upper = 0); /// Far code sits far away from the near code. Execution remains primarily in near code.