diff --git a/src/dynarmic/backend/arm64/abi.h b/src/dynarmic/backend/arm64/abi.h index e39f0781..93ba6b5a 100644 --- a/src/dynarmic/backend/arm64/abi.h +++ b/src/dynarmic/backend/arm64/abi.h @@ -6,6 +6,8 @@ #pragma once #include +#include +#include #include #include @@ -48,6 +50,22 @@ constexpr std::initializer_list FPR_ORDER{8, 9, 10, 11, 12, 13, 14, 15, 16, using RegisterList = u64; +constexpr RegisterList ToRegList(oaknut::Reg reg) { + if (reg.is_vector()) { + return RegisterList{1} << (reg.index() + 32); + } + + if (reg.index() == 31) { + throw std::out_of_range("ZR not allowed in reg list"); + } + + if (reg.index() == -1) { + return RegisterList{1} << 31; + } + + return RegisterList{1} << reg.index(); +} + constexpr RegisterList ABI_CALLEE_SAVE = 0x0000ff00'3ff80000; constexpr RegisterList ABI_CALLER_SAVE = 0xffffffff'4000ffff; diff --git a/src/dynarmic/backend/arm64/emit_arm64_memory.cpp b/src/dynarmic/backend/arm64/emit_arm64_memory.cpp index 4de30869..e7b3f85c 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_memory.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64_memory.cpp @@ -336,7 +336,7 @@ void InlinePageTableEmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx EmitMemoryLdr(code, Rvalue->index(), Xbase, Xoffset, ordered); ctx.deferred_emits.emplace_back([&code, &ctx, inst, Xaddr = *Xaddr, Rvalue = *Rvalue, ordered, fallback, end] { - const u64 save_regs = ABI_CALLER_SAVE & ~((bitsize == 128 ? (1ull << 32) : 1ull) << Rvalue.index()); + const u64 save_regs = ABI_CALLER_SAVE & ~ToRegList(Rvalue); code.l(*fallback); ABI_PushRegisters(code, save_regs, 0); code.MOV(X1, Xaddr);