From 613446086be9d9b6eeae042d6f5800d5ea2e8894 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Sun, 27 Mar 2022 19:27:28 +0200 Subject: [PATCH] early-access version 2615 --- README.md | 2 +- externals/dynarmic/CMakeLists.txt | 2 +- .../dynarmic/src/dynarmic/CMakeLists.txt | 5 +- .../backend/x64/a32_emit_x64_memory.cpp | 128 +------ .../backend/x64/a64_emit_x64_memory.cpp | 315 +----------------- .../dynarmic/backend/x64/emit_x64_memory.h | 227 +++++++++++++ .../src/dynarmic/backend/x64/reg_alloc.cpp | 6 +- .../src/dynarmic/backend/x64/reg_alloc.h | 1 - .../dynarmic/frontend/A32/a32_ir_emitter.cpp | 96 +++--- .../dynarmic/frontend/A32/a32_ir_emitter.h | 36 +- .../impl/asimd_load_store_structures.cpp | 10 +- .../A32/translate/impl/load_store.cpp | 118 ++++--- .../A32/translate/impl/synchronization.cpp | 54 +-- .../frontend/A32/translate/impl/thumb16.cpp | 44 +-- .../A32/translate/impl/thumb32_load_byte.cpp | 6 +- .../translate/impl/thumb32_load_halfword.cpp | 6 +- .../impl/thumb32_load_store_dual.cpp | 69 ++-- .../impl/thumb32_load_store_multiple.cpp | 6 +- .../A32/translate/impl/thumb32_load_word.cpp | 8 +- .../impl/thumb32_store_single_data_item.cpp | 12 +- .../frontend/A32/translate/impl/vfp.cpp | 36 +- .../dynarmic/frontend/A64/a64_ir_emitter.cpp | 80 ++--- .../dynarmic/frontend/A64/a64_ir_emitter.h | 40 +-- .../frontend/A64/translate/impl/impl.cpp | 48 +-- .../frontend/A64/translate/impl/impl.h | 8 +- .../translate/impl/load_store_exclusive.cpp | 4 +- .../impl/load_store_load_literal.cpp | 6 +- .../impl/load_store_multiple_structures.cpp | 8 +- .../impl/load_store_register_immediate.cpp | 6 +- .../impl/load_store_register_pair.cpp | 16 +- .../load_store_register_register_offset.cpp | 4 +- .../impl/load_store_register_unprivileged.cpp | 8 +- .../impl/load_store_single_structure.cpp | 6 +- .../frontend/A64/translate/impl/sys_ic.cpp | 12 +- externals/dynarmic/src/dynarmic/ir/acc_type.h | 29 ++ .../dynarmic/src/dynarmic/ir/ir_emitter.h | 2 +- .../dynarmic/src/dynarmic/ir/opcodes.cpp | 2 +- .../dynarmic/src/dynarmic/ir/opcodes.inc | 72 ++-- .../ir/opt/a64_callback_config_pass.cpp | 6 +- externals/dynarmic/src/dynarmic/ir/type.h | 2 +- externals/dynarmic/src/dynarmic/ir/value.cpp | 8 +- externals/dynarmic/src/dynarmic/ir/value.h | 8 +- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 6 +- .../backend/spirv/emit_spirv_atomic.cpp | 2 + .../spirv/emit_spirv_context_get_set.cpp | 1 + .../backend/spirv/spirv_emit_context.cpp | 1 + 46 files changed, 731 insertions(+), 841 deletions(-) create mode 100755 externals/dynarmic/src/dynarmic/ir/acc_type.h diff --git a/README.md b/README.md index 752f4a435..fbc814b6b 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 2614. +This is the source code for early-access 2615. ## Legal Notice diff --git a/externals/dynarmic/CMakeLists.txt b/externals/dynarmic/CMakeLists.txt index 71352c429..b5fd5f1ec 100755 --- a/externals/dynarmic/CMakeLists.txt +++ b/externals/dynarmic/CMakeLists.txt @@ -160,7 +160,7 @@ if (DYNARMIC_USE_LLVM) llvm_map_components_to_libnames(llvm_libs armdesc armdisassembler aarch64desc aarch64disassembler x86desc x86disassembler) endif() -if (DYNARMIC_TESTS_USE_UNICORN) +if (DYNARMIC_TESTS_USE_UNICORN AND DYNARMIC_TESTS) find_package(Unicorn REQUIRED) endif() diff --git a/externals/dynarmic/src/dynarmic/CMakeLists.txt b/externals/dynarmic/src/dynarmic/CMakeLists.txt index 9d1db6a58..c64233371 100755 --- a/externals/dynarmic/src/dynarmic/CMakeLists.txt +++ b/externals/dynarmic/src/dynarmic/CMakeLists.txt @@ -75,6 +75,7 @@ add_library(dynarmic frontend/imm.h interface/exclusive_monitor.h interface/optimization_flags.h + ir/acc_type.h ir/basic_block.cpp ir/basic_block.h ir/cond.h @@ -99,7 +100,7 @@ add_library(dynarmic ir/type.h ir/value.cpp ir/value.h - ir/access_type.h) +) if ("A32" IN_LIST DYNARMIC_FRONTENDS) target_sources(dynarmic PRIVATE @@ -390,7 +391,7 @@ target_link_libraries(dynarmic tsl::robin_map $ $ - $<$:${llvm_libs}> + "$<$:${llvm_libs}>" ) if (DYNARMIC_ENABLE_CPU_FEATURE_DETECTION) target_compile_definitions(dynarmic PRIVATE DYNARMIC_ENABLE_CPU_FEATURE_DETECTION=1) diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp index 82e9ae964..43d7c0c7f 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp @@ -158,120 +158,6 @@ FakeCall A32EmitX64::FastmemCallback(u64 rip_) { }; } -namespace { - -constexpr size_t page_bits = 12; -constexpr size_t page_size = 1 << page_bits; -constexpr size_t page_mask = (1 << page_bits) - 1; - -void EmitDetectMisaignedVAddr(BlockOfCode& code, A32EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg32 vaddr, Xbyak::Reg32 tmp) { - if (bitsize == 8 || (ctx.conf.detect_misaligned_access_via_page_table & bitsize) == 0) { - return; - } - - const u32 align_mask = [bitsize]() -> u32 { - switch (bitsize) { - case 16: - return 0b1; - case 32: - return 0b11; - case 64: - return 0b111; - } - UNREACHABLE(); - }(); - - code.test(vaddr, align_mask); - - if (!ctx.conf.only_detect_misalignment_via_page_table_on_page_boundary) { - code.jnz(abort, code.T_NEAR); - return; - } - - const u32 page_align_mask = static_cast(page_size - 1) & ~align_mask; - - Xbyak::Label detect_boundary, resume; - - code.jnz(detect_boundary, code.T_NEAR); - code.L(resume); - - code.SwitchToFarCode(); - code.L(detect_boundary); - code.mov(tmp, vaddr); - code.and_(tmp, page_align_mask); - code.cmp(tmp, page_align_mask); - code.jne(resume, code.T_NEAR); - // NOTE: We expect to fallthrough into abort code here. - code.SwitchToNearCode(); -} - -Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A32EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr) { - const Xbyak::Reg64 page = ctx.reg_alloc.ScratchGpr(); - const Xbyak::Reg32 tmp = ctx.conf.absolute_offset_page_table ? page.cvt32() : ctx.reg_alloc.ScratchGpr().cvt32(); - - EmitDetectMisaignedVAddr(code, ctx, bitsize, abort, vaddr.cvt32(), tmp); - - // TODO: This code assumes vaddr has been zext from 32-bits to 64-bits. - - code.mov(tmp, vaddr.cvt32()); - code.shr(tmp, static_cast(page_bits)); - code.mov(page, qword[r14 + tmp.cvt64() * sizeof(void*)]); - if (ctx.conf.page_table_pointer_mask_bits == 0) { - code.test(page, page); - } else { - code.and_(page, ~u32(0) << ctx.conf.page_table_pointer_mask_bits); - } - code.jz(abort, code.T_NEAR); - if (ctx.conf.absolute_offset_page_table) { - return page + vaddr; - } - code.mov(tmp, vaddr.cvt32()); - code.and_(tmp, static_cast(page_mask)); - return page + tmp.cvt64(); -} - -template -void EmitReadMemoryMov(BlockOfCode& code, const Xbyak::Reg64& value, const Xbyak::RegExp& addr) { - switch (bitsize) { - case 8: - code.movzx(value.cvt32(), code.byte[addr]); - return; - case 16: - code.movzx(value.cvt32(), word[addr]); - return; - case 32: - code.mov(value.cvt32(), dword[addr]); - return; - case 64: - code.mov(value, qword[addr]); - return; - default: - ASSERT_FALSE("Invalid bitsize"); - } -} - -template -void EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, const Xbyak::Reg64& value) { - switch (bitsize) { - case 8: - code.mov(code.byte[addr], value.cvt8()); - return; - case 16: - code.mov(word[addr], value.cvt16()); - return; - case 32: - code.mov(dword[addr], value.cvt32()); - return; - case 64: - code.mov(qword[addr], value); - return; - default: - ASSERT_FALSE("Invalid bitsize"); - } -} - -} // anonymous namespace - template void A32EmitX64::EmitMemoryRead(A32EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -295,7 +181,7 @@ void A32EmitX64::EmitMemoryRead(A32EmitContext& ctx, IR::Inst* inst) { const auto src_ptr = r13 + vaddr; const auto location = code.getCurr(); - EmitReadMemoryMov(code, value, src_ptr); + EmitReadMemoryMov(code, value.getIdx(), src_ptr); fastmem_patch_info.emplace( Common::BitCast(location), @@ -315,7 +201,7 @@ void A32EmitX64::EmitMemoryRead(A32EmitContext& ctx, IR::Inst* inst) { Xbyak::Label abort, end; const auto src_ptr = EmitVAddrLookup(code, ctx, bitsize, abort, vaddr); - EmitReadMemoryMov(code, value, src_ptr); + EmitReadMemoryMov(code, value.getIdx(), src_ptr); code.L(end); code.SwitchToFarCode(); @@ -349,7 +235,7 @@ void A32EmitX64::EmitMemoryWrite(A32EmitContext& ctx, IR::Inst* inst) { const auto dest_ptr = r13 + vaddr; const auto location = code.getCurr(); - EmitWriteMemoryMov(code, dest_ptr, value); + EmitWriteMemoryMov(code, dest_ptr, value.getIdx()); fastmem_patch_info.emplace( Common::BitCast(location), @@ -368,7 +254,7 @@ void A32EmitX64::EmitMemoryWrite(A32EmitContext& ctx, IR::Inst* inst) { Xbyak::Label abort, end; const auto dest_ptr = EmitVAddrLookup(code, ctx, bitsize, abort, vaddr); - EmitWriteMemoryMov(code, dest_ptr, value); + EmitWriteMemoryMov(code, dest_ptr, value.getIdx()); code.L(end); code.SwitchToFarCode(); @@ -488,7 +374,7 @@ void A32EmitX64::ExclusiveReadMemoryInline(A32EmitContext& ctx, IR::Inst* inst) const auto src_ptr = r13 + vaddr; const auto location = code.getCurr(); - EmitReadMemoryMov(code, value, src_ptr); + EmitReadMemoryMov(code, value.getIdx(), src_ptr); fastmem_patch_info.emplace( Common::BitCast(location), @@ -505,7 +391,7 @@ void A32EmitX64::ExclusiveReadMemoryInline(A32EmitContext& ctx, IR::Inst* inst) } code.mov(tmp, Common::BitCast(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id))); - EmitWriteMemoryMov(code, tmp, value); + EmitWriteMemoryMov(code, tmp, value.getIdx()); EmitExclusiveUnlock(code, conf, tmp, tmp2.cvt32()); @@ -546,7 +432,7 @@ void A32EmitX64::ExclusiveWriteMemoryInline(A32EmitContext& ctx, IR::Inst* inst) code.mov(code.byte[r15 + offsetof(A32JitState, exclusive_state)], u8(0)); code.mov(tmp, Common::BitCast(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id))); - EmitReadMemoryMov(code, rax, tmp); + EmitReadMemoryMov(code, rax.getIdx(), tmp); const auto fastmem_marker = ShouldFastmem(ctx, inst); if (fastmem_marker) { diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp index f403bba8a..7755c9ff3 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp @@ -22,7 +22,6 @@ #include "dynarmic/common/spin_lock_x64.h" #include "dynarmic/common/x64_disassemble.h" #include "dynarmic/interface/exclusive_monitor.h" -#include "dynarmic/ir/access_type.h" namespace Dynarmic::Backend::X64 { @@ -301,272 +300,19 @@ FakeCall A64EmitX64::FastmemCallback(u64 rip_) { }; } -namespace { - -constexpr size_t page_bits = 12; -constexpr size_t page_size = 1 << page_bits; -constexpr size_t page_mask = (1 << page_bits) - 1; - -void EmitDetectMisaignedVAddr(BlockOfCode& code, A64EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr, Xbyak::Reg64 tmp) { - if (bitsize == 8 || (ctx.conf.detect_misaligned_access_via_page_table & bitsize) == 0) { - return; - } - - const u32 align_mask = [bitsize]() -> u32 { - switch (bitsize) { - case 16: - return 0b1; - case 32: - return 0b11; - case 64: - return 0b111; - case 128: - return 0b1111; - } - UNREACHABLE(); - }(); - - code.test(vaddr, align_mask); - - if (!ctx.conf.only_detect_misalignment_via_page_table_on_page_boundary) { - code.jnz(abort, code.T_NEAR); - return; - } - - const u32 page_align_mask = static_cast(page_size - 1) & ~align_mask; - - Xbyak::Label detect_boundary, resume; - - code.jnz(detect_boundary, code.T_NEAR); - code.L(resume); - - code.SwitchToFarCode(); - code.L(detect_boundary); - code.mov(tmp, vaddr); - code.and_(tmp, page_align_mask); - code.cmp(tmp, page_align_mask); - code.jne(resume, code.T_NEAR); - // NOTE: We expect to fallthrough into abort code here. - code.SwitchToNearCode(); -} - -Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr) { - const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_bits; - const size_t unused_top_bits = 64 - ctx.conf.page_table_address_space_bits; - - const Xbyak::Reg64 page = ctx.reg_alloc.ScratchGpr(); - const Xbyak::Reg64 tmp = ctx.conf.absolute_offset_page_table ? page : ctx.reg_alloc.ScratchGpr(); - - EmitDetectMisaignedVAddr(code, ctx, bitsize, abort, vaddr, tmp); - - if (unused_top_bits == 0) { - code.mov(tmp, vaddr); - code.shr(tmp, int(page_bits)); - } 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.mov(bit_count, unused_top_bits); - code.bzhi(tmp, vaddr, bit_count); - code.shr(tmp, int(page_bits)); - ctx.reg_alloc.Release(bit_count); - } else { - code.mov(tmp, vaddr); - code.shl(tmp, int(unused_top_bits)); - code.shr(tmp, int(unused_top_bits + page_bits)); - } - } else { - code.mov(tmp, vaddr); - code.shr(tmp, int(page_bits)); - code.and_(tmp, u32((1 << valid_page_index_bits) - 1)); - } - } else { - ASSERT(valid_page_index_bits < 32); - code.mov(tmp, vaddr); - code.shr(tmp, int(page_bits)); - code.test(tmp, u32(-(1 << valid_page_index_bits))); - code.jnz(abort, code.T_NEAR); - } - code.mov(page, qword[r14 + tmp * sizeof(void*)]); - if (ctx.conf.page_table_pointer_mask_bits == 0) { - code.test(page, page); - } else { - code.and_(page, ~u32(0) << ctx.conf.page_table_pointer_mask_bits); - } - code.jz(abort, code.T_NEAR); - if (ctx.conf.absolute_offset_page_table) { - return page + vaddr; - } - code.mov(tmp, vaddr); - code.and_(tmp, static_cast(page_mask)); - return page + tmp; -} - -Xbyak::RegExp EmitFastmemVAddr(BlockOfCode& code, A64EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, bool& require_abort_handling, std::optional tmp = std::nullopt) { - const size_t unused_top_bits = 64 - ctx.conf.fastmem_address_space_bits; - - if (unused_top_bits == 0) { - return r13 + vaddr; - } else if (ctx.conf.silently_mirror_fastmem) { - if (!tmp) { - tmp = ctx.reg_alloc.ScratchGpr(); - } - if (unused_top_bits < 32) { - code.mov(*tmp, vaddr); - code.shl(*tmp, int(unused_top_bits)); - code.shr(*tmp, int(unused_top_bits)); - } else if (unused_top_bits == 32) { - code.mov(tmp->cvt32(), vaddr.cvt32()); - } else { - code.mov(tmp->cvt32(), vaddr.cvt32()); - code.and_(*tmp, u32((1 << ctx.conf.fastmem_address_space_bits) - 1)); - } - return r13 + *tmp; - } else { - if (ctx.conf.fastmem_address_space_bits < 32) { - code.test(vaddr, u32(-(1 << ctx.conf.fastmem_address_space_bits))); - code.jnz(abort, code.T_NEAR); - require_abort_handling = true; - } else { - // TODO: Consider having TEST as above but coalesce 64-bit constant in register allocator - if (!tmp) { - tmp = ctx.reg_alloc.ScratchGpr(); - } - code.mov(*tmp, vaddr); - code.shr(*tmp, int(ctx.conf.fastmem_address_space_bits)); - code.jnz(abort, code.T_NEAR); - require_abort_handling = true; - } - return r13 + vaddr; - } -} - -template -const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::RegExp& addr, bool ordered) { - if (ordered) { - if constexpr (bitsize == 128) { - code.mfence(); - } else { - code.xor_(Xbyak::Reg32{value_idx}, Xbyak::Reg32{value_idx}); - } - - const void* fastmem_location = code.getCurr(); - - switch (bitsize) { - case 8: - code.lock(); - code.xadd(code.byte[addr], Xbyak::Reg32{value_idx}.cvt8()); - return fastmem_location; - case 16: - code.lock(); - code.xadd(word[addr], Xbyak::Reg32{value_idx}); - return fastmem_location; - case 32: - code.lock(); - code.xadd(dword[addr], Xbyak::Reg32{value_idx}); - return fastmem_location; - case 64: - code.lock(); - code.xadd(qword[addr], Xbyak::Reg64{value_idx}); - return fastmem_location; - case 128: - code.movaps(Xbyak::Xmm{value_idx}, xword[addr]); - return fastmem_location; - default: - ASSERT_FALSE("Invalid bitsize"); - } - } - - const void* fastmem_location = code.getCurr(); - - switch (bitsize) { - case 8: - code.movzx(Xbyak::Reg32{value_idx}, code.byte[addr]); - return fastmem_location; - case 16: - code.movzx(Xbyak::Reg32{value_idx}, word[addr]); - return fastmem_location; - case 32: - code.mov(Xbyak::Reg32{value_idx}, dword[addr]); - return fastmem_location; - case 64: - code.mov(Xbyak::Reg64{value_idx}, qword[addr]); - return fastmem_location; - case 128: - code.movups(Xbyak::Xmm{value_idx}, xword[addr]); - return fastmem_location; - default: - ASSERT_FALSE("Invalid bitsize"); - } -} - -template -void EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int value_idx, bool ordered) { - switch (bitsize) { - case 8: - if (ordered) { - code.xchg(code.byte[addr], Xbyak::Reg64{value_idx}.cvt8()); - } else { - code.mov(code.byte[addr], Xbyak::Reg64{value_idx}.cvt8()); - } - return; - case 16: - if (ordered) { - code.xchg(word[addr], Xbyak::Reg16{value_idx}); - } else { - code.mov(word[addr], Xbyak::Reg16{value_idx}); - } - return; - case 32: - if (ordered) { - code.xchg(dword[addr], Xbyak::Reg32{value_idx}); - } else { - code.mov(dword[addr], Xbyak::Reg32{value_idx}); - } - return; - case 64: - if (ordered) { - code.xchg(qword[addr], Xbyak::Reg64{value_idx}); - } else { - code.mov(qword[addr], Xbyak::Reg64{value_idx}); - } - return; - case 128: - if (ordered) { - code.movaps(xword[addr], Xbyak::Xmm{value_idx}); - code.mfence(); - } else { - code.movups(xword[addr], Xbyak::Xmm{value_idx}); - } - return; - default: - ASSERT_FALSE("Invalid bitsize"); - } -} - -} // namespace - template void A64EmitX64::EmitMemoryRead(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const IR::AccessType acctype = args[2].GetImmediateAccType(); - const bool ordered = acctype == IR::AccessType::ORDERED || acctype == IR::AccessType::ORDEREDRW || acctype == IR::AccessType::LIMITEDORDERED; const auto fastmem_marker = ShouldFastmem(ctx, inst); if (!conf.page_table && !fastmem_marker) { // Neither fastmem nor page table: Use callbacks if constexpr (bitsize == 128) { ctx.reg_alloc.HostCall(nullptr, {}, args[0]); - if (ordered) { - code.mfence(); - } code.CallFunction(memory_read_128); ctx.reg_alloc.DefineValue(inst, xmm1); } else { ctx.reg_alloc.HostCall(inst, {}, args[0]); - if (ordered) { - code.mfence(); - } Devirtualize(conf.callbacks).EmitCall(code); code.ZeroExtendFrom(bitsize, code.ABI_RETURN); } @@ -585,7 +331,8 @@ void A64EmitX64::EmitMemoryRead(A64EmitContext& ctx, IR::Inst* inst) { // Use fastmem const auto src_ptr = EmitFastmemVAddr(code, ctx, abort, vaddr, require_abort_handling); - const auto location = EmitReadMemoryMov(code, value_idx, src_ptr, ordered); + const auto location = code.getCurr(); + EmitReadMemoryMov(code, value_idx, src_ptr); fastmem_patch_info.emplace( Common::BitCast(location), @@ -600,16 +347,13 @@ void A64EmitX64::EmitMemoryRead(A64EmitContext& ctx, IR::Inst* inst) { ASSERT(conf.page_table); const auto src_ptr = EmitVAddrLookup(code, ctx, bitsize, abort, vaddr); require_abort_handling = true; - EmitReadMemoryMov(code, value_idx, src_ptr, ordered); + EmitReadMemoryMov(code, value_idx, src_ptr); } code.L(end); if (require_abort_handling) { code.SwitchToFarCode(); code.L(abort); - if (ordered) { - code.mfence(); - } code.call(wrapped_fn); code.jmp(end, code.T_NEAR); code.SwitchToNearCode(); @@ -625,8 +369,6 @@ void A64EmitX64::EmitMemoryRead(A64EmitContext& ctx, IR::Inst* inst) { template void A64EmitX64::EmitMemoryWrite(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const IR::AccessType acctype = args[2].GetImmediateAccType(); - const bool ordered = acctype == IR::AccessType::ORDERED || acctype == IR::AccessType::ORDEREDRW || acctype == IR::AccessType::LIMITEDORDERED; const auto fastmem_marker = ShouldFastmem(ctx, inst); if (!conf.page_table && !fastmem_marker) { @@ -641,16 +383,11 @@ void A64EmitX64::EmitMemoryWrite(A64EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(nullptr, {}, args[0], args[1]); Devirtualize(conf.callbacks).EmitCall(code); } - if (ordered) { - code.mfence(); - } return; } const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]); - const int value_idx = bitsize == 128 - ? ctx.reg_alloc.UseXmm(args[1]).getIdx() - : (ordered ? ctx.reg_alloc.UseScratchGpr(args[1]).getIdx() : ctx.reg_alloc.UseGpr(args[1]).getIdx()); + const int value_idx = bitsize == 128 ? ctx.reg_alloc.UseXmm(args[1]).getIdx() : ctx.reg_alloc.UseGpr(args[1]).getIdx(); const auto wrapped_fn = write_fallbacks[std::make_tuple(bitsize, vaddr.getIdx(), value_idx)]; @@ -662,7 +399,7 @@ void A64EmitX64::EmitMemoryWrite(A64EmitContext& ctx, IR::Inst* inst) { const auto dest_ptr = EmitFastmemVAddr(code, ctx, abort, vaddr, require_abort_handling); const auto location = code.getCurr(); - EmitWriteMemoryMov(code, dest_ptr, value_idx, ordered); + EmitWriteMemoryMov(code, dest_ptr, value_idx); fastmem_patch_info.emplace( Common::BitCast(location), @@ -677,7 +414,7 @@ void A64EmitX64::EmitMemoryWrite(A64EmitContext& ctx, IR::Inst* inst) { ASSERT(conf.page_table); const auto dest_ptr = EmitVAddrLookup(code, ctx, bitsize, abort, vaddr); require_abort_handling = true; - EmitWriteMemoryMov(code, dest_ptr, value_idx, ordered); + EmitWriteMemoryMov(code, dest_ptr, value_idx); } code.L(end); @@ -685,9 +422,6 @@ void A64EmitX64::EmitMemoryWrite(A64EmitContext& ctx, IR::Inst* inst) { code.SwitchToFarCode(); code.L(abort); code.call(wrapped_fn); - if (ordered) { - code.mfence(); - } code.jmp(end, code.T_NEAR); code.SwitchToNearCode(); } @@ -737,8 +471,6 @@ template void A64EmitX64::EmitExclusiveReadMemory(A64EmitContext& ctx, IR::Inst* inst) { ASSERT(conf.global_monitor != nullptr); auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const IR::AccessType acctype = args[2].GetImmediateAccType(); - const bool ordered = acctype == IR::AccessType::ORDERED || acctype == IR::AccessType::ORDEREDRW || acctype == IR::AccessType::LIMITEDORDERED; if constexpr (bitsize != 128) { using T = mp::unsigned_integer_of_size; @@ -747,9 +479,6 @@ void A64EmitX64::EmitExclusiveReadMemory(A64EmitContext& ctx, IR::Inst* inst) { code.mov(code.byte[r15 + offsetof(A64JitState, exclusive_state)], u8(1)); code.mov(code.ABI_PARAM1, reinterpret_cast(&conf)); - if (ordered) { - code.mfence(); - } code.CallLambda( [](A64::UserConfig& conf, u64 vaddr) -> T { return conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> T { @@ -767,9 +496,6 @@ void A64EmitX64::EmitExclusiveReadMemory(A64EmitContext& ctx, IR::Inst* inst) { code.mov(code.ABI_PARAM1, reinterpret_cast(&conf)); ctx.reg_alloc.AllocStackSpace(16 + ABI_SHADOW_SPACE); code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]); - if (ordered) { - code.mfence(); - } code.CallLambda( [](A64::UserConfig& conf, u64 vaddr, A64::Vector& ret) { ret = conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> A64::Vector { @@ -787,8 +513,6 @@ template void A64EmitX64::EmitExclusiveWriteMemory(A64EmitContext& ctx, IR::Inst* inst) { ASSERT(conf.global_monitor != nullptr); auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const IR::AccessType acctype = args[3].GetImmediateAccType(); - const bool ordered = acctype == IR::AccessType::ORDERED || acctype == IR::AccessType::ORDEREDRW || acctype == IR::AccessType::LIMITEDORDERED; if constexpr (bitsize != 128) { ctx.reg_alloc.HostCall(inst, {}, args[0], args[1]); @@ -818,9 +542,6 @@ void A64EmitX64::EmitExclusiveWriteMemory(A64EmitContext& ctx, IR::Inst* inst) { ? 0 : 1; }); - if (ordered) { - code.mfence(); - } } else { ctx.reg_alloc.AllocStackSpace(16 + ABI_SHADOW_SPACE); code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]); @@ -834,9 +555,6 @@ void A64EmitX64::EmitExclusiveWriteMemory(A64EmitContext& ctx, IR::Inst* inst) { ? 0 : 1; }); - if (ordered) { - code.mfence(); - } ctx.reg_alloc.ReleaseStackSpace(16 + ABI_SHADOW_SPACE); } code.L(end); @@ -851,8 +569,6 @@ void A64EmitX64::EmitExclusiveReadMemoryInline(A64EmitContext& ctx, IR::Inst* in } auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const IR::AccessType acctype = args[2].GetImmediateAccType(); - const bool ordered = acctype == IR::AccessType::ORDERED || acctype == IR::AccessType::ORDEREDRW || acctype == IR::AccessType::LIMITEDORDERED; const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]); const int value_idx = bitsize == 128 ? ctx.reg_alloc.ScratchXmm().getIdx() : ctx.reg_alloc.ScratchGpr().getIdx(); @@ -875,7 +591,7 @@ void A64EmitX64::EmitExclusiveReadMemoryInline(A64EmitContext& ctx, IR::Inst* in const auto src_ptr = EmitFastmemVAddr(code, ctx, abort, vaddr, require_abort_handling); const auto location = code.getCurr(); - EmitReadMemoryMov(code, value_idx, src_ptr, ordered); + EmitReadMemoryMov(code, value_idx, src_ptr); fastmem_patch_info.emplace( Common::BitCast(location), @@ -900,7 +616,7 @@ void A64EmitX64::EmitExclusiveReadMemoryInline(A64EmitContext& ctx, IR::Inst* in } code.mov(tmp, Common::BitCast(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id))); - EmitWriteMemoryMov(code, tmp, value_idx, false); + EmitWriteMemoryMov(code, tmp, value_idx); EmitExclusiveUnlock(code, conf, tmp, tmp2.cvt32()); @@ -920,8 +636,6 @@ void A64EmitX64::EmitExclusiveWriteMemoryInline(A64EmitContext& ctx, IR::Inst* i } auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const IR::AccessType acctype = args[3].GetImmediateAccType(); - const bool ordered = acctype == IR::AccessType::ORDERED || acctype == IR::AccessType::ORDEREDRW || acctype == IR::AccessType::LIMITEDORDERED; const auto value = [&] { if constexpr (bitsize == 128) { @@ -970,7 +684,7 @@ void A64EmitX64::EmitExclusiveWriteMemoryInline(A64EmitContext& ctx, IR::Inst* i code.movq(rcx, xmm0); } } else { - EmitReadMemoryMov(code, rax.getIdx(), tmp, false); + EmitReadMemoryMov(code, rax.getIdx(), tmp); } const auto fastmem_marker = ShouldFastmem(ctx, inst); @@ -1008,10 +722,6 @@ void A64EmitX64::EmitExclusiveWriteMemoryInline(A64EmitContext& ctx, IR::Inst* i } } - if (ordered) { - code.mfence(); - } - code.setnz(status.cvt8()); code.SwitchToFarCode(); @@ -1027,10 +737,6 @@ void A64EmitX64::EmitExclusiveWriteMemoryInline(A64EmitContext& ctx, IR::Inst* i conf.recompile_on_exclusive_fastmem_failure, }); - if (ordered) { - code.mfence(); - } - code.cmp(al, 0); code.setz(status.cvt8()); code.movzx(status.cvt32(), status.cvt8()); @@ -1038,9 +744,6 @@ void A64EmitX64::EmitExclusiveWriteMemoryInline(A64EmitContext& ctx, IR::Inst* i code.SwitchToNearCode(); } else { code.call(fallback_fn); - if (ordered) { - code.mfence(); - } code.cmp(al, 0); code.setz(status.cvt8()); code.movzx(status.cvt32(), status.cvt8()); diff --git a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h index e5cf6a483..23b567ef6 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h +++ b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h @@ -5,6 +5,7 @@ #include +#include "dynarmic/backend/x64/a32_emit_x64.h" #include "dynarmic/backend/x64/a64_emit_x64.h" #include "dynarmic/backend/x64/exclusive_monitor_friend.h" #include "dynarmic/common/spin_lock_x64.h" @@ -16,6 +17,232 @@ namespace { using namespace Xbyak::util; +constexpr size_t page_bits = 12; +constexpr size_t page_size = 1 << page_bits; +constexpr size_t page_mask = (1 << page_bits) - 1; + +template +void EmitDetectMisalignedVAddr(BlockOfCode& code, EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr, Xbyak::Reg64 tmp) { + if (bitsize == 8 || (ctx.conf.detect_misaligned_access_via_page_table & bitsize) == 0) { + return; + } + + const u32 align_mask = [bitsize]() -> u32 { + switch (bitsize) { + case 16: + return 0b1; + case 32: + return 0b11; + case 64: + return 0b111; + case 128: + return 0b1111; + default: + UNREACHABLE(); + } + }(); + + code.test(vaddr, align_mask); + + if (!ctx.conf.only_detect_misalignment_via_page_table_on_page_boundary) { + code.jnz(abort, code.T_NEAR); + return; + } + + const u32 page_align_mask = static_cast(page_size - 1) & ~align_mask; + + Xbyak::Label detect_boundary, resume; + + code.jnz(detect_boundary, code.T_NEAR); + code.L(resume); + + code.SwitchToFarCode(); + code.L(detect_boundary); + code.mov(tmp, vaddr); + code.and_(tmp, page_align_mask); + code.cmp(tmp, page_align_mask); + code.jne(resume, code.T_NEAR); + // NOTE: We expect to fallthrough into abort code here. + code.SwitchToNearCode(); +} + +template +Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr); + +template<> +[[maybe_unused]] Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A32EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr) { + const Xbyak::Reg64 page = ctx.reg_alloc.ScratchGpr(); + const Xbyak::Reg32 tmp = ctx.conf.absolute_offset_page_table ? page.cvt32() : ctx.reg_alloc.ScratchGpr().cvt32(); + + EmitDetectMisalignedVAddr(code, ctx, bitsize, abort, vaddr, tmp.cvt64()); + + // TODO: This code assumes vaddr has been zext from 32-bits to 64-bits. + + code.mov(tmp, vaddr.cvt32()); + code.shr(tmp, static_cast(page_bits)); + + code.mov(page, qword[r14 + tmp.cvt64() * sizeof(void*)]); + if (ctx.conf.page_table_pointer_mask_bits == 0) { + code.test(page, page); + } else { + code.and_(page, ~u32(0) << ctx.conf.page_table_pointer_mask_bits); + } + code.jz(abort, code.T_NEAR); + if (ctx.conf.absolute_offset_page_table) { + return page + vaddr; + } + code.mov(tmp, vaddr.cvt32()); + code.and_(tmp, static_cast(page_mask)); + return page + tmp.cvt64(); +} + +template<> +[[maybe_unused]] Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr) { + const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_bits; + const size_t unused_top_bits = 64 - ctx.conf.page_table_address_space_bits; + + const Xbyak::Reg64 page = ctx.reg_alloc.ScratchGpr(); + const Xbyak::Reg64 tmp = ctx.conf.absolute_offset_page_table ? page : ctx.reg_alloc.ScratchGpr(); + + EmitDetectMisalignedVAddr(code, ctx, bitsize, abort, vaddr, tmp); + + if (unused_top_bits == 0) { + code.mov(tmp, vaddr); + code.shr(tmp, int(page_bits)); + } 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.mov(bit_count, unused_top_bits); + code.bzhi(tmp, vaddr, bit_count); + code.shr(tmp, int(page_bits)); + ctx.reg_alloc.Release(bit_count); + } else { + code.mov(tmp, vaddr); + code.shl(tmp, int(unused_top_bits)); + code.shr(tmp, int(unused_top_bits + page_bits)); + } + } else { + code.mov(tmp, vaddr); + code.shr(tmp, int(page_bits)); + code.and_(tmp, u32((1 << valid_page_index_bits) - 1)); + } + } else { + ASSERT(valid_page_index_bits < 32); + code.mov(tmp, vaddr); + code.shr(tmp, int(page_bits)); + code.test(tmp, u32(-(1 << valid_page_index_bits))); + code.jnz(abort, code.T_NEAR); + } + code.mov(page, qword[r14 + tmp * sizeof(void*)]); + if (ctx.conf.page_table_pointer_mask_bits == 0) { + code.test(page, page); + } else { + code.and_(page, ~u32(0) << ctx.conf.page_table_pointer_mask_bits); + } + code.jz(abort, code.T_NEAR); + if (ctx.conf.absolute_offset_page_table) { + return page + vaddr; + } + code.mov(tmp, vaddr); + code.and_(tmp, static_cast(page_mask)); + return page + tmp; +} + +template +Xbyak::RegExp EmitFastmemVAddr(BlockOfCode& code, EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, bool& require_abort_handling, std::optional tmp = std::nullopt); + +template<> +[[maybe_unused]] Xbyak::RegExp EmitFastmemVAddr(BlockOfCode&, A32EmitContext&, Xbyak::Label&, Xbyak::Reg64 vaddr, bool&, std::optional) { + return r13 + vaddr; +} + +template<> +[[maybe_unused]] Xbyak::RegExp EmitFastmemVAddr(BlockOfCode& code, A64EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, bool& require_abort_handling, std::optional tmp) { + const size_t unused_top_bits = 64 - ctx.conf.fastmem_address_space_bits; + + if (unused_top_bits == 0) { + return r13 + vaddr; + } else if (ctx.conf.silently_mirror_fastmem) { + if (!tmp) { + tmp = ctx.reg_alloc.ScratchGpr(); + } + if (unused_top_bits < 32) { + code.mov(*tmp, vaddr); + code.shl(*tmp, int(unused_top_bits)); + code.shr(*tmp, int(unused_top_bits)); + } else if (unused_top_bits == 32) { + code.mov(tmp->cvt32(), vaddr.cvt32()); + } else { + code.mov(tmp->cvt32(), vaddr.cvt32()); + code.and_(*tmp, u32((1 << ctx.conf.fastmem_address_space_bits) - 1)); + } + return r13 + *tmp; + } else { + if (ctx.conf.fastmem_address_space_bits < 32) { + code.test(vaddr, u32(-(1 << ctx.conf.fastmem_address_space_bits))); + code.jnz(abort, code.T_NEAR); + require_abort_handling = true; + } else { + // TODO: Consider having TEST as above but coalesce 64-bit constant in register allocator + if (!tmp) { + tmp = ctx.reg_alloc.ScratchGpr(); + } + code.mov(*tmp, vaddr); + code.shr(*tmp, int(ctx.conf.fastmem_address_space_bits)); + code.jnz(abort, code.T_NEAR); + require_abort_handling = true; + } + return r13 + vaddr; + } +} + +template +void EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::RegExp& addr) { + switch (bitsize) { + case 8: + code.movzx(Xbyak::Reg32{value_idx}, code.byte[addr]); + return; + case 16: + code.movzx(Xbyak::Reg32{value_idx}, word[addr]); + return; + case 32: + code.mov(Xbyak::Reg32{value_idx}, dword[addr]); + return; + case 64: + code.mov(Xbyak::Reg64{value_idx}, qword[addr]); + return; + case 128: + code.movups(Xbyak::Xmm{value_idx}, xword[addr]); + return; + default: + ASSERT_FALSE("Invalid bitsize"); + } +} + +template +void EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int value_idx) { + switch (bitsize) { + case 8: + code.mov(code.byte[addr], Xbyak::Reg64{value_idx}.cvt8()); + return; + case 16: + code.mov(word[addr], Xbyak::Reg16{value_idx}); + return; + case 32: + code.mov(dword[addr], Xbyak::Reg32{value_idx}); + return; + case 64: + code.mov(qword[addr], Xbyak::Reg64{value_idx}); + return; + case 128: + code.movups(xword[addr], Xbyak::Xmm{value_idx}); + return; + default: + ASSERT_FALSE("Invalid bitsize"); + } +} + template void EmitExclusiveLock(BlockOfCode& code, const UserConfig& conf, Xbyak::Reg64 pointer, Xbyak::Reg32 tmp) { if (conf.HasOptimization(OptimizationFlag::Unsafe_IgnoreGlobalMonitor)) { diff --git a/externals/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp b/externals/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp index be45e9de1..ae53a620a 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp @@ -42,6 +42,7 @@ static size_t GetBitWidth(IR::Type type) { case IR::Type::Cond: case IR::Type::Void: case IR::Type::Table: + case IR::Type::AccType: ASSERT_FALSE("Type {} cannot be represented at runtime", type); case IR::Type::Opaque: ASSERT_FALSE("Not a concrete type"); @@ -207,11 +208,6 @@ IR::Cond Argument::GetImmediateCond() const { return value.GetCond(); } -IR::AccessType Argument::GetImmediateAccType() const { - ASSERT(IsImmediate() && GetType() == IR::Type::AccessType); - return value.GetAccType(); -} - bool Argument::IsInGpr() const { if (IsImmediate()) return false; diff --git a/externals/dynarmic/src/dynarmic/backend/x64/reg_alloc.h b/externals/dynarmic/src/dynarmic/backend/x64/reg_alloc.h index f8c88b596..58bfe87f3 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/reg_alloc.h +++ b/externals/dynarmic/src/dynarmic/backend/x64/reg_alloc.h @@ -75,7 +75,6 @@ public: u64 GetImmediateS32() const; u64 GetImmediateU64() const; IR::Cond GetImmediateCond() const; - IR::AccessType GetImmediateAccType() const; /// Is this value currently in a GPR? bool IsInGpr() const; diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp index 8363f81f6..8d2b9db72 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp @@ -229,55 +229,55 @@ void IREmitter::ClearExclusive() { Inst(Opcode::A32ClearExclusive); } -IR::UAny IREmitter::ReadMemory(size_t bitsize, const IR::U32& vaddr) { +IR::UAny IREmitter::ReadMemory(size_t bitsize, const IR::U32& vaddr, IR::AccType acc_type) { switch (bitsize) { case 8: - return ReadMemory8(vaddr); + return ReadMemory8(vaddr, acc_type); case 16: - return ReadMemory16(vaddr); + return ReadMemory16(vaddr, acc_type); case 32: - return ReadMemory32(vaddr); + return ReadMemory32(vaddr, acc_type); case 64: - return ReadMemory64(vaddr); + return ReadMemory64(vaddr, acc_type); } ASSERT_FALSE("Invalid bitsize"); } -IR::U8 IREmitter::ReadMemory8(const IR::U32& vaddr) { - return Inst(Opcode::A32ReadMemory8, vaddr); +IR::U8 IREmitter::ReadMemory8(const IR::U32& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A32ReadMemory8, vaddr, IR::Value{acc_type}); } -IR::U16 IREmitter::ReadMemory16(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ReadMemory16, vaddr); +IR::U16 IREmitter::ReadMemory16(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ReadMemory16, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseHalf(value) : value; } -IR::U32 IREmitter::ReadMemory32(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ReadMemory32, vaddr); +IR::U32 IREmitter::ReadMemory32(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ReadMemory32, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseWord(value) : value; } -IR::U64 IREmitter::ReadMemory64(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ReadMemory64, vaddr); +IR::U64 IREmitter::ReadMemory64(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ReadMemory64, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseDual(value) : value; } -IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U32& vaddr) { - return Inst(Opcode::A32ExclusiveReadMemory8, vaddr); +IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U32& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A32ExclusiveReadMemory8, vaddr, IR::Value{acc_type}); } -IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ExclusiveReadMemory16, vaddr); +IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ExclusiveReadMemory16, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseHalf(value) : value; } -IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ExclusiveReadMemory32, vaddr); +IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ExclusiveReadMemory32, vaddr, IR::Value{acc_type}); return current_location.EFlag() ? ByteReverseWord(value) : value; } -std::pair IREmitter::ExclusiveReadMemory64(const IR::U32& vaddr) { - const auto value = Inst(Opcode::A32ExclusiveReadMemory64, vaddr); +std::pair IREmitter::ExclusiveReadMemory64(const IR::U32& vaddr, IR::AccType acc_type) { + const auto value = Inst(Opcode::A32ExclusiveReadMemory64, vaddr, IR::Value{acc_type}); const auto lo = LeastSignificantWord(value); const auto hi = MostSignificantWord(value).result; if (current_location.EFlag()) { @@ -287,80 +287,80 @@ std::pair IREmitter::ExclusiveReadMemory64(const IR::U32& vadd return std::make_pair(lo, hi); } -void IREmitter::WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value) { +void IREmitter::WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value, IR::AccType acc_type) { switch (bitsize) { case 8: - return WriteMemory8(vaddr, value); + return WriteMemory8(vaddr, value, acc_type); case 16: - return WriteMemory16(vaddr, value); + return WriteMemory16(vaddr, value, acc_type); case 32: - return WriteMemory32(vaddr, value); + return WriteMemory32(vaddr, value, acc_type); case 64: - return WriteMemory64(vaddr, value); + return WriteMemory64(vaddr, value, acc_type); } ASSERT_FALSE("Invalid bitsize"); } -void IREmitter::WriteMemory8(const IR::U32& vaddr, const IR::U8& value) { - Inst(Opcode::A32WriteMemory8, vaddr, value); +void IREmitter::WriteMemory8(const IR::U32& vaddr, const IR::U8& value, IR::AccType acc_type) { + Inst(Opcode::A32WriteMemory8, vaddr, value, IR::Value{acc_type}); } -void IREmitter::WriteMemory16(const IR::U32& vaddr, const IR::U16& value) { +void IREmitter::WriteMemory16(const IR::U32& vaddr, const IR::U16& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseHalf(value); - Inst(Opcode::A32WriteMemory16, vaddr, v); + Inst(Opcode::A32WriteMemory16, vaddr, v, IR::Value{acc_type}); } else { - Inst(Opcode::A32WriteMemory16, vaddr, value); + Inst(Opcode::A32WriteMemory16, vaddr, value, IR::Value{acc_type}); } } -void IREmitter::WriteMemory32(const IR::U32& vaddr, const IR::U32& value) { +void IREmitter::WriteMemory32(const IR::U32& vaddr, const IR::U32& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseWord(value); - Inst(Opcode::A32WriteMemory32, vaddr, v); + Inst(Opcode::A32WriteMemory32, vaddr, v, IR::Value{acc_type}); } else { - Inst(Opcode::A32WriteMemory32, vaddr, value); + Inst(Opcode::A32WriteMemory32, vaddr, value, IR::Value{acc_type}); } } -void IREmitter::WriteMemory64(const IR::U32& vaddr, const IR::U64& value) { +void IREmitter::WriteMemory64(const IR::U32& vaddr, const IR::U64& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseDual(value); - Inst(Opcode::A32WriteMemory64, vaddr, v); + Inst(Opcode::A32WriteMemory64, vaddr, v, IR::Value{acc_type}); } else { - Inst(Opcode::A32WriteMemory64, vaddr, value); + Inst(Opcode::A32WriteMemory64, vaddr, value, IR::Value{acc_type}); } } -IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value) { - return Inst(Opcode::A32ExclusiveWriteMemory8, vaddr, value); +IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value, IR::AccType acc_type) { + return Inst(Opcode::A32ExclusiveWriteMemory8, vaddr, value, IR::Value{acc_type}); } -IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value) { +IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseHalf(value); - return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, v); + return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, v, IR::Value{acc_type}); } else { - return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, value); + return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, value, IR::Value{acc_type}); } } -IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value) { +IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value, IR::AccType acc_type) { if (current_location.EFlag()) { const auto v = ByteReverseWord(value); - return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, v); + return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, v, IR::Value{acc_type}); } else { - return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, value); + return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, value, IR::Value{acc_type}); } } -IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi) { +IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi, IR::AccType acc_type) { if (current_location.EFlag()) { const auto vlo = ByteReverseWord(value_lo); const auto vhi = ByteReverseWord(value_hi); - return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(vlo, vhi)); + return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(vlo, vhi), IR::Value{acc_type}); } else { - return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(value_lo, value_hi)); + return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(value_lo, value_hi), IR::Value{acc_type}); } } diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h index 7b6b1b03a..0f36958a3 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h +++ b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h @@ -80,24 +80,24 @@ public: void SetFpscrNZCV(const IR::NZCV& new_fpscr_nzcv); void ClearExclusive(); - IR::UAny ReadMemory(size_t bitsize, const IR::U32& vaddr); - IR::U8 ReadMemory8(const IR::U32& vaddr); - IR::U16 ReadMemory16(const IR::U32& vaddr); - IR::U32 ReadMemory32(const IR::U32& vaddr); - IR::U64 ReadMemory64(const IR::U32& vaddr); - IR::U8 ExclusiveReadMemory8(const IR::U32& vaddr); - IR::U16 ExclusiveReadMemory16(const IR::U32& vaddr); - IR::U32 ExclusiveReadMemory32(const IR::U32& vaddr); - std::pair ExclusiveReadMemory64(const IR::U32& vaddr); - void WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value); - void WriteMemory8(const IR::U32& vaddr, const IR::U8& value); - void WriteMemory16(const IR::U32& vaddr, const IR::U16& value); - void WriteMemory32(const IR::U32& vaddr, const IR::U32& value); - void WriteMemory64(const IR::U32& vaddr, const IR::U64& value); - IR::U32 ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value); - IR::U32 ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value); - IR::U32 ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value); - IR::U32 ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi); + IR::UAny ReadMemory(size_t bitsize, const IR::U32& vaddr, IR::AccType acc_type); + IR::U8 ReadMemory8(const IR::U32& vaddr, IR::AccType acc_type); + IR::U16 ReadMemory16(const IR::U32& vaddr, IR::AccType acc_type); + IR::U32 ReadMemory32(const IR::U32& vaddr, IR::AccType acc_type); + IR::U64 ReadMemory64(const IR::U32& vaddr, IR::AccType acc_type); + IR::U8 ExclusiveReadMemory8(const IR::U32& vaddr, IR::AccType acc_type); + IR::U16 ExclusiveReadMemory16(const IR::U32& vaddr, IR::AccType acc_type); + IR::U32 ExclusiveReadMemory32(const IR::U32& vaddr, IR::AccType acc_type); + std::pair ExclusiveReadMemory64(const IR::U32& vaddr, IR::AccType acc_type); + void WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value, IR::AccType acc_type); + void WriteMemory8(const IR::U32& vaddr, const IR::U8& value, IR::AccType acc_type); + void WriteMemory16(const IR::U32& vaddr, const IR::U16& value, IR::AccType acc_type); + void WriteMemory32(const IR::U32& vaddr, const IR::U32& value, IR::AccType acc_type); + void WriteMemory64(const IR::U32& vaddr, const IR::U64& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi, IR::AccType acc_type); void CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, CoprocReg CRd, CoprocReg CRn, CoprocReg CRm, size_t opc2); void CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2, const IR::U32& word); diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp index ec56443d9..4afd0b1fc 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp @@ -103,7 +103,7 @@ bool TranslatorVisitor::v8_VST_multiple(bool D, Reg n, size_t Vd, Imm<4> type, s const ExtReg ext_reg = d + i * inc + r; const IR::U64 shifted_element = ir.LogicalShiftRight(ir.GetExtendedRegister(ext_reg), ir.Imm8(static_cast(e * ebytes * 8))); const IR::UAny element = ir.LeastSignificant(8 * ebytes, shifted_element); - ir.WriteMemory(8 * ebytes, address, element); + ir.WriteMemory(8 * ebytes, address, element, IR::AccType::NORMAL); address = ir.Add(address, ir.Imm32(static_cast(ebytes))); } @@ -156,7 +156,7 @@ bool TranslatorVisitor::v8_VLD_multiple(bool D, Reg n, size_t Vd, Imm<4> type, s for (size_t r = 0; r < regs; r++) { for (size_t e = 0; e < elements; e++) { for (size_t i = 0; i < nelem; i++) { - const IR::U64 element = ir.ZeroExtendToLong(ir.ReadMemory(ebytes * 8, address)); + const IR::U64 element = ir.ZeroExtendToLong(ir.ReadMemory(ebytes * 8, address, IR::AccType::NORMAL)); const IR::U64 shifted_element = ir.LogicalShiftLeft(element, ir.Imm8(static_cast(e * ebytes * 8))); const ExtReg ext_reg = d + i * inc + r; @@ -221,7 +221,7 @@ bool TranslatorVisitor::v8_VLD_all_lanes(bool D, Reg n, size_t Vd, size_t nn, si auto address = ir.GetRegister(n); for (size_t i = 0; i < nelem; i++) { - const auto element = ir.ReadMemory(ebytes * 8, address); + const auto element = ir.ReadMemory(ebytes * 8, address, IR::AccType::NORMAL); const auto replicated_element = ir.VectorBroadcast(ebytes * 8, element); for (size_t r = 0; r < regs; r++) { @@ -291,7 +291,7 @@ bool TranslatorVisitor::v8_VST_single(bool D, Reg n, size_t Vd, size_t sz, size_ const ExtReg ext_reg = d + i * inc; const auto element = ir.VectorGetElement(ebytes * 8, ir.GetVector(ext_reg), index); - ir.WriteMemory(ebytes * 8, address, element); + ir.WriteMemory(ebytes * 8, address, element, IR::AccType::NORMAL); address = ir.Add(address, ir.Imm32(static_cast(ebytes))); } @@ -352,7 +352,7 @@ bool TranslatorVisitor::v8_VLD_single(bool D, Reg n, size_t Vd, size_t sz, size_ auto address = ir.GetRegister(n); for (size_t i = 0; i < nelem; i++) { - const auto element = ir.ReadMemory(ebytes * 8, address); + const auto element = ir.ReadMemory(ebytes * 8, address, IR::AccType::NORMAL); const ExtReg ext_reg = d + i * inc; const auto new_reg = ir.VectorSetElement(ebytes * 8, ir.GetVector(ext_reg), index, element); diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp index b511e4411..77df6a4d1 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp @@ -71,7 +71,7 @@ bool TranslatorVisitor::arm_LDR_lit(Cond cond, bool U, Reg t, Imm<12> imm12) { const bool add = U; const u32 base = ir.AlignPC(4); const u32 address = add ? (base + imm12.ZeroExtend()) : (base - imm12.ZeroExtend()); - const auto data = ir.ReadMemory32(ir.Imm32(address)); + const auto data = ir.ReadMemory32(ir.Imm32(address), IR::AccType::NORMAL); if (t == Reg::PC) { ir.LoadWritePC(data); @@ -102,7 +102,7 @@ bool TranslatorVisitor::arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Re const u32 imm32 = imm12.ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (t == Reg::PC) { ir.LoadWritePC(data); @@ -138,7 +138,7 @@ bool TranslatorVisitor::arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Re const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (t == Reg::PC) { ir.LoadWritePC(data); @@ -164,7 +164,7 @@ bool TranslatorVisitor::arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> imm12) { const bool add = U; const u32 base = ir.AlignPC(4); const u32 address = add ? (base + imm32) : (base - imm32); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(ir.Imm32(address))); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(ir.Imm32(address), IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -193,7 +193,7 @@ bool TranslatorVisitor::arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, R const u32 imm32 = imm12.ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -217,7 +217,7 @@ bool TranslatorVisitor::arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, R const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -243,11 +243,17 @@ bool TranslatorVisitor::arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm const u32 base = ir.AlignPC(4); const u32 address = add ? (base + imm32) : (base - imm32); - const auto data_a = ir.ReadMemory32(ir.Imm32(address)); - const auto data_b = ir.ReadMemory32(ir.Imm32(address + 4)); - ir.SetRegister(t, data_a); - ir.SetRegister(t2, data_b); + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = ir.ReadMemory64(ir.Imm32(address), IR::AccType::ATOMIC); + + if (ir.current_location.EFlag()) { + ir.SetRegister(t, ir.MostSignificantWord(data).result); + ir.SetRegister(t2, ir.LeastSignificantWord(data)); + } else { + ir.SetRegister(t, ir.LeastSignificantWord(data)); + ir.SetRegister(t2, ir.MostSignificantWord(data).result); + } return true; } @@ -282,13 +288,18 @@ bool TranslatorVisitor::arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, R const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); const auto offset = ir.Imm32(imm32); - const auto address_a = GetAddress(ir, P, U, W, n, offset); - const auto address_b = ir.Add(address_a, ir.Imm32(4)); - const auto data_a = ir.ReadMemory32(address_a); - const auto data_b = ir.ReadMemory32(address_b); + const auto address = GetAddress(ir, P, U, W, n, offset); - ir.SetRegister(t, data_a); - ir.SetRegister(t2, data_b); + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = ir.ReadMemory64(address, IR::AccType::ATOMIC); + + if (ir.current_location.EFlag()) { + ir.SetRegister(t, ir.MostSignificantWord(data).result); + ir.SetRegister(t2, ir.LeastSignificantWord(data)); + } else { + ir.SetRegister(t, ir.LeastSignificantWord(data)); + ir.SetRegister(t2, ir.MostSignificantWord(data).result); + } return true; } @@ -317,13 +328,18 @@ bool TranslatorVisitor::arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, R const Reg t2 = t + 1; const auto offset = ir.GetRegister(m); - const auto address_a = GetAddress(ir, P, U, W, n, offset); - const auto address_b = ir.Add(address_a, ir.Imm32(4)); - const auto data_a = ir.ReadMemory32(address_a); - const auto data_b = ir.ReadMemory32(address_b); + const auto address = GetAddress(ir, P, U, W, n, offset); - ir.SetRegister(t, data_a); - ir.SetRegister(t2, data_b); + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = ir.ReadMemory64(address, IR::AccType::ATOMIC); + + if (ir.current_location.EFlag()) { + ir.SetRegister(t, ir.MostSignificantWord(data).result); + ir.SetRegister(t2, ir.LeastSignificantWord(data)); + } else { + ir.SetRegister(t, ir.LeastSignificantWord(data)); + ir.SetRegister(t2, ir.MostSignificantWord(data).result); + } return true; } @@ -346,7 +362,7 @@ bool TranslatorVisitor::arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, I const bool add = U; const u32 base = ir.AlignPC(4); const u32 address = add ? (base + imm32) : (base - imm32); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address))); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address), IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -375,7 +391,7 @@ bool TranslatorVisitor::arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, R const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -399,7 +415,7 @@ bool TranslatorVisitor::arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, R const auto offset = ir.GetRegister(m); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -420,7 +436,7 @@ bool TranslatorVisitor::arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Im const u32 base = ir.AlignPC(4); const u32 address = add ? (base + imm32) : (base - imm32); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(ir.Imm32(address))); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(ir.Imm32(address), IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -449,7 +465,7 @@ bool TranslatorVisitor::arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -473,7 +489,7 @@ bool TranslatorVisitor::arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, const auto offset = ir.GetRegister(m); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -493,7 +509,7 @@ bool TranslatorVisitor::arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Im const bool add = U; const u32 base = ir.AlignPC(4); const u32 address = add ? (base + imm32) : (base - imm32); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address))); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(ir.Imm32(address), IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -522,7 +538,7 @@ bool TranslatorVisitor::arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -546,7 +562,7 @@ bool TranslatorVisitor::arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, const auto offset = ir.GetRegister(m); const auto address = GetAddress(ir, P, U, W, n, offset); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -565,7 +581,7 @@ bool TranslatorVisitor::arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Re const auto offset = ir.Imm32(imm12.ZeroExtend()); const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory32(address, ir.GetRegister(t)); + ir.WriteMemory32(address, ir.GetRegister(t), IR::AccType::NORMAL); return true; } @@ -586,7 +602,7 @@ bool TranslatorVisitor::arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Re const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory32(address, ir.GetRegister(t)); + ir.WriteMemory32(address, ir.GetRegister(t), IR::AccType::NORMAL); return true; } @@ -607,7 +623,7 @@ bool TranslatorVisitor::arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, R const auto offset = ir.Imm32(imm12.ZeroExtend()); const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); + ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)), IR::AccType::NORMAL); return true; } @@ -628,7 +644,7 @@ bool TranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, R const auto offset = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()).result; const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); + ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)), IR::AccType::NORMAL); return true; } @@ -658,13 +674,15 @@ bool TranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, R const u32 imm32 = concatenate(imm8a, imm8b).ZeroExtend(); const auto offset = ir.Imm32(imm32); - const auto address_a = GetAddress(ir, P, U, W, n, offset); - const auto address_b = ir.Add(address_a, ir.Imm32(4)); + const auto address = GetAddress(ir, P, U, W, n, offset); const auto value_a = ir.GetRegister(t); const auto value_b = ir.GetRegister(t2); - ir.WriteMemory32(address_a, value_a); - ir.WriteMemory32(address_b, value_b); + const IR::U64 data = ir.current_location.EFlag() ? ir.Pack2x32To1x64(value_b, value_a) + : ir.Pack2x32To1x64(value_a, value_b); + + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + ir.WriteMemory64(address, data, IR::AccType::ATOMIC); return true; } @@ -693,13 +711,15 @@ bool TranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, R } const auto offset = ir.GetRegister(m); - const auto address_a = GetAddress(ir, P, U, W, n, offset); - const auto address_b = ir.Add(address_a, ir.Imm32(4)); + const auto address = GetAddress(ir, P, U, W, n, offset); const auto value_a = ir.GetRegister(t); const auto value_b = ir.GetRegister(t2); - ir.WriteMemory32(address_a, value_a); - ir.WriteMemory32(address_b, value_b); + const IR::U64 data = ir.current_location.EFlag() ? ir.Pack2x32To1x64(value_b, value_a) + : ir.Pack2x32To1x64(value_a, value_b); + + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + ir.WriteMemory64(address, data, IR::AccType::ATOMIC); return true; } @@ -722,7 +742,7 @@ bool TranslatorVisitor::arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, R const auto offset = ir.Imm32(imm32); const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t))); + ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t)), IR::AccType::NORMAL); return true; } @@ -744,7 +764,7 @@ bool TranslatorVisitor::arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, R const auto offset = ir.GetRegister(m); const auto address = GetAddress(ir, P, U, W, n, offset); - ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t))); + ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t)), IR::AccType::NORMAL); return true; } @@ -752,7 +772,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { - ir.SetRegister(static_cast(i), ir.ReadMemory32(address)); + ir.SetRegister(static_cast(i), ir.ReadMemory32(address, IR::AccType::ATOMIC)); address = ir.Add(address, ir.Imm32(4)); } } @@ -760,7 +780,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s ir.SetRegister(n, writeback_address); } if (Common::Bit<15>(list)) { - ir.LoadWritePC(ir.ReadMemory32(address)); + ir.LoadWritePC(ir.ReadMemory32(address, IR::AccType::ATOMIC)); if (n == Reg::R13) ir.SetTerm(IR::Term::PopRSBHint{}); else @@ -854,7 +874,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { - ir.WriteMemory32(address, ir.GetRegister(static_cast(i))); + ir.WriteMemory32(address, ir.GetRegister(static_cast(i)), IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } @@ -862,7 +882,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s ir.SetRegister(n, writeback_address); } if (Common::Bit<15>(list)) { - ir.WriteMemory32(address, ir.Imm32(ir.PC())); + ir.WriteMemory32(address, ir.Imm32(ir.PC()), IR::AccType::ATOMIC); } return true; } diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/synchronization.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/synchronization.cpp index b020164ec..e9f04b70e 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/synchronization.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/synchronization.cpp @@ -24,8 +24,9 @@ bool TranslatorVisitor::arm_SWP(Cond cond, Reg n, Reg t, Reg t2) { return true; } - const auto data = ir.ReadMemory32(ir.GetRegister(n)); - ir.WriteMemory32(ir.GetRegister(n), ir.GetRegister(t2)); + // TODO (HACK): Implement bus locking here + const auto data = ir.ReadMemory32(ir.GetRegister(n), IR::AccType::SWAP); + ir.WriteMemory32(ir.GetRegister(n), ir.GetRegister(t2), IR::AccType::SWAP); // TODO: Alignment check ir.SetRegister(t, data); return true; @@ -42,8 +43,9 @@ bool TranslatorVisitor::arm_SWPB(Cond cond, Reg n, Reg t, Reg t2) { return true; } - const auto data = ir.ReadMemory8(ir.GetRegister(n)); - ir.WriteMemory8(ir.GetRegister(n), ir.LeastSignificantByte(ir.GetRegister(t2))); + // TODO (HACK): Implement bus locking here + const auto data = ir.ReadMemory8(ir.GetRegister(n), IR::AccType::SWAP); + ir.WriteMemory8(ir.GetRegister(n), ir.LeastSignificantByte(ir.GetRegister(t2)), IR::AccType::SWAP); // TODO: Alignment check ir.SetRegister(t, ir.ZeroExtendByteToWord(data)); return true; @@ -60,7 +62,7 @@ bool TranslatorVisitor::arm_LDA(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ReadMemory32(address)); // AccessType::Ordered + ir.SetRegister(t, ir.ReadMemory32(address, IR::AccType::ORDERED)); return true; } // LDAB , [] @@ -74,7 +76,7 @@ bool TranslatorVisitor::arm_LDAB(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory8(address))); // AccessType::Ordered + ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory8(address, IR::AccType::ORDERED))); return true; } // LDAH , [] @@ -88,7 +90,7 @@ bool TranslatorVisitor::arm_LDAH(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory16(address))); // AccessType::Ordered + ir.SetRegister(t, ir.ZeroExtendToWord(ir.ReadMemory16(address, IR::AccType::ORDERED))); return true; } @@ -103,7 +105,7 @@ bool TranslatorVisitor::arm_LDAEX(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ExclusiveReadMemory32(address)); // AccessType::Ordered + ir.SetRegister(t, ir.ExclusiveReadMemory32(address, IR::AccType::ORDERED)); return true; } @@ -118,7 +120,7 @@ bool TranslatorVisitor::arm_LDAEXB(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address))); // AccessType::Ordered + ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address, IR::AccType::ORDERED))); return true; } @@ -133,7 +135,7 @@ bool TranslatorVisitor::arm_LDAEXD(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - const auto [lo, hi] = ir.ExclusiveReadMemory64(address); // AccessType::Ordered + const auto [lo, hi] = ir.ExclusiveReadMemory64(address, IR::AccType::ORDERED); // DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR ir.SetRegister(t, lo); ir.SetRegister(t + 1, hi); @@ -151,7 +153,7 @@ bool TranslatorVisitor::arm_LDAEXH(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address))); // AccessType::Ordered + ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address, IR::AccType::ORDERED))); return true; } @@ -166,7 +168,7 @@ bool TranslatorVisitor::arm_STL(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.WriteMemory32(address, ir.GetRegister(t)); // AccessType::Ordered + ir.WriteMemory32(address, ir.GetRegister(t), IR::AccType::ORDERED); return true; } @@ -181,7 +183,7 @@ bool TranslatorVisitor::arm_STLB(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t))); // AccessType::Ordered + ir.WriteMemory8(address, ir.LeastSignificantByte(ir.GetRegister(t)), IR::AccType::ORDERED); return true; } @@ -196,7 +198,7 @@ bool TranslatorVisitor::arm_STLH(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t))); // AccessType::Ordered + ir.WriteMemory16(address, ir.LeastSignificantHalf(ir.GetRegister(t)), IR::AccType::ORDERED); return true; } @@ -216,7 +218,7 @@ bool TranslatorVisitor::arm_STLEXB(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantByte(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory8(address, value); // AccessType::Ordered + const auto passed = ir.ExclusiveWriteMemory8(address, value, IR::AccType::ORDERED); ir.SetRegister(d, passed); return true; } @@ -238,7 +240,7 @@ bool TranslatorVisitor::arm_STLEXD(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value_lo = ir.GetRegister(t); const auto value_hi = ir.GetRegister(t2); - const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi); // AccessType::Ordered + const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi, IR::AccType::ORDERED); ir.SetRegister(d, passed); return true; } @@ -259,7 +261,7 @@ bool TranslatorVisitor::arm_STLEXH(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantHalf(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory16(address, value); // AccessType::Ordered + const auto passed = ir.ExclusiveWriteMemory16(address, value, IR::AccType::ORDERED); ir.SetRegister(d, passed); return true; } @@ -280,7 +282,7 @@ bool TranslatorVisitor::arm_STLEX(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.GetRegister(t); - const auto passed = ir.ExclusiveWriteMemory32(address, value); + const auto passed = ir.ExclusiveWriteMemory32(address, value, IR::AccType::ORDERED); ir.SetRegister(d, passed); return true; } @@ -296,7 +298,7 @@ bool TranslatorVisitor::arm_LDREX(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ExclusiveReadMemory32(address)); + ir.SetRegister(t, ir.ExclusiveReadMemory32(address, IR::AccType::ATOMIC)); return true; } @@ -311,7 +313,7 @@ bool TranslatorVisitor::arm_LDREXB(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address))); + ir.SetRegister(t, ir.ZeroExtendByteToWord(ir.ExclusiveReadMemory8(address, IR::AccType::ATOMIC))); return true; } @@ -326,7 +328,7 @@ bool TranslatorVisitor::arm_LDREXD(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - const auto [lo, hi] = ir.ExclusiveReadMemory64(address); + const auto [lo, hi] = ir.ExclusiveReadMemory64(address, IR::AccType::ATOMIC); // DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR ir.SetRegister(t, lo); ir.SetRegister(t + 1, hi); @@ -344,7 +346,7 @@ bool TranslatorVisitor::arm_LDREXH(Cond cond, Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address))); + ir.SetRegister(t, ir.ZeroExtendHalfToWord(ir.ExclusiveReadMemory16(address, IR::AccType::ATOMIC))); return true; } @@ -364,7 +366,7 @@ bool TranslatorVisitor::arm_STREX(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.GetRegister(t); - const auto passed = ir.ExclusiveWriteMemory32(address, value); + const auto passed = ir.ExclusiveWriteMemory32(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -385,7 +387,7 @@ bool TranslatorVisitor::arm_STREXB(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantByte(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory8(address, value); + const auto passed = ir.ExclusiveWriteMemory8(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -408,7 +410,7 @@ bool TranslatorVisitor::arm_STREXD(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value_lo = ir.GetRegister(t); const auto value_hi = ir.GetRegister(t2); - const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi); + const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -429,7 +431,7 @@ bool TranslatorVisitor::arm_STREXH(Cond cond, Reg n, Reg d, Reg t) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantHalf(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory16(address, value); + const auto passed = ir.ExclusiveWriteMemory16(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp index d57971158..dbaf5f08f 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp @@ -444,7 +444,7 @@ bool TranslatorVisitor::thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) { bool TranslatorVisitor::thumb16_LDR_literal(Reg t, Imm<8> imm8) { const u32 imm32 = imm8.ZeroExtend() << 2; const u32 address = ir.AlignPC(4) + imm32; - const auto data = ir.ReadMemory32(ir.Imm32(address)); + const auto data = ir.ReadMemory32(ir.Imm32(address), IR::AccType::NORMAL); ir.SetRegister(t, data); return true; @@ -456,7 +456,7 @@ bool TranslatorVisitor::thumb16_STR_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); const auto data = ir.GetRegister(t); - ir.WriteMemory32(address, data); + ir.WriteMemory32(address, data, IR::AccType::NORMAL); return true; } @@ -466,7 +466,7 @@ bool TranslatorVisitor::thumb16_STRH_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); const auto data = ir.LeastSignificantHalf(ir.GetRegister(t)); - ir.WriteMemory16(address, data); + ir.WriteMemory16(address, data, IR::AccType::NORMAL); return true; } @@ -476,7 +476,7 @@ bool TranslatorVisitor::thumb16_STRB_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); const auto data = ir.LeastSignificantByte(ir.GetRegister(t)); - ir.WriteMemory8(address, data); + ir.WriteMemory8(address, data, IR::AccType::NORMAL); return true; } @@ -484,7 +484,7 @@ bool TranslatorVisitor::thumb16_STRB_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDRSB_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.SignExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -494,7 +494,7 @@ bool TranslatorVisitor::thumb16_LDRSB_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDR_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); ir.SetRegister(t, data); return true; @@ -504,7 +504,7 @@ bool TranslatorVisitor::thumb16_LDR_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDRH_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -514,7 +514,7 @@ bool TranslatorVisitor::thumb16_LDRH_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDRB_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -524,7 +524,7 @@ bool TranslatorVisitor::thumb16_LDRB_reg(Reg m, Reg n, Reg t) { // Rt cannot encode R15. bool TranslatorVisitor::thumb16_LDRSH_reg(Reg m, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); - const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.SignExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -537,7 +537,7 @@ bool TranslatorVisitor::thumb16_STR_imm_t1(Imm<5> imm5, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto data = ir.GetRegister(t); - ir.WriteMemory32(address, data); + ir.WriteMemory32(address, data, IR::AccType::NORMAL); return true; } @@ -546,7 +546,7 @@ bool TranslatorVisitor::thumb16_STR_imm_t1(Imm<5> imm5, Reg n, Reg t) { bool TranslatorVisitor::thumb16_LDR_imm_t1(Imm<5> imm5, Reg n, Reg t) { const u32 imm32 = imm5.ZeroExtend() << 2; const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); ir.SetRegister(t, data); return true; @@ -559,7 +559,7 @@ bool TranslatorVisitor::thumb16_STRB_imm(Imm<5> imm5, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto data = ir.LeastSignificantByte(ir.GetRegister(t)); - ir.WriteMemory8(address, data); + ir.WriteMemory8(address, data, IR::AccType::NORMAL); return true; } @@ -568,7 +568,7 @@ bool TranslatorVisitor::thumb16_STRB_imm(Imm<5> imm5, Reg n, Reg t) { bool TranslatorVisitor::thumb16_LDRB_imm(Imm<5> imm5, Reg n, Reg t) { const u32 imm32 = imm5.ZeroExtend(); const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); - const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address)); + const auto data = ir.ZeroExtendByteToWord(ir.ReadMemory8(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -580,7 +580,7 @@ bool TranslatorVisitor::thumb16_STRH_imm(Imm<5> imm5, Reg n, Reg t) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto data = ir.LeastSignificantHalf(ir.GetRegister(t)); - ir.WriteMemory16(address, data); + ir.WriteMemory16(address, data, IR::AccType::NORMAL); return true; } @@ -588,7 +588,7 @@ bool TranslatorVisitor::thumb16_STRH_imm(Imm<5> imm5, Reg n, Reg t) { bool TranslatorVisitor::thumb16_LDRH_imm(Imm<5> imm5, Reg n, Reg t) { const u32 imm32 = imm5.ZeroExtend() << 1; const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); - const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address)); + const auto data = ir.ZeroExtendHalfToWord(ir.ReadMemory16(address, IR::AccType::NORMAL)); ir.SetRegister(t, data); return true; @@ -602,7 +602,7 @@ bool TranslatorVisitor::thumb16_STR_imm_t2(Reg t, Imm<8> imm8) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); const auto data = ir.GetRegister(t); - ir.WriteMemory32(address, data); + ir.WriteMemory32(address, data, IR::AccType::NORMAL); return true; } @@ -612,7 +612,7 @@ bool TranslatorVisitor::thumb16_LDR_imm_t2(Reg t, Imm<8> imm8) { const u32 imm32 = imm8.ZeroExtend() << 2; const Reg n = Reg::SP; const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm32)); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); ir.SetRegister(t, data); return true; @@ -766,7 +766,7 @@ bool TranslatorVisitor::thumb16_PUSH(bool M, RegList reg_list) { if (Common::Bit(i, reg_list)) { // TODO: Deal with alignment const auto Ri = ir.GetRegister(static_cast(i)); - ir.WriteMemory32(address, Ri); + ir.WriteMemory32(address, Ri, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } @@ -789,7 +789,7 @@ bool TranslatorVisitor::thumb16_POP(bool P, RegList reg_list) { for (size_t i = 0; i < 15; i++) { if (Common::Bit(i, reg_list)) { // TODO: Deal with alignment - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::ATOMIC); ir.SetRegister(static_cast(i), data); address = ir.Add(address, ir.Imm32(4)); } @@ -797,7 +797,7 @@ bool TranslatorVisitor::thumb16_POP(bool P, RegList reg_list) { if (Common::Bit<15>(reg_list)) { // TODO(optimization): Possible location for an RSB pop. - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::ATOMIC); ir.UpdateUpperLocationDescriptor(); ir.LoadWritePC(data); address = ir.Add(address, ir.Imm32(4)); @@ -879,7 +879,7 @@ bool TranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) { for (size_t i = 0; i < 8; i++) { if (Common::Bit(i, reg_list)) { const auto Ri = ir.GetRegister(static_cast(i)); - ir.WriteMemory32(address, Ri); + ir.WriteMemory32(address, Ri, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } @@ -899,7 +899,7 @@ bool TranslatorVisitor::thumb16_LDMIA(Reg n, RegList reg_list) { for (size_t i = 0; i < 8; i++) { if (Common::Bit(i, reg_list)) { - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::ATOMIC); ir.SetRegister(static_cast(i), data); address = ir.Add(address, ir.Imm32(4)); } diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp index 3f00efa81..42b2ebf4a 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp @@ -31,7 +31,7 @@ static bool LoadByteLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, const u32 imm32 = imm12.ZeroExtend(); const u32 base = v.ir.AlignPC(4); const u32 address = U ? (base + imm32) : (base - imm32); - const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory8(v.ir.Imm32(address))); + const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory8(v.ir.Imm32(address), IR::AccType::NORMAL)); v.ir.SetRegister(t, data); return true; @@ -46,7 +46,7 @@ static bool LoadByteRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re const auto reg_m = v.ir.GetRegister(m); const auto offset = v.ir.LogicalShiftLeft(reg_m, v.ir.Imm8(imm2.ZeroExtend())); const auto address = v.ir.Add(reg_n, offset); - const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory8(address)); + const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory8(address, IR::AccType::NORMAL)); v.ir.SetRegister(t, data); return true; @@ -58,7 +58,7 @@ static bool LoadByteImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32)) : v.ir.Sub(reg_n, v.ir.Imm32(imm32)); const IR::U32 address = P ? offset_address : reg_n; - const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory8(address)); + const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory8(address, IR::AccType::NORMAL)); v.ir.SetRegister(t, data); if (W) { diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp index f1bba517a..5b9f1639a 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp @@ -13,7 +13,7 @@ static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, const auto imm32 = imm12.ZeroExtend(); const auto base = v.ir.AlignPC(4); const auto address = U ? (base + imm32) : (base - imm32); - const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory16(v.ir.Imm32(address))); + const auto data = (v.ir.*ext_fn)(v.ir.ReadMemory16(v.ir.Imm32(address), IR::AccType::NORMAL)); v.ir.SetRegister(t, data); return true; @@ -28,7 +28,7 @@ static bool LoadHalfRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re const IR::U32 reg_n = v.ir.GetRegister(n); const IR::U32 offset = v.ir.LogicalShiftLeft(reg_m, v.ir.Imm8(imm2.ZeroExtend())); const IR::U32 address = v.ir.Add(reg_n, offset); - const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory16(address)); + const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory16(address, IR::AccType::NORMAL)); v.ir.SetRegister(t, data); return true; @@ -41,7 +41,7 @@ static bool LoadHalfImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U : v.ir.Sub(reg_n, v.ir.Imm32(imm32)); const IR::U32 address = P ? offset_address : reg_n; - const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory16(address)); + const IR::U32 data = (v.ir.*ext_fn)(v.ir.ReadMemory16(address, IR::AccType::NORMAL)); if (W) { v.ir.SetRegister(n, offset_address); diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp index af539b25a..374cc906f 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp @@ -24,10 +24,10 @@ static bool TableBranch(TranslatorVisitor& v, Reg n, Reg m, bool half) { IR::U32 halfwords; if (half) { - const auto data = v.ir.ReadMemory16(v.ir.Add(reg_n, v.ir.LogicalShiftLeft(reg_m, v.ir.Imm8(1)))); + const auto data = v.ir.ReadMemory16(v.ir.Add(reg_n, v.ir.LogicalShiftLeft(reg_m, v.ir.Imm8(1))), IR::AccType::NORMAL); halfwords = v.ir.ZeroExtendToWord(data); } else { - halfwords = v.ir.ZeroExtendToWord(v.ir.ReadMemory8(v.ir.Add(reg_n, reg_m))); + halfwords = v.ir.ZeroExtendToWord(v.ir.ReadMemory8(v.ir.Add(reg_n, reg_m), IR::AccType::NORMAL)); } const auto current_pc = v.ir.Imm32(v.ir.PC()); @@ -51,12 +51,18 @@ static bool LoadDualImmediate(TranslatorVisitor& v, bool P, bool U, bool W, Reg const IR::U32 reg_n = v.ir.GetRegister(n); const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm)) : v.ir.Sub(reg_n, v.ir.Imm32(imm)); - const IR::U32 address_1 = P ? offset_address - : reg_n; - const IR::U32 address_2 = v.ir.Add(address_1, v.ir.Imm32(4)); + const IR::U32 address = P ? offset_address : reg_n; - v.ir.SetRegister(t, v.ir.ReadMemory32(address_1)); - v.ir.SetRegister(t2, v.ir.ReadMemory32(address_2)); + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = v.ir.ReadMemory64(address, IR::AccType::ATOMIC); + + if (v.ir.current_location.EFlag()) { + v.ir.SetRegister(t, v.ir.MostSignificantWord(data).result); + v.ir.SetRegister(t2, v.ir.LeastSignificantWord(data)); + } else { + v.ir.SetRegister(t, v.ir.LeastSignificantWord(data)); + v.ir.SetRegister(t2, v.ir.MostSignificantWord(data).result); + } if (W) { v.ir.SetRegister(n, offset_address); @@ -73,12 +79,20 @@ static bool LoadDualLiteral(TranslatorVisitor& v, bool U, bool W, Reg t, Reg t2, } const auto imm = imm8.ZeroExtend() << 2; - const auto address_1 = U ? v.ir.Add(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)) - : v.ir.Sub(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)); - const auto address_2 = v.ir.Add(address_1, v.ir.Imm32(4)); + const auto address = U ? v.ir.Add(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)) + : v.ir.Sub(v.ir.Imm32(v.ir.AlignPC(4)), v.ir.Imm32(imm)); + + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + const IR::U64 data = v.ir.ReadMemory64(address, IR::AccType::ATOMIC); + + if (v.ir.current_location.EFlag()) { + v.ir.SetRegister(t, v.ir.MostSignificantWord(data).result); + v.ir.SetRegister(t2, v.ir.LeastSignificantWord(data)); + } else { + v.ir.SetRegister(t, v.ir.LeastSignificantWord(data)); + v.ir.SetRegister(t2, v.ir.MostSignificantWord(data).result); + } - v.ir.SetRegister(t, v.ir.ReadMemory32(address_1)); - v.ir.SetRegister(t2, v.ir.ReadMemory32(address_2)); return true; } @@ -97,12 +111,13 @@ static bool StoreDual(TranslatorVisitor& v, bool P, bool U, bool W, Reg n, Reg t const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm)) : v.ir.Sub(reg_n, v.ir.Imm32(imm)); - const IR::U32 address_1 = P ? offset_address - : reg_n; - const IR::U32 address_2 = v.ir.Add(address_1, v.ir.Imm32(4)); + const IR::U32 address = P ? offset_address : reg_n; - v.ir.WriteMemory32(address_1, reg_t); - v.ir.WriteMemory32(address_2, reg_t2); + const IR::U64 data = v.ir.current_location.EFlag() ? v.ir.Pack2x32To1x64(reg_t2, reg_t) + : v.ir.Pack2x32To1x64(reg_t, reg_t2); + + // NOTE: If alignment is exactly off by 4, each word is an atomic access. + v.ir.WriteMemory64(address, data, IR::AccType::ATOMIC); if (W) { v.ir.SetRegister(n, offset_address); @@ -116,7 +131,7 @@ bool TranslatorVisitor::thumb32_LDA(Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.SetRegister(t, ir.ReadMemory32(address)); // AccType::Ordered + ir.SetRegister(t, ir.ReadMemory32(address, IR::AccType::ORDERED)); return true; } @@ -150,7 +165,7 @@ bool TranslatorVisitor::thumb32_LDREX(Reg n, Reg t, Imm<8> imm8) { } const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm8.ZeroExtend() << 2)); - const auto value = ir.ExclusiveReadMemory32(address); + const auto value = ir.ExclusiveReadMemory32(address, IR::AccType::ATOMIC); ir.SetRegister(t, value); return true; @@ -162,7 +177,7 @@ bool TranslatorVisitor::thumb32_LDREXB(Reg n, Reg t) { } const auto address = ir.GetRegister(n); - const auto value = ir.ZeroExtendToWord(ir.ExclusiveReadMemory8(address)); + const auto value = ir.ZeroExtendToWord(ir.ExclusiveReadMemory8(address, IR::AccType::ATOMIC)); ir.SetRegister(t, value); return true; @@ -174,7 +189,7 @@ bool TranslatorVisitor::thumb32_LDREXD(Reg n, Reg t, Reg t2) { } const auto address = ir.GetRegister(n); - const auto [lo, hi] = ir.ExclusiveReadMemory64(address); + const auto [lo, hi] = ir.ExclusiveReadMemory64(address, IR::AccType::ATOMIC); // DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR ir.SetRegister(t, lo); @@ -188,7 +203,7 @@ bool TranslatorVisitor::thumb32_LDREXH(Reg n, Reg t) { } const auto address = ir.GetRegister(n); - const auto value = ir.ZeroExtendToWord(ir.ExclusiveReadMemory16(address)); + const auto value = ir.ZeroExtendToWord(ir.ExclusiveReadMemory16(address, IR::AccType::ATOMIC)); ir.SetRegister(t, value); return true; @@ -200,7 +215,7 @@ bool TranslatorVisitor::thumb32_STL(Reg n, Reg t) { } const auto address = ir.GetRegister(n); - ir.WriteMemory32(address, ir.GetRegister(t)); // AccType::Ordered + ir.WriteMemory32(address, ir.GetRegister(t), IR::AccType::ORDERED); return true; } @@ -214,7 +229,7 @@ bool TranslatorVisitor::thumb32_STREX(Reg n, Reg t, Reg d, Imm<8> imm8) { const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm8.ZeroExtend() << 2)); const auto value = ir.GetRegister(t); - const auto passed = ir.ExclusiveWriteMemory32(address, value); + const auto passed = ir.ExclusiveWriteMemory32(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -229,7 +244,7 @@ bool TranslatorVisitor::thumb32_STREXB(Reg n, Reg t, Reg d) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantByte(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory8(address, value); + const auto passed = ir.ExclusiveWriteMemory8(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -245,7 +260,7 @@ bool TranslatorVisitor::thumb32_STREXD(Reg n, Reg t, Reg t2, Reg d) { const auto address = ir.GetRegister(n); const auto value_lo = ir.GetRegister(t); const auto value_hi = ir.GetRegister(t2); - const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi); + const auto passed = ir.ExclusiveWriteMemory64(address, value_lo, value_hi, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } @@ -260,7 +275,7 @@ bool TranslatorVisitor::thumb32_STREXH(Reg n, Reg t, Reg d) { const auto address = ir.GetRegister(n); const auto value = ir.LeastSignificantHalf(ir.GetRegister(t)); - const auto passed = ir.ExclusiveWriteMemory16(address, value); + const auto passed = ir.ExclusiveWriteMemory16(address, value, IR::AccType::ATOMIC); ir.SetRegister(d, passed); return true; } diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp index da6e6e653..c4ff07664 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp @@ -15,7 +15,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32 auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { - ir.SetRegister(static_cast(i), ir.ReadMemory32(address)); + ir.SetRegister(static_cast(i), ir.ReadMemory32(address, IR::AccType::ATOMIC)); address = ir.Add(address, ir.Imm32(4)); } } @@ -24,7 +24,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32 } if (Common::Bit<15>(list)) { ir.UpdateUpperLocationDescriptor(); - ir.LoadWritePC(ir.ReadMemory32(address)); + ir.LoadWritePC(ir.ReadMemory32(address, IR::AccType::ATOMIC)); if (n == Reg::R13) { ir.SetTerm(IR::Term::PopRSBHint{}); } else { @@ -39,7 +39,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32 auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { - ir.WriteMemory32(address, ir.GetRegister(static_cast(i))); + ir.WriteMemory32(address, ir.GetRegister(static_cast(i)), IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp index caa370adb..b92e27fc6 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp @@ -18,7 +18,7 @@ bool TranslatorVisitor::thumb32_LDR_lit(bool U, Reg t, Imm<12> imm12) { const u32 imm32 = imm12.ZeroExtend(); const u32 base = ir.AlignPC(4); const u32 address = U ? base + imm32 : base - imm32; - const auto data = ir.ReadMemory32(ir.Imm32(address)); + const auto data = ir.ReadMemory32(ir.Imm32(address), IR::AccType::NORMAL); if (t == Reg::PC) { ir.UpdateUpperLocationDescriptor(); @@ -48,7 +48,7 @@ bool TranslatorVisitor::thumb32_LDR_imm8(Reg n, Reg t, bool P, bool U, bool W, I : ir.Sub(reg_n, ir.Imm32(imm32)); const IR::U32 address = P ? offset_address : reg_n; - const IR::U32 data = ir.ReadMemory32(address); + const IR::U32 data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (W) { ir.SetRegister(n, offset_address); @@ -79,7 +79,7 @@ bool TranslatorVisitor::thumb32_LDR_imm12(Reg n, Reg t, Imm<12> imm12) { const auto imm32 = imm12.ZeroExtend(); const auto reg_n = ir.GetRegister(n); const auto address = ir.Add(reg_n, ir.Imm32(imm32)); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (t == Reg::PC) { ir.UpdateUpperLocationDescriptor(); @@ -104,7 +104,7 @@ bool TranslatorVisitor::thumb32_LDR_reg(Reg n, Reg t, Imm<2> imm2, Reg m) { const auto reg_n = ir.GetRegister(n); const auto offset = ir.LogicalShiftLeft(reg_m, ir.Imm8(imm2.ZeroExtend())); const auto address = ir.Add(reg_n, offset); - const auto data = ir.ReadMemory32(address); + const auto data = ir.ReadMemory32(address, IR::AccType::NORMAL); if (t == Reg::PC) { ir.UpdateUpperLocationDescriptor(); diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp index 9a9774230..93c383757 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp @@ -32,15 +32,15 @@ static bool StoreRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m using StoreImmFn = void (*)(TranslatorVisitor&, const IR::U32&, const IR::U32&); static void StoreImmByteFn(TranslatorVisitor& v, const IR::U32& address, const IR::U32& data) { - v.ir.WriteMemory8(address, v.ir.LeastSignificantByte(data)); + v.ir.WriteMemory8(address, v.ir.LeastSignificantByte(data), IR::AccType::NORMAL); } static void StoreImmHalfFn(TranslatorVisitor& v, const IR::U32& address, const IR::U32& data) { - v.ir.WriteMemory16(address, v.ir.LeastSignificantHalf(data)); + v.ir.WriteMemory16(address, v.ir.LeastSignificantHalf(data), IR::AccType::NORMAL); } static void StoreImmWordFn(TranslatorVisitor& v, const IR::U32& address, const IR::U32& data) { - v.ir.WriteMemory32(address, data); + v.ir.WriteMemory32(address, data, IR::AccType::NORMAL); } static bool StoreImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12, StoreImmFn store_fn) { @@ -110,7 +110,7 @@ bool TranslatorVisitor::thumb32_STRBT(Reg n, Reg t, Imm<8> imm8) { bool TranslatorVisitor::thumb32_STRB(Reg n, Reg t, Imm<2> imm2, Reg m) { return StoreRegister(*this, n, t, imm2, m, [this](const IR::U32& offset_address, const IR::U32& data) { - ir.WriteMemory8(offset_address, ir.LeastSignificantByte(data)); + ir.WriteMemory8(offset_address, ir.LeastSignificantByte(data), IR::AccType::NORMAL); }); } @@ -163,7 +163,7 @@ bool TranslatorVisitor::thumb32_STRHT(Reg n, Reg t, Imm<8> imm8) { bool TranslatorVisitor::thumb32_STRH(Reg n, Reg t, Imm<2> imm2, Reg m) { return StoreRegister(*this, n, t, imm2, m, [this](const IR::U32& offset_address, const IR::U32& data) { - ir.WriteMemory16(offset_address, ir.LeastSignificantHalf(data)); + ir.WriteMemory16(offset_address, ir.LeastSignificantHalf(data), IR::AccType::NORMAL); }); } @@ -216,7 +216,7 @@ bool TranslatorVisitor::thumb32_STRT(Reg n, Reg t, Imm<8> imm8) { bool TranslatorVisitor::thumb32_STR_reg(Reg n, Reg t, Imm<2> imm2, Reg m) { return StoreRegister(*this, n, t, imm2, m, [this](const IR::U32& offset_address, const IR::U32& data) { - ir.WriteMemory32(offset_address, data); + ir.WriteMemory32(offset_address, data, IR::AccType::NORMAL); }); } diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/vfp.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/vfp.cpp index 58300efb7..f68c8f382 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/vfp.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/vfp.cpp @@ -1186,16 +1186,16 @@ bool TranslatorVisitor::vfp_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm<8> i for (size_t i = 0; i < regs; ++i) { if (sz) { - auto lo = ir.ReadMemory32(address); + auto lo = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); - auto hi = ir.ReadMemory32(address); + auto hi = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); if (ir.current_location.EFlag()) { std::swap(lo, hi); } ir.SetExtendedRegister(d + i, ir.Pack2x32To1x64(lo, hi)); } else { - const auto res = ir.ReadMemory32(address); + const auto res = ir.ReadMemory32(address, IR::AccType::ATOMIC); ir.SetExtendedRegister(d + i, res); address = ir.Add(address, ir.Imm32(4)); } @@ -1232,12 +1232,12 @@ bool TranslatorVisitor::vfp_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8> auto hi = ir.MostSignificantWord(reg_d).result; if (ir.current_location.EFlag()) std::swap(lo, hi); - ir.WriteMemory32(address, lo); + ir.WriteMemory32(address, lo, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); - ir.WriteMemory32(address, hi); + ir.WriteMemory32(address, hi, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } else { - ir.WriteMemory32(address, ir.GetExtendedRegister(d + i)); + ir.WriteMemory32(address, ir.GetExtendedRegister(d + i), IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } } @@ -1258,14 +1258,14 @@ bool TranslatorVisitor::vfp_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bo const auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32)); if (sz) { - auto lo = ir.ReadMemory32(address); - auto hi = ir.ReadMemory32(ir.Add(address, ir.Imm32(4))); + auto lo = ir.ReadMemory32(address, IR::AccType::ATOMIC); + auto hi = ir.ReadMemory32(ir.Add(address, ir.Imm32(4)), IR::AccType::ATOMIC); if (ir.current_location.EFlag()) { std::swap(lo, hi); } ir.SetExtendedRegister(d, ir.Pack2x32To1x64(lo, hi)); } else { - ir.SetExtendedRegister(d, ir.ReadMemory32(address)); + ir.SetExtendedRegister(d, ir.ReadMemory32(address, IR::AccType::ATOMIC)); } return true; @@ -1289,10 +1289,10 @@ bool TranslatorVisitor::vfp_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bo if (ir.current_location.EFlag()) { std::swap(lo, hi); } - ir.WriteMemory32(address, lo); - ir.WriteMemory32(ir.Add(address, ir.Imm32(4)), hi); + ir.WriteMemory32(address, lo, IR::AccType::ATOMIC); + ir.WriteMemory32(ir.Add(address, ir.Imm32(4)), hi, IR::AccType::ATOMIC); } else { - ir.WriteMemory32(address, ir.GetExtendedRegister(d)); + ir.WriteMemory32(address, ir.GetExtendedRegister(d), IR::AccType::ATOMIC); } return true; @@ -1341,9 +1341,9 @@ bool TranslatorVisitor::vfp_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, R std::swap(word1, word2); } - ir.WriteMemory32(address, word1); + ir.WriteMemory32(address, word1, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); - ir.WriteMemory32(address, word2); + ir.WriteMemory32(address, word2, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } @@ -1386,7 +1386,7 @@ bool TranslatorVisitor::vfp_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, R } for (size_t i = 0; i < regs; i++) { const auto word = ir.GetExtendedRegister(d + i); - ir.WriteMemory32(address, word); + ir.WriteMemory32(address, word, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); } @@ -1428,9 +1428,9 @@ bool TranslatorVisitor::vfp_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, R ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address); } for (size_t i = 0; i < regs; i++) { - auto word1 = ir.ReadMemory32(address); + auto word1 = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); - auto word2 = ir.ReadMemory32(address); + auto word2 = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); if (ir.current_location.EFlag()) { @@ -1478,7 +1478,7 @@ bool TranslatorVisitor::vfp_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, R ir.SetRegister(n, u ? IR::U32(ir.Add(address, ir.Imm32(imm32))) : address); } for (size_t i = 0; i < regs; i++) { - const auto word = ir.ReadMemory32(address); + const auto word = ir.ReadMemory32(address, IR::AccType::ATOMIC); address = ir.Add(address, ir.Imm32(4)); ir.SetExtendedRegister(d + i, word); } diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp index f9eb671ef..e4ea1f5e6 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp @@ -105,84 +105,84 @@ void IREmitter::ClearExclusive() { Inst(Opcode::A64ClearExclusive); } -IR::U8 IREmitter::ReadMemory8(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ReadMemory8, vaddr, IR::Value(acctype)); +IR::U8 IREmitter::ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ReadMemory8, vaddr, IR::Value{acc_type}); } -IR::U16 IREmitter::ReadMemory16(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ReadMemory16, vaddr, IR::Value(acctype)); +IR::U16 IREmitter::ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ReadMemory16, vaddr, IR::Value{acc_type}); } -IR::U32 IREmitter::ReadMemory32(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ReadMemory32, vaddr, IR::Value(acctype)); +IR::U32 IREmitter::ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ReadMemory32, vaddr, IR::Value{acc_type}); } -IR::U64 IREmitter::ReadMemory64(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ReadMemory64, vaddr, IR::Value(acctype)); +IR::U64 IREmitter::ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ReadMemory64, vaddr, IR::Value{acc_type}); } -IR::U128 IREmitter::ReadMemory128(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ReadMemory128, vaddr, IR::Value(acctype)); +IR::U128 IREmitter::ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ReadMemory128, vaddr, IR::Value{acc_type}); } -IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveReadMemory8, vaddr, IR::Value(acctype)); +IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveReadMemory8, vaddr, IR::Value{acc_type}); } -IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveReadMemory16, vaddr, IR::Value(acctype)); +IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveReadMemory16, vaddr, IR::Value{acc_type}); } -IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveReadMemory32, vaddr, IR::Value(acctype)); +IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveReadMemory32, vaddr, IR::Value{acc_type}); } -IR::U64 IREmitter::ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveReadMemory64, vaddr, IR::Value(acctype)); +IR::U64 IREmitter::ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveReadMemory64, vaddr, IR::Value{acc_type}); } -IR::U128 IREmitter::ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveReadMemory128, vaddr, IR::Value(acctype)); +IR::U128 IREmitter::ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveReadMemory128, vaddr, IR::Value{acc_type}); } -void IREmitter::WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccessType acctype) { - Inst(Opcode::A64WriteMemory8, vaddr, value, IR::Value(acctype)); +void IREmitter::WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) { + Inst(Opcode::A64WriteMemory8, vaddr, value, IR::Value{acc_type}); } -void IREmitter::WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccessType acctype) { - Inst(Opcode::A64WriteMemory16, vaddr, value, IR::Value(acctype)); +void IREmitter::WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) { + Inst(Opcode::A64WriteMemory16, vaddr, value, IR::Value{acc_type}); } -void IREmitter::WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccessType acctype) { - Inst(Opcode::A64WriteMemory32, vaddr, value, IR::Value(acctype)); +void IREmitter::WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) { + Inst(Opcode::A64WriteMemory32, vaddr, value, IR::Value{acc_type}); } -void IREmitter::WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccessType acctype) { - Inst(Opcode::A64WriteMemory64, vaddr, value, IR::Value(acctype)); +void IREmitter::WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) { + Inst(Opcode::A64WriteMemory64, vaddr, value, IR::Value{acc_type}); } -void IREmitter::WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccessType acctype) { - Inst(Opcode::A64WriteMemory128, vaddr, value, IR::Value(acctype)); +void IREmitter::WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) { + Inst(Opcode::A64WriteMemory128, vaddr, value, IR::Value{acc_type}); } -IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveWriteMemory8, vaddr, value, IR::Value(acctype)); +IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveWriteMemory8, vaddr, value, IR::Value{acc_type}); } -IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveWriteMemory16, vaddr, value, IR::Value(acctype)); +IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveWriteMemory16, vaddr, value, IR::Value{acc_type}); } -IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveWriteMemory32, vaddr, value, IR::Value(acctype)); +IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveWriteMemory32, vaddr, value, IR::Value{acc_type}); } -IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveWriteMemory64, vaddr, value, IR::Value(acctype)); +IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveWriteMemory64, vaddr, value, IR::Value{acc_type}); } -IR::U32 IREmitter::ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccessType acctype) { - return Inst(Opcode::A64ExclusiveWriteMemory128, vaddr, value, IR::Value(acctype)); +IR::U32 IREmitter::ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) { + return Inst(Opcode::A64ExclusiveWriteMemory128, vaddr, value, IR::Value{acc_type}); } IR::U32 IREmitter::GetW(Reg reg) { diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h b/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h index ba76f9c6a..56ad7673e 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h +++ b/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h @@ -56,26 +56,26 @@ public: void SetTPIDR(const IR::U64& value); void ClearExclusive(); - IR::U8 ReadMemory8(const IR::U64& vaddr, IR::AccessType acctype); - IR::U16 ReadMemory16(const IR::U64& vaddr, IR::AccessType acctype); - IR::U32 ReadMemory32(const IR::U64& vaddr, IR::AccessType acctype); - IR::U64 ReadMemory64(const IR::U64& vaddr, IR::AccessType acctype); - IR::U128 ReadMemory128(const IR::U64& vaddr, IR::AccessType acctype); - IR::U8 ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccessType acctype); - IR::U16 ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccessType acctype); - IR::U32 ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccessType acctype); - IR::U64 ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccessType acctype); - IR::U128 ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccessType acctype); - void WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccessType acctype); - void WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccessType acctype); - void WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccessType acctype); - void WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccessType acctype); - void WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccessType acctype); - IR::U32 ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccessType acctype); - IR::U32 ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccessType acctype); - IR::U32 ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccessType acctype); - IR::U32 ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccessType acctype); - IR::U32 ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccessType acctype); + IR::U8 ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type); + IR::U16 ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type); + IR::U32 ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type); + IR::U64 ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type); + IR::U128 ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type); + IR::U8 ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type); + IR::U16 ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type); + IR::U32 ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type); + IR::U64 ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type); + IR::U128 ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type); + void WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type); + void WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type); + void WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type); + void WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type); + void WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type); + IR::U32 ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type); IR::U32 GetW(Reg source_reg); IR::U64 GetX(Reg source_reg); diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp index f9dd83804..24607ef74 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp @@ -217,74 +217,74 @@ void TranslatorVisitor::Vpart_scalar(size_t bitsize, Vec vec, size_t part, IR::U } } -IR::UAnyU128 TranslatorVisitor::Mem(IR::U64 address, size_t bytesize, IR::AccessType acctype) { +IR::UAnyU128 TranslatorVisitor::Mem(IR::U64 address, size_t bytesize, IR::AccType acc_type) { switch (bytesize) { case 1: - return ir.ReadMemory8(address, acctype); + return ir.ReadMemory8(address, acc_type); case 2: - return ir.ReadMemory16(address, acctype); + return ir.ReadMemory16(address, acc_type); case 4: - return ir.ReadMemory32(address, acctype); + return ir.ReadMemory32(address, acc_type); case 8: - return ir.ReadMemory64(address, acctype); + return ir.ReadMemory64(address, acc_type); case 16: - return ir.ReadMemory128(address, acctype); + return ir.ReadMemory128(address, acc_type); default: ASSERT_FALSE("Invalid bytesize parameter {}", bytesize); } } -void TranslatorVisitor::Mem(IR::U64 address, size_t bytesize, IR::AccessType acctype, IR::UAnyU128 value) { +void TranslatorVisitor::Mem(IR::U64 address, size_t bytesize, IR::AccType acc_type, IR::UAnyU128 value) { switch (bytesize) { case 1: - ir.WriteMemory8(address, value, acctype); + ir.WriteMemory8(address, value, acc_type); return; case 2: - ir.WriteMemory16(address, value, acctype); + ir.WriteMemory16(address, value, acc_type); return; case 4: - ir.WriteMemory32(address, value, acctype); + ir.WriteMemory32(address, value, acc_type); return; case 8: - ir.WriteMemory64(address, value, acctype); + ir.WriteMemory64(address, value, acc_type); return; case 16: - ir.WriteMemory128(address, value, acctype); + ir.WriteMemory128(address, value, acc_type); return; default: ASSERT_FALSE("Invalid bytesize parameter {}", bytesize); } } -IR::UAnyU128 TranslatorVisitor::ExclusiveMem(IR::U64 address, size_t bytesize, IR::AccessType acctype) { +IR::UAnyU128 TranslatorVisitor::ExclusiveMem(IR::U64 address, size_t bytesize, IR::AccType acc_type) { switch (bytesize) { case 1: - return ir.ExclusiveReadMemory8(address, acctype); + return ir.ExclusiveReadMemory8(address, acc_type); case 2: - return ir.ExclusiveReadMemory16(address, acctype); + return ir.ExclusiveReadMemory16(address, acc_type); case 4: - return ir.ExclusiveReadMemory32(address, acctype); + return ir.ExclusiveReadMemory32(address, acc_type); case 8: - return ir.ExclusiveReadMemory64(address, acctype); + return ir.ExclusiveReadMemory64(address, acc_type); case 16: - return ir.ExclusiveReadMemory128(address, acctype); + return ir.ExclusiveReadMemory128(address, acc_type); default: ASSERT_FALSE("Invalid bytesize parameter {}", bytesize); } } -IR::U32 TranslatorVisitor::ExclusiveMem(IR::U64 address, size_t bytesize, IR::AccessType acctype, IR::UAnyU128 value) { +IR::U32 TranslatorVisitor::ExclusiveMem(IR::U64 address, size_t bytesize, IR::AccType acc_type, IR::UAnyU128 value) { switch (bytesize) { case 1: - return ir.ExclusiveWriteMemory8(address, value, acctype); + return ir.ExclusiveWriteMemory8(address, value, acc_type); case 2: - return ir.ExclusiveWriteMemory16(address, value, acctype); + return ir.ExclusiveWriteMemory16(address, value, acc_type); case 4: - return ir.ExclusiveWriteMemory32(address, value, acctype); + return ir.ExclusiveWriteMemory32(address, value, acc_type); case 8: - return ir.ExclusiveWriteMemory64(address, value, acctype); + return ir.ExclusiveWriteMemory64(address, value, acc_type); case 16: - return ir.ExclusiveWriteMemory128(address, value, acctype); + return ir.ExclusiveWriteMemory128(address, value, acc_type); default: ASSERT_FALSE("Invalid bytesize parameter {}", bytesize); } diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.h b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.h index c83c962d1..86bc534d5 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.h +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.h @@ -55,10 +55,10 @@ struct TranslatorVisitor final { IR::UAny Vpart_scalar(size_t bitsize, Vec vec, size_t part); void Vpart_scalar(size_t bitsize, Vec vec, size_t part, IR::UAny value); - IR::UAnyU128 Mem(IR::U64 address, size_t size, IR::AccessType acctype); - void Mem(IR::U64 address, size_t size, IR::AccessType acctype, IR::UAnyU128 value); - IR::UAnyU128 ExclusiveMem(IR::U64 address, size_t size, IR::AccessType acctype); - IR::U32 ExclusiveMem(IR::U64 address, size_t size, IR::AccessType acctype, IR::UAnyU128 value); + IR::UAnyU128 Mem(IR::U64 address, size_t size, IR::AccType acctype); + void Mem(IR::U64 address, size_t size, IR::AccType acctype, IR::UAnyU128 value); + IR::UAnyU128 ExclusiveMem(IR::U64 address, size_t size, IR::AccType acctype); + IR::U32 ExclusiveMem(IR::U64 address, size_t size, IR::AccType acctype, IR::UAnyU128 value); IR::U32U64 SignExtend(IR::UAny value, size_t to_size); IR::U32U64 ZeroExtend(IR::UAny value, size_t to_size); diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_exclusive.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_exclusive.cpp index 804c53f86..0e67e11b4 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_exclusive.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_exclusive.cpp @@ -12,7 +12,7 @@ namespace Dynarmic::A64 { static bool ExclusiveSharedDecodeAndOperation(TranslatorVisitor& v, bool pair, size_t size, bool L, bool o0, std::optional Rs, std::optional Rt2, Reg Rn, Reg Rt) { // Shared Decode - const auto acctype = o0 ? IR::AccessType::ORDERED : IR::AccessType::ATOMIC; + const auto acctype = o0 ? IR::AccType::ORDERED : IR::AccType::ATOMIC; const auto memop = L ? IR::MemOp::LOAD : IR::MemOp::STORE; const size_t elsize = 8 << size; const size_t regsize = elsize == 64 ? 64 : 32; @@ -142,7 +142,7 @@ bool TranslatorVisitor::LDAXP(Imm<1> sz, Reg Rt2, Reg Rn, Reg Rt) { static bool OrderedSharedDecodeAndOperation(TranslatorVisitor& v, size_t size, bool L, bool o0, Reg Rn, Reg Rt) { // Shared Decode - const auto acctype = !o0 ? IR::AccessType::LIMITEDORDERED : IR::AccessType::ORDERED; + const auto acctype = !o0 ? IR::AccType::LIMITEDORDERED : IR::AccType::ORDERED; const auto memop = L ? IR::MemOp::LOAD : IR::MemOp::STORE; const size_t elsize = 8 << size; const size_t regsize = elsize == 64 ? 64 : 32; diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_load_literal.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_load_literal.cpp index a4b2beae3..995aba425 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_load_literal.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_load_literal.cpp @@ -12,7 +12,7 @@ bool TranslatorVisitor::LDR_lit_gen(bool opc_0, Imm<19> imm19, Reg Rt) { const s64 offset = concatenate(imm19, Imm<2>{0}).SignExtend(); const u64 address = ir.PC() + offset; - const auto data = Mem(ir.Imm64(address), size, IR::AccessType::NORMAL); + const auto data = Mem(ir.Imm64(address), size, IR::AccType::NORMAL); X(8 * size, Rt, data); return true; @@ -26,7 +26,7 @@ bool TranslatorVisitor::LDR_lit_fpsimd(Imm<2> opc, Imm<19> imm19, Vec Vt) { const u64 size = 4 << opc.ZeroExtend(); const u64 offset = imm19.SignExtend() << 2; const IR::U64 address = ir.Imm64(ir.PC() + offset); - const IR::UAnyU128 data = Mem(address, size, IR::AccessType::VEC); + const IR::UAnyU128 data = Mem(address, size, IR::AccType::VEC); if (size == 16) { V(128, Vt, data); @@ -39,7 +39,7 @@ bool TranslatorVisitor::LDR_lit_fpsimd(Imm<2> opc, Imm<19> imm19, Vec Vt) { bool TranslatorVisitor::LDRSW_lit(Imm<19> imm19, Reg Rt) { const s64 offset = concatenate(imm19, Imm<2>{0}).SignExtend(); const u64 address = ir.PC() + offset; - const auto data = Mem(ir.Imm64(address), 4, IR::AccessType::NORMAL); + const auto data = Mem(ir.Imm64(address), 4, IR::AccType::NORMAL); X(64, Rt, ir.SignExtendWordToLong(data)); return true; diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_multiple_structures.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_multiple_structures.cpp index 0c1a2d7d1..77c57a965 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_multiple_structures.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_multiple_structures.cpp @@ -67,11 +67,11 @@ static bool SharedDecodeAndOperation(TranslatorVisitor& v, bool wback, IR::MemOp for (size_t r = 0; r < rpt; r++) { const Vec tt = static_cast((VecNumber(Vt) + r) % 32); if (memop == IR::MemOp::LOAD) { - const IR::UAnyU128 vec = v.Mem(v.ir.Add(address, offs), ebytes * elements, IR::AccessType::VEC); + const IR::UAnyU128 vec = v.Mem(v.ir.Add(address, offs), ebytes * elements, IR::AccType::VEC); v.V_scalar(datasize, tt, vec); } else { const IR::UAnyU128 vec = v.V_scalar(datasize, tt); - v.Mem(v.ir.Add(address, offs), ebytes * elements, IR::AccessType::VEC, vec); + v.Mem(v.ir.Add(address, offs), ebytes * elements, IR::AccType::VEC, vec); } offs = v.ir.Add(offs, v.ir.Imm64(ebytes * elements)); } @@ -80,12 +80,12 @@ static bool SharedDecodeAndOperation(TranslatorVisitor& v, bool wback, IR::MemOp for (size_t s = 0; s < selem; s++) { const Vec tt = static_cast((VecNumber(Vt) + s) % 32); if (memop == IR::MemOp::LOAD) { - const IR::UAny elem = v.Mem(v.ir.Add(address, offs), ebytes, IR::AccessType::VEC); + const IR::UAny elem = v.Mem(v.ir.Add(address, offs), ebytes, IR::AccType::VEC); const IR::U128 vec = v.ir.VectorSetElement(esize, v.V(datasize, tt), e, elem); v.V(datasize, tt, vec); } else { const IR::UAny elem = v.ir.VectorGetElement(esize, v.V(datasize, tt), e); - v.Mem(v.ir.Add(address, offs), ebytes, IR::AccessType::VEC, elem); + v.Mem(v.ir.Add(address, offs), ebytes, IR::AccType::VEC, elem); } offs = v.ir.Add(offs, v.ir.Imm64(ebytes)); } diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_immediate.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_immediate.cpp index 5b17b3353..d939c45f2 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_immediate.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_immediate.cpp @@ -43,11 +43,11 @@ static bool LoadStoreRegisterImmediate(TranslatorVisitor& v, bool wback, bool po switch (memop) { case IR::MemOp::STORE: { const auto data = v.X(datasize, Rt); - v.Mem(address, datasize / 8, IR::AccessType::NORMAL, data); + v.Mem(address, datasize / 8, IR::AccType::NORMAL, data); break; } case IR::MemOp::LOAD: { - const auto data = v.Mem(address, datasize / 8, IR::AccessType::NORMAL); + const auto data = v.Mem(address, datasize / 8, IR::AccType::NORMAL); if (signed_) { v.X(regsize, Rt, v.SignExtend(data, regsize)); } else { @@ -115,7 +115,7 @@ bool TranslatorVisitor::PRFM_unscaled_imm([[maybe_unused]] Imm<9> imm9, [[maybe_ } static bool LoadStoreSIMD(TranslatorVisitor& v, bool wback, bool postindex, size_t scale, u64 offset, IR::MemOp memop, Reg Rn, Vec Vt) { - const auto acctype = IR::AccessType::VEC; + const auto acctype = IR::AccType::VEC; const size_t datasize = 8 << scale; IR::U64 address; diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_pair.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_pair.cpp index acbdf2e48..4c81564f7 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_pair.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_pair.cpp @@ -46,13 +46,13 @@ bool TranslatorVisitor::STP_LDP_gen(Imm<2> opc, bool not_postindex, bool wback, case IR::MemOp::STORE: { const IR::U32U64 data1 = X(datasize, Rt); const IR::U32U64 data2 = X(datasize, Rt2); - Mem(address, dbytes, IR::AccessType::NORMAL, data1); - Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, IR::AccessType::NORMAL, data2); + Mem(address, dbytes, IR::AccType::NORMAL, data1); + Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, IR::AccType::NORMAL, data2); break; } case IR::MemOp::LOAD: { - const IR::U32U64 data1 = Mem(address, dbytes, IR::AccessType::NORMAL); - const IR::U32U64 data2 = Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, IR::AccessType::NORMAL); + const IR::U32U64 data1 = Mem(address, dbytes, IR::AccType::NORMAL); + const IR::U32U64 data2 = Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, IR::AccType::NORMAL); if (signed_) { X(64, Rt, SignExtend(data1, 64)); X(64, Rt2, SignExtend(data2, 64)); @@ -117,13 +117,13 @@ bool TranslatorVisitor::STP_LDP_fpsimd(Imm<2> opc, bool not_postindex, bool wbac data1 = ir.VectorGetElement(datasize, data1, 0); data2 = ir.VectorGetElement(datasize, data2, 0); } - Mem(address, dbytes, IR::AccessType::VEC, data1); - Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, IR::AccessType::VEC, data2); + Mem(address, dbytes, IR::AccType::VEC, data1); + Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, IR::AccType::VEC, data2); break; } case IR::MemOp::LOAD: { - IR::UAnyU128 data1 = Mem(address, dbytes, IR::AccessType::VEC); - IR::UAnyU128 data2 = Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, IR::AccessType::VEC); + IR::UAnyU128 data1 = Mem(address, dbytes, IR::AccType::VEC); + IR::UAnyU128 data2 = Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, IR::AccType::VEC); if (datasize != 128) { data1 = ir.ZeroExtendToQuad(data1); data2 = ir.ZeroExtendToQuad(data2); diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_register_offset.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_register_offset.cpp index 4c2bfbc49..979109586 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_register_offset.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_register_offset.cpp @@ -10,7 +10,7 @@ namespace Dynarmic::A64 { static bool RegSharedDecodeAndOperation(TranslatorVisitor& v, size_t scale, u8 shift, Imm<2> size, Imm<1> opc_1, Imm<1> opc_0, Reg Rm, Imm<3> option, Reg Rn, Reg Rt) { // Shared Decode - const auto acctype = IR::AccessType::NORMAL; + const auto acctype = IR::AccType::NORMAL; IR::MemOp memop; size_t regsize = 64; bool signed_ = false; @@ -96,7 +96,7 @@ bool TranslatorVisitor::LDRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> optio static bool VecSharedDecodeAndOperation(TranslatorVisitor& v, size_t scale, u8 shift, Imm<1> opc_0, Reg Rm, Imm<3> option, Reg Rn, Vec Vt) { // Shared Decode - const auto acctype = IR::AccessType::VEC; + const auto acctype = IR::AccType::VEC; const auto memop = opc_0 == 1 ? IR::MemOp::LOAD : IR::MemOp::STORE; const size_t datasize = 8 << scale; diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_unprivileged.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_unprivileged.cpp index 6d12f955e..d3f4194ff 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_unprivileged.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_register_unprivileged.cpp @@ -9,7 +9,7 @@ namespace Dynarmic::A64 { static bool StoreRegister(TranslatorVisitor& v, const size_t datasize, const Imm<9> imm9, const Reg Rn, const Reg Rt) { const u64 offset = imm9.SignExtend(); - const auto acctype = IR::AccessType::UNPRIV; + const auto acctype = IR::AccType::UNPRIV; IR::U64 address; if (Rn == Reg::SP) { @@ -27,7 +27,7 @@ static bool StoreRegister(TranslatorVisitor& v, const size_t datasize, const Imm static bool LoadRegister(TranslatorVisitor& v, const size_t datasize, const Imm<9> imm9, const Reg Rn, const Reg Rt) { const u64 offset = imm9.SignExtend(); - const auto acctype = IR::AccessType::UNPRIV; + const auto acctype = IR::AccType::UNPRIV; IR::U64 address; if (Rn == Reg::SP) { @@ -47,7 +47,7 @@ static bool LoadRegister(TranslatorVisitor& v, const size_t datasize, const Imm< static bool LoadRegisterSigned(TranslatorVisitor& v, const size_t datasize, const Imm<2> opc, const Imm<9> imm9, const Reg Rn, const Reg Rt) { const u64 offset = imm9.SignExtend(); - const auto acctype = IR::AccessType::UNPRIV; + const auto acctype = IR::AccType::UNPRIV; IR::MemOp memop; bool is_signed; @@ -131,7 +131,7 @@ bool TranslatorVisitor::LDTRSH(Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt) { bool TranslatorVisitor::LDTRSW(Imm<9> imm9, Reg Rn, Reg Rt) { const u64 offset = imm9.SignExtend(); - const auto acctype = IR::AccessType::UNPRIV; + const auto acctype = IR::AccType::UNPRIV; IR::U64 address; if (Rn == Reg::SP) { diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_single_structure.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_single_structure.cpp index cbbc4de9d..b4bc84294 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_single_structure.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/load_store_single_structure.cpp @@ -62,7 +62,7 @@ static bool SharedDecodeAndOperation(TranslatorVisitor& v, bool wback, IR::MemOp if (replicate) { for (size_t s = 0; s < selem; s++) { const Vec tt = static_cast((VecNumber(Vt) + s) % 32); - const IR::UAnyU128 element = v.Mem(v.ir.Add(address, offs), ebytes, IR::AccessType::VEC); + const IR::UAnyU128 element = v.Mem(v.ir.Add(address, offs), ebytes, IR::AccType::VEC); const IR::U128 broadcasted_element = v.ir.VectorBroadcast(esize, element); v.V(datasize, tt, broadcasted_element); @@ -75,12 +75,12 @@ static bool SharedDecodeAndOperation(TranslatorVisitor& v, bool wback, IR::MemOp const IR::U128 rval = v.V(128, tt); if (memop == IR::MemOp::LOAD) { - const IR::UAny elem = v.Mem(v.ir.Add(address, offs), ebytes, IR::AccessType::VEC); + const IR::UAny elem = v.Mem(v.ir.Add(address, offs), ebytes, IR::AccType::VEC); const IR::U128 vec = v.ir.VectorSetElement(esize, rval, index, elem); v.V(128, tt, vec); } else { const IR::UAny elem = v.ir.VectorGetElement(esize, rval, index); - v.Mem(v.ir.Add(address, offs), ebytes, IR::AccessType::VEC, elem); + v.Mem(v.ir.Add(address, offs), ebytes, IR::AccType::VEC, elem); } offs = v.ir.Add(offs, v.ir.Imm64(ebytes)); } diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/sys_ic.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/sys_ic.cpp index 35fa24083..3c91168ca 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/sys_ic.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/sys_ic.cpp @@ -9,17 +9,23 @@ namespace Dynarmic::A64 { bool TranslatorVisitor::IC_IALLU() { ir.InstructionCacheOperationRaised(InstructionCacheOperation::InvalidateAllToPoU, ir.Imm64(0)); - return true; + ir.SetPC(ir.Imm64(ir.current_location->PC() + 4)); + ir.SetTerm(IR::Term::CheckHalt{IR::Term::ReturnToDispatch{}}); + return false; } bool TranslatorVisitor::IC_IALLUIS() { ir.InstructionCacheOperationRaised(InstructionCacheOperation::InvalidateAllToPoUInnerSharable, ir.Imm64(0)); - return true; + ir.SetPC(ir.Imm64(ir.current_location->PC() + 4)); + ir.SetTerm(IR::Term::CheckHalt{IR::Term::ReturnToDispatch{}}); + return false; } bool TranslatorVisitor::IC_IVAU(Reg Rt) { ir.InstructionCacheOperationRaised(InstructionCacheOperation::InvalidateByVAToPoU, X(64, Rt)); - return true; + ir.SetPC(ir.Imm64(ir.current_location->PC() + 4)); + ir.SetTerm(IR::Term::CheckHalt{IR::Term::ReturnToDispatch{}}); + return false; } } // namespace Dynarmic::A64 diff --git a/externals/dynarmic/src/dynarmic/ir/acc_type.h b/externals/dynarmic/src/dynarmic/ir/acc_type.h new file mode 100755 index 000000000..f259660b6 --- /dev/null +++ b/externals/dynarmic/src/dynarmic/ir/acc_type.h @@ -0,0 +1,29 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2022 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +namespace Dynarmic::IR { + +enum class AccType { + NORMAL, + VEC, + STREAM, + VECSTREAM, + ATOMIC, + ORDERED, + ORDEREDRW, + LIMITEDORDERED, + UNPRIV, + IFETCH, + PTW, + DC, + IC, + DCZVA, + AT, + SWAP, // TODO: Remove +}; + +} // namespace Dynarmic::IR diff --git a/externals/dynarmic/src/dynarmic/ir/ir_emitter.h b/externals/dynarmic/src/dynarmic/ir/ir_emitter.h index 75b614b7f..fb8d957cd 100755 --- a/externals/dynarmic/src/dynarmic/ir/ir_emitter.h +++ b/externals/dynarmic/src/dynarmic/ir/ir_emitter.h @@ -6,7 +6,7 @@ #pragma once #include "dynarmic/common/common_types.h" -#include "dynarmic/ir/access_type.h" +#include "dynarmic/ir/acc_type.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/location_descriptor.h" #include "dynarmic/ir/terminal.h" diff --git a/externals/dynarmic/src/dynarmic/ir/opcodes.cpp b/externals/dynarmic/src/dynarmic/ir/opcodes.cpp index 8fc6c4686..2741e5fbd 100755 --- a/externals/dynarmic/src/dynarmic/ir/opcodes.cpp +++ b/externals/dynarmic/src/dynarmic/ir/opcodes.cpp @@ -43,7 +43,7 @@ constexpr Type CoprocInfo = Type::CoprocInfo; constexpr Type NZCV = Type::NZCVFlags; constexpr Type Cond = Type::Cond; constexpr Type Table = Type::Table; -constexpr Type AccessType = Type::AccessType; +constexpr Type AccType = Type::AccType; static const std::array opcode_info{ #define OPCODE(name, type, ...) Meta{#name, type, {__VA_ARGS__}}, diff --git a/externals/dynarmic/src/dynarmic/ir/opcodes.inc b/externals/dynarmic/src/dynarmic/ir/opcodes.inc index 2a6f8f593..797193068 100755 --- a/externals/dynarmic/src/dynarmic/ir/opcodes.inc +++ b/externals/dynarmic/src/dynarmic/ir/opcodes.inc @@ -688,45 +688,45 @@ OPCODE(FPVectorToUnsignedFixed64, U128, U128 // A32 Memory access A32OPC(ClearExclusive, Void, ) -A32OPC(ReadMemory8, U8, U32 ) -A32OPC(ReadMemory16, U16, U32 ) -A32OPC(ReadMemory32, U32, U32 ) -A32OPC(ReadMemory64, U64, U32 ) -A32OPC(ExclusiveReadMemory8, U8, U32 ) -A32OPC(ExclusiveReadMemory16, U16, U32 ) -A32OPC(ExclusiveReadMemory32, U32, U32 ) -A32OPC(ExclusiveReadMemory64, U64, U32 ) -A32OPC(WriteMemory8, Void, U32, U8 ) -A32OPC(WriteMemory16, Void, U32, U16 ) -A32OPC(WriteMemory32, Void, U32, U32 ) -A32OPC(WriteMemory64, Void, U32, U64 ) -A32OPC(ExclusiveWriteMemory8, U32, U32, U8 ) -A32OPC(ExclusiveWriteMemory16, U32, U32, U16 ) -A32OPC(ExclusiveWriteMemory32, U32, U32, U32 ) -A32OPC(ExclusiveWriteMemory64, U32, U32, U64 ) +A32OPC(ReadMemory8, U8, U32, AccType ) +A32OPC(ReadMemory16, U16, U32, AccType ) +A32OPC(ReadMemory32, U32, U32, AccType ) +A32OPC(ReadMemory64, U64, U32, AccType ) +A32OPC(ExclusiveReadMemory8, U8, U32, AccType ) +A32OPC(ExclusiveReadMemory16, U16, U32, AccType ) +A32OPC(ExclusiveReadMemory32, U32, U32, AccType ) +A32OPC(ExclusiveReadMemory64, U64, U32, AccType ) +A32OPC(WriteMemory8, Void, U32, U8, AccType ) +A32OPC(WriteMemory16, Void, U32, U16, AccType ) +A32OPC(WriteMemory32, Void, U32, U32, AccType ) +A32OPC(WriteMemory64, Void, U32, U64, AccType ) +A32OPC(ExclusiveWriteMemory8, U32, U32, U8, AccType ) +A32OPC(ExclusiveWriteMemory16, U32, U32, U16, AccType ) +A32OPC(ExclusiveWriteMemory32, U32, U32, U32, AccType ) +A32OPC(ExclusiveWriteMemory64, U32, U32, U64, AccType ) // A64 Memory access A64OPC(ClearExclusive, Void, ) -A64OPC(ReadMemory8, U8, U64, AccessType ) -A64OPC(ReadMemory16, U16, U64, AccessType ) -A64OPC(ReadMemory32, U32, U64, AccessType ) -A64OPC(ReadMemory64, U64, U64, AccessType ) -A64OPC(ReadMemory128, U128, U64, AccessType ) -A64OPC(ExclusiveReadMemory8, U8, U64, AccessType ) -A64OPC(ExclusiveReadMemory16, U16, U64, AccessType ) -A64OPC(ExclusiveReadMemory32, U32, U64, AccessType ) -A64OPC(ExclusiveReadMemory64, U64, U64, AccessType ) -A64OPC(ExclusiveReadMemory128, U128, U64, AccessType ) -A64OPC(WriteMemory8, Void, U64, U8, AccessType ) -A64OPC(WriteMemory16, Void, U64, U16, AccessType ) -A64OPC(WriteMemory32, Void, U64, U32, AccessType ) -A64OPC(WriteMemory64, Void, U64, U64, AccessType ) -A64OPC(WriteMemory128, Void, U64, U128, AccessType ) -A64OPC(ExclusiveWriteMemory8, U32, U64, U8, AccessType ) -A64OPC(ExclusiveWriteMemory16, U32, U64, U16, AccessType ) -A64OPC(ExclusiveWriteMemory32, U32, U64, U32, AccessType ) -A64OPC(ExclusiveWriteMemory64, U32, U64, U64, AccessType ) -A64OPC(ExclusiveWriteMemory128, U32, U64, U128, AccessType ) +A64OPC(ReadMemory8, U8, U64, AccType ) +A64OPC(ReadMemory16, U16, U64, AccType ) +A64OPC(ReadMemory32, U32, U64, AccType ) +A64OPC(ReadMemory64, U64, U64, AccType ) +A64OPC(ReadMemory128, U128, U64, AccType ) +A64OPC(ExclusiveReadMemory8, U8, U64, AccType ) +A64OPC(ExclusiveReadMemory16, U16, U64, AccType ) +A64OPC(ExclusiveReadMemory32, U32, U64, AccType ) +A64OPC(ExclusiveReadMemory64, U64, U64, AccType ) +A64OPC(ExclusiveReadMemory128, U128, U64, AccType ) +A64OPC(WriteMemory8, Void, U64, U8, AccType ) +A64OPC(WriteMemory16, Void, U64, U16, AccType ) +A64OPC(WriteMemory32, Void, U64, U32, AccType ) +A64OPC(WriteMemory64, Void, U64, U64, AccType ) +A64OPC(WriteMemory128, Void, U64, U128, AccType ) +A64OPC(ExclusiveWriteMemory8, U32, U64, U8, AccType ) +A64OPC(ExclusiveWriteMemory16, U32, U64, U16, AccType ) +A64OPC(ExclusiveWriteMemory32, U32, U64, U32, AccType ) +A64OPC(ExclusiveWriteMemory64, U32, U64, U64, AccType ) +A64OPC(ExclusiveWriteMemory128, U32, U64, U128, AccType ) // Coprocessor A32OPC(CoprocInternalOperation, Void, CoprocInfo ) diff --git a/externals/dynarmic/src/dynarmic/ir/opt/a64_callback_config_pass.cpp b/externals/dynarmic/src/dynarmic/ir/opt/a64_callback_config_pass.cpp index f8e968d5b..f90370712 100755 --- a/externals/dynarmic/src/dynarmic/ir/opt/a64_callback_config_pass.cpp +++ b/externals/dynarmic/src/dynarmic/ir/opt/a64_callback_config_pass.cpp @@ -32,19 +32,19 @@ void A64CallbackConfigPass(IR::Block& block, const A64::UserConfig& conf) { const IR::U128 zero_u128 = ir.ZeroExtendToQuad(ir.Imm64(0)); while (bytes >= 16) { - ir.WriteMemory128(addr, zero_u128, IR::AccessType::DCZVA); + ir.WriteMemory128(addr, zero_u128, IR::AccType::DCZVA); addr = ir.Add(addr, ir.Imm64(16)); bytes -= 16; } while (bytes >= 8) { - ir.WriteMemory64(addr, ir.Imm64(0), IR::AccessType::DCZVA); + ir.WriteMemory64(addr, ir.Imm64(0), IR::AccType::DCZVA); addr = ir.Add(addr, ir.Imm64(8)); bytes -= 8; } while (bytes >= 4) { - ir.WriteMemory32(addr, ir.Imm32(0), IR::AccessType::DCZVA); + ir.WriteMemory32(addr, ir.Imm32(0), IR::AccType::DCZVA); addr = ir.Add(addr, ir.Imm64(4)); bytes -= 4; } diff --git a/externals/dynarmic/src/dynarmic/ir/type.h b/externals/dynarmic/src/dynarmic/ir/type.h index 569738aa1..35c029702 100755 --- a/externals/dynarmic/src/dynarmic/ir/type.h +++ b/externals/dynarmic/src/dynarmic/ir/type.h @@ -32,7 +32,7 @@ enum class Type { NZCVFlags = 1 << 12, Cond = 1 << 13, Table = 1 << 14, - AccessType = 1 << 15, + AccType = 1 << 15, }; constexpr Type operator|(Type a, Type b) { diff --git a/externals/dynarmic/src/dynarmic/ir/value.cpp b/externals/dynarmic/src/dynarmic/ir/value.cpp index a0cc0bbf0..8cdefa39b 100755 --- a/externals/dynarmic/src/dynarmic/ir/value.cpp +++ b/externals/dynarmic/src/dynarmic/ir/value.cpp @@ -73,8 +73,8 @@ Value::Value(Cond value) inner.imm_cond = value; } -Value::Value(AccessType value) - : type(Type::AccessType) { +Value::Value(AccType value) + : type(Type::AccType) { inner.imm_acctype = value; } @@ -183,10 +183,10 @@ Cond Value::GetCond() const { return inner.imm_cond; } -AccessType Value::GetAccType() const { +AccType Value::GetAccType() const { if (IsIdentity()) return inner.inst->GetArg(0).GetAccType(); - ASSERT(type == Type::AccessType); + ASSERT(type == Type::AccType); return inner.imm_acctype; } diff --git a/externals/dynarmic/src/dynarmic/ir/value.h b/externals/dynarmic/src/dynarmic/ir/value.h index 27df0bf3a..9e0b19c7e 100755 --- a/externals/dynarmic/src/dynarmic/ir/value.h +++ b/externals/dynarmic/src/dynarmic/ir/value.h @@ -25,7 +25,7 @@ enum class Vec; namespace Dynarmic::IR { class Inst; -enum class AccessType; +enum class AccType; enum class Cond; /** @@ -50,7 +50,7 @@ public: explicit Value(u64 value); explicit Value(CoprocessorInfo value); explicit Value(Cond value); - explicit Value(AccessType value); + explicit Value(AccType value); bool IsIdentity() const; bool IsEmpty() const; @@ -70,7 +70,7 @@ public: u64 GetU64() const; CoprocessorInfo GetCoprocInfo() const; Cond GetCond() const; - AccessType GetAccType() const; + AccType GetAccType() const; /** * Retrieves the immediate of a Value instance as a signed 64-bit value. @@ -143,7 +143,7 @@ private: u64 imm_u64; CoprocessorInfo imm_coproc; Cond imm_cond; - AccessType imm_acctype; + AccType imm_acctype; } inner; }; static_assert(sizeof(Value) <= 2 * sizeof(u64), "IR::Value should be kept small in size"); diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index d96226c41..24107f9f6 100755 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -93,17 +93,19 @@ public: static constexpr u64 ICACHE_LINE_SIZE = 64; const u64 cache_line_start = value & ~(ICACHE_LINE_SIZE - 1); - parent.InvalidateCacheRange(cache_line_start, ICACHE_LINE_SIZE); + parent.system.InvalidateCpuInstructionCacheRange(cache_line_start, ICACHE_LINE_SIZE); break; } case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoU: - parent.ClearInstructionCache(); + parent.system.InvalidateCpuInstructionCaches(); break; case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoUInnerSharable: default: LOG_DEBUG(Core_ARM, "Unprocesseed instruction cache operation: {}", op); break; } + + parent.jit->HaltExecution(); } void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index d3cbb14a9..cb47d253c 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include "shader_recompiler/backend/spirv/emit_spirv.h" #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" #include "shader_recompiler/backend/spirv/spirv_emit_context.h" diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 3c2a5e16f..aa7082978 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include #include diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 53be98ced..28f6a6184 100755 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include