From d2c7394abd1329eb43013b2231d751cea4ea4003 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 18 Sep 2026 06:06:10 +0000 Subject: [PATCH] 2026-09-18 06:06:10 Signed-off-by: lizzie --- .../backend/x64/a32_emit_x64_memory.cpp | 3 +- .../backend/x64/a64_emit_x64_memory.cpp | 3 +- .../backend/x64/emit_x64_memory.cpp.inc | 54 ++++++++----------- .../dynarmic/backend/x64/emit_x64_memory.h | 40 ++++++++++---- 4 files changed, 52 insertions(+), 48 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp index f138b5f137..079a7b58e3 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp @@ -11,8 +11,7 @@ #include #include -#include -#include +#include "common/logging.h" #include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp index 4b7054b4b2..9997c275fc 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp @@ -11,8 +11,7 @@ #include #include -#include -#include +#include "common/logging.h" #include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc index 4fa14d504b..5267e7d5ed 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -11,10 +14,6 @@ #define AxxJitState CONCATENATE_TOKENS(Axx, JitState) #define AxxUserConfig Axx::UserConfig -namespace { -using Vector = std::array; -} - std::optional AxxEmitX64::ShouldFastmem(AxxEmitContext& ctx, IR::Inst* inst) const { if (!conf.fastmem_pointer || !exception_handler.SupportsFastmem()) { return std::nullopt; @@ -28,22 +27,19 @@ std::optional AxxEmitX64::ShouldFastmem(AxxEmitC } FakeCall AxxEmitX64::FastmemCallback(u64 rip_) { - const auto iter = fastmem_patch_info.find(rip_); - if (iter != fastmem_patch_info.end()) { + if (auto const it = fastmem_patch_info.find(rip_); it != fastmem_patch_info.end()) { FakeCall result{ - .call_rip = iter->second.callback, - .ret_rip = iter->second.resume_rip, + .call_rip = it->second.callback, + .ret_rip = it->second.resume_rip, }; - if (iter->second.recompile) { - const auto marker = iter->second.marker; + if (it->second.recompile) { + const auto marker = it->second.marker; do_not_fastmem.insert(marker); InvalidateBasicBlocks({std::get<0>(marker)}); } return result; } - fmt::print("dynarmic: Segfault happened within JITted code at rip = {:016x}\n" - "Segfault wasn't at a fastmem patch location!\n", rip_); - UNREACHABLE(); //("iter != fastmem_patch_info.end()"); + UNREACHABLE_MSG("SIGSEGV @ JIT, rip={:#016x}", rip_); //("iter != fastmem_patch_info.end()"); } template @@ -83,22 +79,17 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) { const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(code, args[1]); const int value_idx = bitsize == 128 ? ctx.reg_alloc.ScratchXmm(code).getIdx() : ctx.reg_alloc.ScratchGpr(code).getIdx(); - const auto wrapped_fn = read_fallbacks[std::make_tuple(ordered, bitsize, vaddr.getIdx(), value_idx)]; SharedLabel abort = ctx.GenSharedLabel(), end = ctx.GenSharedLabel(); - if (fastmem_marker) { // Use fastmem bool require_abort_handling = false; const auto src_ptr = EmitFastmemVAddr(code, ctx, *abort, vaddr, require_abort_handling); - const auto location = EmitReadMemoryMov(code, value_idx, src_ptr, ordered); - ctx.deferred_emits.emplace_back([=, this, &ctx] { code.L(*abort); code.call(wrapped_fn); - fastmem_patch_info.emplace( std::bit_cast(location), FastmemPatchInfo{ @@ -107,25 +98,23 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) { *fastmem_marker, conf.recompile_on_fastmem_failure, }); - EmitCheckMemoryAbort(ctx, inst, end); code.jmp(*end, code.T_NEAR); }); - } else { + } else if (conf.page_table) { // Use page table - ASSERT(conf.page_table); const auto src_ptr = EmitVAddrLookup(code, ctx, bitsize, *abort, vaddr); EmitReadMemoryMov(code, value_idx, src_ptr, ordered); - ctx.deferred_emits.emplace_back([=, this, &ctx] { code.L(*abort); code.call(wrapped_fn); EmitCheckMemoryAbort(ctx, inst, end); code.jmp(*end, code.T_NEAR); }); + } else { + UNREACHABLE(); } code.L(*end); - if constexpr (bitsize == 128) { ctx.reg_alloc.DefineValue(code, inst, Xbyak::Xmm{value_idx}); } else { @@ -168,18 +157,16 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) { const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(code, args[1]); const int value_idx = bitsize == 128 - ? ctx.reg_alloc.UseXmm(code, args[2]).getIdx() - : (ordered ? ctx.reg_alloc.UseScratchGpr(code, args[2]).getIdx() : ctx.reg_alloc.UseGpr(code, args[2]).getIdx()); + ? ctx.reg_alloc.UseXmm(code, args[2]).getIdx() + : (ordered ? ctx.reg_alloc.UseScratchGpr(code, args[2]).getIdx() : ctx.reg_alloc.UseGpr(code, args[2]).getIdx()); const auto wrapped_fn = write_fallbacks[std::make_tuple(ordered, bitsize, vaddr.getIdx(), value_idx)]; SharedLabel abort = ctx.GenSharedLabel(), end = ctx.GenSharedLabel(); - if (fastmem_marker) { // Use fastmem bool require_abort_handling = false; const auto dest_ptr = EmitFastmemVAddr(code, ctx, *abort, vaddr, require_abort_handling); - const auto location = EmitWriteMemoryMov(code, dest_ptr, value_idx, ordered); ctx.deferred_emits.emplace_back([=, this, &ctx] { @@ -198,9 +185,8 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) { EmitCheckMemoryAbort(ctx, inst, end); code.jmp(*end, code.T_NEAR); }); - } else { + } else if (conf.page_table) { // Use page table - ASSERT(conf.page_table); const auto dest_ptr = EmitVAddrLookup(code, ctx, bitsize, *abort, vaddr); EmitWriteMemoryMov(code, dest_ptr, value_idx, ordered); @@ -210,6 +196,8 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) { EmitCheckMemoryAbort(ctx, inst, end); code.jmp(*end, code.T_NEAR); }); + } else { + UNREACHABLE(); } code.L(*end); } @@ -251,8 +239,8 @@ void AxxEmitX64::EmitExclusiveReadMemory(AxxEmitContext& ctx, IR::Inst* inst) { code.mfence(); } code.CallLambda( - [](AxxUserConfig& conf, Axx::VAddr vaddr, Vector& ret) { - ret = conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> Vector { + [](AxxUserConfig& conf, Axx::VAddr vaddr, u128& ret) { + ret = conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> u128 { return (conf.callbacks->*callback)(vaddr); }); }); @@ -303,8 +291,8 @@ void AxxEmitX64::EmitExclusiveWriteMemory(AxxEmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.AllocStackSpace(code, 16 + ABI_SHADOW_SPACE); code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]); code.movaps(xword[code.ABI_PARAM3], xmm1); - code.CallLambda([](AxxUserConfig& conf, Axx::VAddr vaddr, Vector& value) -> u32 { - return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, [&](Vector expected) -> bool { + code.CallLambda([](AxxUserConfig& conf, Axx::VAddr vaddr, u128& value) -> u32 { + return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, [&](u128 expected) -> bool { return (conf.callbacks->*callback)(vaddr, value, expected); }) ? 0 : 1; }); diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h index d072b9963d..1b18d2a54f 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h @@ -135,10 +135,16 @@ template<> if (unused_top_bits == 0) { code.mov(tmp, vaddr); code.shr(tmp, int(page_table_const_bits)); + if (ctx.conf.page_table_log2_stride > 3) { + code.shl(tmp, int(ctx.conf.page_table_log2_stride)); + code.mov(page, qword[r14 + tmp.cvt64()]); + } else { + code.mov(page, qword[r14 + tmp.cvt64() * int(1 << ctx.conf.page_table_log2_stride)]); + } } else if (ctx.conf.silently_mirror_page_table) { if (valid_page_index_bits >= 32) { if (code.HasHostFeature(HostFeature::BMI2)) { - const Xbyak::Reg64 bit_count = ctx.reg_alloc.ScratchGpr(code); + auto const bit_count = ctx.reg_alloc.ScratchGpr(code); code.mov(bit_count, unused_top_bits); code.bzhi(tmp, vaddr, bit_count); code.shr(tmp, int(page_table_const_bits)); @@ -153,19 +159,31 @@ template<> code.shr(tmp, int(page_table_const_bits)); code.and_(tmp, u32((1 << valid_page_index_bits) - 1)); } + if (ctx.conf.page_table_log2_stride > 3) { + code.shl(tmp, int(ctx.conf.page_table_log2_stride)); + code.mov(page, qword[r14 + tmp.cvt64()]); + } else { + code.mov(page, qword[r14 + tmp.cvt64() * int(1 << ctx.conf.page_table_log2_stride)]); + } } else { + // Common VA sizes: 39 - 12 => 27, 42 - 12 => 30 + // Check if bits outside of VA space are non-zero ASSERT(valid_page_index_bits < 32); code.mov(tmp, vaddr); + if (ctx.conf.check_halt_on_memory_access) { + auto const tmp2 = ctx.reg_alloc.ScratchGpr(code); + code.mov(tmp2, u64(-(1ull << valid_page_index_bits) << page_table_const_bits)); + code.test(tmp, tmp2); + code.jnz(abort, code.T_NEAR); + ctx.reg_alloc.Release(tmp2); + } code.shr(tmp, int(page_table_const_bits)); - code.test(tmp, u32(-(1 << valid_page_index_bits))); - code.jnz(abort, code.T_NEAR); - } - - if (ctx.conf.page_table_log2_stride > 3) { - code.shl(tmp, int(ctx.conf.page_table_log2_stride)); - code.mov(page, qword[r14 + tmp.cvt64()]); - } else { - code.mov(page, qword[r14 + tmp.cvt64() * int(1 << ctx.conf.page_table_log2_stride)]); + if (ctx.conf.page_table_log2_stride > 3) { + code.shl(tmp, int(ctx.conf.page_table_log2_stride)); + code.mov(page, qword[r14 + tmp.cvt64()]); + } else { + code.mov(page, qword[r14 + tmp.cvt64() * int(1 << ctx.conf.page_table_log2_stride)]); + } } // check for marked bit, use as unmapped if marked @@ -193,7 +211,7 @@ template<> return page + vaddr; } code.mov(tmp, vaddr); - code.and_(tmp, static_cast(page_table_const_mask)); + code.and_(tmp, u32(page_table_const_mask)); return page + tmp; }