From dd5dc4a807288d6b22974f576135e5723dc9974a Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Sun, 11 Apr 2021 18:10:39 +0200 Subject: [PATCH] early-access version 1584 --- README.md | 2 +- .../dynarmic/src/backend/x64/a32_emit_x64.cpp | 5 +- .../src/backend/x64/a32_interface.cpp | 1 + .../dynarmic/src/backend/x64/a64_emit_x64.cpp | 6 +- .../src/backend/x64/a64_interface.cpp | 1 + .../src/backend/x64/block_of_code.cpp | 2 +- .../dynarmic/src/backend/x64/emit_x64.cpp | 5 +- externals/dynarmic/src/backend/x64/emit_x64.h | 2 +- .../dynarmic/src/backend/x64/perf_map.cpp | 5 + .../dynarmic/src/frontend/A32/decoder/arm.inc | 204 +++++++++--------- .../src/frontend/A32/decoder/thumb32.inc | 8 +- .../impl/thumb32_load_store_dual.cpp | 61 ++++++ .../A32/translate/impl/translate_thumb.h | 4 + externals/dynarmic/tests/A32/fuzz_arm.cpp | 6 + 14 files changed, 200 insertions(+), 112 deletions(-) diff --git a/README.md b/README.md index 181417009..fd675aef4 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 1583. +This is the source code for early-access 1584. ## Legal Notice diff --git a/externals/dynarmic/src/backend/x64/a32_emit_x64.cpp b/externals/dynarmic/src/backend/x64/a32_emit_x64.cpp index 55c75bbbe..fd37a0a68 100755 --- a/externals/dynarmic/src/backend/x64/a32_emit_x64.cpp +++ b/externals/dynarmic/src/backend/x64/a32_emit_x64.cpp @@ -115,6 +115,9 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) { // Start emitting. code.align(); const u8* const entrypoint = code.getCurr(); + code.SwitchToFarCode(); + const u8* const entrypoint_far = code.getCurr(); + code.SwitchToNearCode(); EmitCondPrelude(ctx); @@ -160,7 +163,7 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) { const auto range = boost::icl::discrete_interval::closed(descriptor.PC(), end_location.PC() - 1); block_ranges.AddRange(range, descriptor); - return RegisterBlock(descriptor, entrypoint, size); + return RegisterBlock(descriptor, entrypoint, entrypoint_far, size); } void A32EmitX64::ClearCache() { diff --git a/externals/dynarmic/src/backend/x64/a32_interface.cpp b/externals/dynarmic/src/backend/x64/a32_interface.cpp index 09d9d6c76..60abb1472 100755 --- a/externals/dynarmic/src/backend/x64/a32_interface.cpp +++ b/externals/dynarmic/src/backend/x64/a32_interface.cpp @@ -90,6 +90,7 @@ struct Jit::Impl { } void ExceptionalExit() { + ClearExclusiveState(); if (!conf.wall_clock_cntpct) { const s64 ticks = jit_state.cycles_to_run - jit_state.cycles_remaining; conf.callbacks->AddTicks(ticks); diff --git a/externals/dynarmic/src/backend/x64/a64_emit_x64.cpp b/externals/dynarmic/src/backend/x64/a64_emit_x64.cpp index 20514599a..60e7fe655 100755 --- a/externals/dynarmic/src/backend/x64/a64_emit_x64.cpp +++ b/externals/dynarmic/src/backend/x64/a64_emit_x64.cpp @@ -81,6 +81,9 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) { // Start emitting. code.align(); const u8* const entrypoint = code.getCurr(); + code.SwitchToFarCode(); + const u8* const entrypoint_far = code.getCurr(); + code.SwitchToNearCode(); ASSERT(block.GetCondition() == IR::Cond::AL); @@ -126,7 +129,7 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) { const auto range = boost::icl::discrete_interval::closed(descriptor.PC(), end_location.PC() - 1); block_ranges.AddRange(range, descriptor); - return RegisterBlock(descriptor, entrypoint, size); + return RegisterBlock(descriptor, entrypoint, entrypoint_far, size); } void A64EmitX64::ClearCache() { @@ -358,6 +361,7 @@ void A64EmitX64::GenTerminalHandlers() { code.and_(code.ABI_PARAM1.cvt32(), fast_dispatch_table_mask); code.lea(code.ABI_RETURN, code.ptr[code.ABI_PARAM1 + code.ABI_PARAM2]); code.ret(); + PerfMapRegister(fast_dispatch_table_lookup, code.getCurr(), "a64_fast_dispatch_table_lookup"); } } diff --git a/externals/dynarmic/src/backend/x64/a64_interface.cpp b/externals/dynarmic/src/backend/x64/a64_interface.cpp index acde3f34a..9bce1c7e1 100755 --- a/externals/dynarmic/src/backend/x64/a64_interface.cpp +++ b/externals/dynarmic/src/backend/x64/a64_interface.cpp @@ -88,6 +88,7 @@ public: } void ExceptionalExit() { + ClearExclusiveState(); if (!conf.wall_clock_cntpct) { const s64 ticks = jit_state.cycles_to_run - jit_state.cycles_remaining; conf.callbacks->AddTicks(ticks); diff --git a/externals/dynarmic/src/backend/x64/block_of_code.cpp b/externals/dynarmic/src/backend/x64/block_of_code.cpp index 8b96b8afc..59044e521 100755 --- a/externals/dynarmic/src/backend/x64/block_of_code.cpp +++ b/externals/dynarmic/src/backend/x64/block_of_code.cpp @@ -120,7 +120,7 @@ size_t BlockOfCode::SpaceRemaining() const { return 0; if (current_far_ptr >= &top_[maxSize_]) return 0; - return std::min(current_near_ptr - reinterpret_cast(far_code_begin), current_far_ptr - &top_[maxSize_]); + return std::min(reinterpret_cast(far_code_begin) - current_near_ptr, &top_[maxSize_] - current_far_ptr); } void BlockOfCode::RunCode(void* jit_state, CodePtr code_ptr) const { diff --git a/externals/dynarmic/src/backend/x64/emit_x64.cpp b/externals/dynarmic/src/backend/x64/emit_x64.cpp index 6261f9abc..a53d12319 100755 --- a/externals/dynarmic/src/backend/x64/emit_x64.cpp +++ b/externals/dynarmic/src/backend/x64/emit_x64.cpp @@ -264,8 +264,11 @@ Xbyak::Label EmitX64::EmitCond(IR::Cond cond) { return pass; } -EmitX64::BlockDescriptor EmitX64::RegisterBlock(const IR::LocationDescriptor& descriptor, CodePtr entrypoint, size_t size) { +EmitX64::BlockDescriptor EmitX64::RegisterBlock(const IR::LocationDescriptor& descriptor, CodePtr entrypoint, CodePtr entrypoint_far, size_t size) { PerfMapRegister(entrypoint, code.getCurr(), LocationDescriptorToFriendlyName(descriptor)); + code.SwitchToFarCode(); + PerfMapRegister(entrypoint_far, code.getCurr(), LocationDescriptorToFriendlyName(descriptor) + "_far"); + code.SwitchToNearCode(); Patch(descriptor, entrypoint); BlockDescriptor block_desc{entrypoint, size}; diff --git a/externals/dynarmic/src/backend/x64/emit_x64.h b/externals/dynarmic/src/backend/x64/emit_x64.h index 7f784b474..c895aa73d 100755 --- a/externals/dynarmic/src/backend/x64/emit_x64.h +++ b/externals/dynarmic/src/backend/x64/emit_x64.h @@ -94,7 +94,7 @@ protected: virtual std::string LocationDescriptorToFriendlyName(const IR::LocationDescriptor&) const = 0; void EmitAddCycles(size_t cycles); Xbyak::Label EmitCond(IR::Cond cond); - BlockDescriptor RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, size_t size); + BlockDescriptor RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, CodePtr entrypoint_far, size_t size); void PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target); // Terminal instruction emitters diff --git a/externals/dynarmic/src/backend/x64/perf_map.cpp b/externals/dynarmic/src/backend/x64/perf_map.cpp index 4051445ff..8b077537e 100755 --- a/externals/dynarmic/src/backend/x64/perf_map.cpp +++ b/externals/dynarmic/src/backend/x64/perf_map.cpp @@ -47,6 +47,11 @@ void OpenFile() { namespace detail { void PerfMapRegister(const void* start, const void* end, std::string_view friendly_name) { + if (start == end) { + // Nothing to register + return; + } + std::lock_guard guard{mutex}; if (!file) { diff --git a/externals/dynarmic/src/frontend/A32/decoder/arm.inc b/externals/dynarmic/src/frontend/A32/decoder/arm.inc index 364f575c3..90995c4c0 100755 --- a/externals/dynarmic/src/frontend/A32/decoder/arm.inc +++ b/externals/dynarmic/src/frontend/A32/decoder/arm.inc @@ -6,8 +6,8 @@ INST(arm_ISB, "ISB", "1111010101111111111100000110oooo // Branch instructions INST(arm_BLX_imm, "BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv") // v5 INST(arm_BLX_reg, "BLX (reg)", "cccc000100101111111111110011mmmm") // v5 -INST(arm_B, "B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv") // all -INST(arm_BL, "BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv") // all +INST(arm_B, "B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv") // v1 +INST(arm_BL, "BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv") // v1 INST(arm_BX, "BX", "cccc000100101111111111110001mmmm") // v4T INST(arm_BXJ, "BXJ", "cccc000100101111111111110010mmmm") // v5J @@ -25,59 +25,59 @@ INST(arm_MRRC, "MRRC", "cccc11000101uuuuttttppppooooMMMM INST(arm_STC, "STC", "cccc110pudw0nnnnDDDDppppvvvvvvvv") // v2 (STC2: v5) // Data Processing instructions -INST(arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv") // all -INST(arm_ADC_reg, "ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm") // all -INST(arm_ADC_rsr, "ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm") // all -INST(arm_ADD_imm, "ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv") // all -INST(arm_ADD_reg, "ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm") // all -INST(arm_ADD_rsr, "ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm") // all -INST(arm_AND_imm, "AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv") // all -INST(arm_AND_reg, "AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm") // all -INST(arm_AND_rsr, "AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm") // all -INST(arm_BIC_imm, "BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv") // all -INST(arm_BIC_reg, "BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm") // all -INST(arm_BIC_rsr, "BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm") // all -INST(arm_CMN_imm, "CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv") // all -INST(arm_CMN_reg, "CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm") // all -INST(arm_CMN_rsr, "CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm") // all -INST(arm_CMP_imm, "CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv") // all -INST(arm_CMP_reg, "CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm") // all -INST(arm_CMP_rsr, "CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm") // all -INST(arm_EOR_imm, "EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv") // all -INST(arm_EOR_reg, "EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm") // all -INST(arm_EOR_rsr, "EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm") // all -INST(arm_MOV_imm, "MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv") // all -INST(arm_MOV_reg, "MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm") // all -INST(arm_MOV_rsr, "MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm") // all -INST(arm_MVN_imm, "MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv") // all -INST(arm_MVN_reg, "MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm") // all -INST(arm_MVN_rsr, "MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm") // all -INST(arm_ORR_imm, "ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv") // all -INST(arm_ORR_reg, "ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm") // all -INST(arm_ORR_rsr, "ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm") // all -INST(arm_RSB_imm, "RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv") // all -INST(arm_RSB_reg, "RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm") // all -INST(arm_RSB_rsr, "RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm") // all -INST(arm_RSC_imm, "RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv") // all -INST(arm_RSC_reg, "RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm") // all -INST(arm_RSC_rsr, "RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm") // all -INST(arm_SBC_imm, "SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv") // all -INST(arm_SBC_reg, "SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm") // all -INST(arm_SBC_rsr, "SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm") // all -INST(arm_SUB_imm, "SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv") // all -INST(arm_SUB_reg, "SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm") // all -INST(arm_SUB_rsr, "SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm") // all -INST(arm_TEQ_imm, "TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv") // all -INST(arm_TEQ_reg, "TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm") // all -INST(arm_TEQ_rsr, "TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm") // all -INST(arm_TST_imm, "TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv") // all -INST(arm_TST_reg, "TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm") // all -INST(arm_TST_rsr, "TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm") // all +INST(arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_ADC_reg, "ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_ADC_rsr, "ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm") // v1 +INST(arm_ADD_imm, "ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_ADD_reg, "ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_ADD_rsr, "ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm") // v1 +INST(arm_AND_imm, "AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_AND_reg, "AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_AND_rsr, "AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm") // v1 +INST(arm_BIC_imm, "BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_BIC_reg, "BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_BIC_rsr, "BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm") // v1 +INST(arm_CMN_imm, "CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv") // v1 +INST(arm_CMN_reg, "CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm") // v1 +INST(arm_CMN_rsr, "CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm") // v1 +INST(arm_CMP_imm, "CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv") // v1 +INST(arm_CMP_reg, "CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm") // v1 +INST(arm_CMP_rsr, "CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm") // v1 +INST(arm_EOR_imm, "EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_EOR_reg, "EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_EOR_rsr, "EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm") // v1 +INST(arm_MOV_imm, "MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv") // v1 +INST(arm_MOV_reg, "MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm") // v1 +INST(arm_MOV_rsr, "MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm") // v1 +INST(arm_MVN_imm, "MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv") // v1 +INST(arm_MVN_reg, "MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm") // v1 +INST(arm_MVN_rsr, "MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm") // v1 +INST(arm_ORR_imm, "ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_ORR_reg, "ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_ORR_rsr, "ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm") // v1 +INST(arm_RSB_imm, "RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_RSB_reg, "RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_RSB_rsr, "RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm") // v1 +INST(arm_RSC_imm, "RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_RSC_reg, "RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_RSC_rsr, "RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm") // v1 +INST(arm_SBC_imm, "SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_SBC_reg, "SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_SBC_rsr, "SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm") // v1 +INST(arm_SUB_imm, "SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv") // v1 +INST(arm_SUB_reg, "SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm") // v1 +INST(arm_SUB_rsr, "SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm") // v1 +INST(arm_TEQ_imm, "TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv") // v1 +INST(arm_TEQ_reg, "TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm") // v1 +INST(arm_TEQ_rsr, "TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm") // v1 +INST(arm_TST_imm, "TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv") // v1 +INST(arm_TST_reg, "TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm") // v1 +INST(arm_TST_rsr, "TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm") // v1 // Exception Generating instructions INST(arm_BKPT, "BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv") // v5 -INST(arm_SVC, "SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv") // all -INST(arm_UDF, "UDF", "111001111111------------1111----") // all +INST(arm_SVC, "SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv") // v1 +INST(arm_UDF, "UDF", "111001111111------------1111----") // Extension instructions INST(arm_SXTB, "SXTB", "cccc011010101111ddddrr000111mmmm") // v6 @@ -132,62 +132,62 @@ INST(arm_LDAEXH, "LDAEXH", "cccc00011111nnnndddd111010011111 INST(arm_LDREXH, "LDREXH", "cccc00011111nnnndddd111110011111") // v6K // Load/Store instructions -INST(arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------") -INST(arm_LDRBT, "LDRBT (A2)", "----0110-111---------------0----") -INST(arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----") -INST(arm_LDRHT, "LDRHT (A1)", "----0000-1111111--------1011----") -INST(arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----") -INST(arm_LDRSBT, "LDRSBT (A1)", "----0000-111------------1101----") -INST(arm_LDRSBT, "LDRSBT (A2)", "----0000-011--------00001101----") -INST(arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----") -INST(arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----") -INST(arm_LDRT, "LDRT (A1)", "----0100-011--------------------") -INST(arm_LDRT, "LDRT (A2)", "----0110-011---------------0----") -INST(arm_STRBT, "STRBT (A1)", "----0100-110--------------------") -INST(arm_STRBT, "STRBT (A2)", "----0110-110---------------0----") -INST(arm_STRHT, "STRHT (A1)", "----0000-110------------1011----") -INST(arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----") -INST(arm_STRT, "STRT (A1)", "----0100-010--------------------") -INST(arm_STRT, "STRT (A2)", "----0110-010---------------0----") -INST(arm_LDR_lit, "LDR (lit)", "cccc0101u0011111ttttvvvvvvvvvvvv") -INST(arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnttttvvvvvvvvvvvv") -INST(arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnttttvvvvvrr0mmmm") -INST(arm_LDRB_lit, "LDRB (lit)", "cccc0101u1011111ttttvvvvvvvvvvvv") -INST(arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnttttvvvvvvvvvvvv") -INST(arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnttttvvvvvrr0mmmm") -INST(arm_LDRD_lit, "LDRD (lit)", "cccc0001u1001111ttttvvvv1101vvvv") +INST(arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------") // v1 +INST(arm_LDRBT, "LDRBT (A2)", "----0110-111---------------0----") // v1 +INST(arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----") // v6T2 +INST(arm_LDRHT, "LDRHT (A1)", "----0000-1111111--------1011----") // v6T2 +INST(arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----") // v6T2 +INST(arm_LDRSBT, "LDRSBT (A1)", "----0000-111------------1101----") // v6T2 +INST(arm_LDRSBT, "LDRSBT (A2)", "----0000-011--------00001101----") // v6T2 +INST(arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----") // v6T2 +INST(arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----") // v6T2 +INST(arm_LDRT, "LDRT (A1)", "----0100-011--------------------") // v1 +INST(arm_LDRT, "LDRT (A2)", "----0110-011---------------0----") // v1 +INST(arm_STRBT, "STRBT (A1)", "----0100-110--------------------") // v1 +INST(arm_STRBT, "STRBT (A2)", "----0110-110---------------0----") // v1 +INST(arm_STRHT, "STRHT (A1)", "----0000-110------------1011----") // v6T2 +INST(arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----") // v6T2 +INST(arm_STRT, "STRT (A1)", "----0100-010--------------------") // v1 +INST(arm_STRT, "STRT (A2)", "----0110-010---------------0----") // v1 +INST(arm_LDR_lit, "LDR (lit)", "cccc0101u0011111ttttvvvvvvvvvvvv") // v1 +INST(arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnttttvvvvvvvvvvvv") // v1 +INST(arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnttttvvvvvrr0mmmm") // v1 +INST(arm_LDRB_lit, "LDRB (lit)", "cccc0101u1011111ttttvvvvvvvvvvvv") // v1 +INST(arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnttttvvvvvvvvvvvv") // v1 +INST(arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnttttvvvvvrr0mmmm") // v1 +INST(arm_LDRD_lit, "LDRD (lit)", "cccc0001u1001111ttttvvvv1101vvvv") // v5E INST(arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnttttvvvv1101vvvv") // v5E INST(arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnntttt00001101mmmm") // v5E -INST(arm_LDRH_lit, "LDRH (lit)", "cccc000pu1w11111ttttvvvv1011vvvv") -INST(arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnttttvvvv1011vvvv") -INST(arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnntttt00001011mmmm") -INST(arm_LDRSB_lit, "LDRSB (lit)", "cccc0001u1011111ttttvvvv1101vvvv") -INST(arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnttttvvvv1101vvvv") -INST(arm_LDRSB_reg, "LDRSB (reg)", "cccc000pu0w1nnnntttt00001101mmmm") -INST(arm_LDRSH_lit, "LDRSH (lit)", "cccc0001u1011111ttttvvvv1111vvvv") -INST(arm_LDRSH_imm, "LDRSH (imm)", "cccc000pu1w1nnnnttttvvvv1111vvvv") -INST(arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnntttt00001111mmmm") -INST(arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnttttvvvvvvvvvvvv") -INST(arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnttttvvvvvrr0mmmm") -INST(arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnttttvvvvvvvvvvvv") -INST(arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnttttvvvvvrr0mmmm") +INST(arm_LDRH_lit, "LDRH (lit)", "cccc000pu1w11111ttttvvvv1011vvvv") // v4 +INST(arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnttttvvvv1011vvvv") // v4 +INST(arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnntttt00001011mmmm") // v4 +INST(arm_LDRSB_lit, "LDRSB (lit)", "cccc0001u1011111ttttvvvv1101vvvv") // v4 +INST(arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnttttvvvv1101vvvv") // v4 +INST(arm_LDRSB_reg, "LDRSB (reg)", "cccc000pu0w1nnnntttt00001101mmmm") // v4 +INST(arm_LDRSH_lit, "LDRSH (lit)", "cccc0001u1011111ttttvvvv1111vvvv") // v4 +INST(arm_LDRSH_imm, "LDRSH (imm)", "cccc000pu1w1nnnnttttvvvv1111vvvv") // v4 +INST(arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnntttt00001111mmmm") // v4 +INST(arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnttttvvvvvvvvvvvv") // v1 +INST(arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnttttvvvvvrr0mmmm") // v1 +INST(arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnttttvvvvvvvvvvvv") // v1 +INST(arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnttttvvvvvrr0mmmm") // v1 INST(arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnttttvvvv1111vvvv") // v5E INST(arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnntttt00001111mmmm") // v5E -INST(arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnttttvvvv1011vvvv") -INST(arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnntttt00001011mmmm") +INST(arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnttttvvvv1011vvvv") // v4 +INST(arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnntttt00001011mmmm") // v4 // Load/Store Multiple instructions -INST(arm_LDM, "LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx") // all -INST(arm_LDMDA, "LDMDA", "cccc100000w1nnnnxxxxxxxxxxxxxxxx") // all -INST(arm_LDMDB, "LDMDB", "cccc100100w1nnnnxxxxxxxxxxxxxxxx") // all -INST(arm_LDMIB, "LDMIB", "cccc100110w1nnnnxxxxxxxxxxxxxxxx") // all -INST(arm_LDM_usr, "LDM (usr reg)", "----100--101--------------------") // all -INST(arm_LDM_eret, "LDM (exce ret)", "----100--1-1----1---------------") // all -INST(arm_STM, "STM", "cccc100010w0nnnnxxxxxxxxxxxxxxxx") // all -INST(arm_STMDA, "STMDA", "cccc100000w0nnnnxxxxxxxxxxxxxxxx") // all -INST(arm_STMDB, "STMDB", "cccc100100w0nnnnxxxxxxxxxxxxxxxx") // all -INST(arm_STMIB, "STMIB", "cccc100110w0nnnnxxxxxxxxxxxxxxxx") // all -INST(arm_STM_usr, "STM (usr reg)", "----100--100--------------------") // all +INST(arm_LDM, "LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx") // v1 +INST(arm_LDMDA, "LDMDA", "cccc100000w1nnnnxxxxxxxxxxxxxxxx") // v1 +INST(arm_LDMDB, "LDMDB", "cccc100100w1nnnnxxxxxxxxxxxxxxxx") // v1 +INST(arm_LDMIB, "LDMIB", "cccc100110w1nnnnxxxxxxxxxxxxxxxx") // v1 +INST(arm_LDM_usr, "LDM (usr reg)", "----100--101--------------------") // v1 +INST(arm_LDM_eret, "LDM (exce ret)", "----100--1-1----1---------------") // v1 +INST(arm_STM, "STM", "cccc100010w0nnnnxxxxxxxxxxxxxxxx") // v1 +INST(arm_STMDA, "STMDA", "cccc100000w0nnnnxxxxxxxxxxxxxxxx") // v1 +INST(arm_STMDB, "STMDB", "cccc100100w0nnnnxxxxxxxxxxxxxxxx") // v1 +INST(arm_STMIB, "STMIB", "cccc100110w0nnnnxxxxxxxxxxxxxxxx") // v1 +INST(arm_STM_usr, "STM (usr reg)", "----100--100--------------------") // v1 // Miscellaneous instructions INST(arm_BFC, "BFC", "cccc0111110vvvvvddddvvvvv0011111") // v6T2 diff --git a/externals/dynarmic/src/frontend/A32/decoder/thumb32.inc b/externals/dynarmic/src/frontend/A32/decoder/thumb32.inc index 2e133989e..6347fd0b6 100755 --- a/externals/dynarmic/src/frontend/A32/decoder/thumb32.inc +++ b/externals/dynarmic/src/frontend/A32/decoder/thumb32.inc @@ -11,7 +11,7 @@ INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100W1nnnniiiiii //INST(thumb32_RFE_2, "RFE", "1110100110-1--------------------") // Load/Store Dual, Load/Store Exclusive, Table Branch -//INST(thumb32_STREX, "STREX", "111010000100--------------------") +INST(thumb32_STREX, "STREX", "111010000100nnnnttttddddiiiiiiii") //INST(thumb32_LDREX, "LDREX", "111010000101--------------------") INST(thumb32_STRD_imm_1, "STRD (imm)", "11101000U110nnnnttttssssiiiiiiii") INST(thumb32_STRD_imm_2, "STRD (imm)", "11101001U1W0nnnnttttssssiiiiiiii") @@ -19,9 +19,9 @@ INST(thumb32_LDRD_lit_1, "LDRD (lit)", "11101000U1111111ttttss INST(thumb32_LDRD_lit_2, "LDRD (lit)", "11101001U1W11111ttttssssiiiiiiii") INST(thumb32_LDRD_imm_1, "LDRD (imm)", "11101000U111nnnnttttssssiiiiiiii") INST(thumb32_LDRD_imm_2, "LDRD (imm)", "11101001U1W1nnnnttttssssiiiiiiii") -//INST(thumb32_STREXB, "STREXB", "111010001100------------0100----") -//INST(thumb32_STREXH, "STREXH", "111010001100------------0101----") -//INST(thumb32_STREXD, "STREXD", "111010001100------------0111----") +INST(thumb32_STREXB, "STREXB", "111010001100nnnntttt11110100dddd") +INST(thumb32_STREXH, "STREXH", "111010001100nnnntttt11110101dddd") +INST(thumb32_STREXD, "STREXD", "111010001100nnnnttttuuuu0111dddd") INST(thumb32_TBB, "TBB", "111010001101nnnn111100000000mmmm") INST(thumb32_TBH, "TBH", "111010001101nnnn111100000001mmmm") //INST(thumb32_LDREXB, "LDREXB", "111010001101------------0100----") diff --git a/externals/dynarmic/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp b/externals/dynarmic/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp index c3d5323a7..09918e653 100755 --- a/externals/dynarmic/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp +++ b/externals/dynarmic/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp @@ -135,6 +135,67 @@ bool ThumbTranslatorVisitor::thumb32_STRD_imm_2(bool U, bool W, Reg n, Reg t, Re return StoreDual(*this, true, U, W, n, t, t2, imm8); } +bool ThumbTranslatorVisitor::thumb32_STREX(Reg n, Reg t, Reg d, Imm<8> imm8) { + if (d == Reg::PC || t == Reg::PC || n == Reg::PC) { + return UnpredictableInstruction(); + } + if (d == n || d == t) { + return UnpredictableInstruction(); + } + + const auto address = ir.Add(ir.GetRegister(n), ir.Imm32(imm8.ZeroExtend())); + const auto value = ir.GetRegister(t); + const auto passed = ir.ExclusiveWriteMemory32(address, value); + ir.SetRegister(d, passed); + return true; +} + +bool ThumbTranslatorVisitor::thumb32_STREXB(Reg n, Reg t, Reg d) { + if (d == Reg::PC || t == Reg::PC || n == Reg::PC) { + return UnpredictableInstruction(); + } + if (d == n || d == t) { + return UnpredictableInstruction(); + } + + const auto address = ir.GetRegister(n); + const auto value = ir.LeastSignificantByte(ir.GetRegister(t)); + const auto passed = ir.ExclusiveWriteMemory8(address, value); + ir.SetRegister(d, passed); + return true; +} + +bool ThumbTranslatorVisitor::thumb32_STREXD(Reg n, Reg t, Reg t2, Reg d) { + if (d == Reg::PC || t == Reg::PC || t2 == Reg::PC || n == Reg::PC) { + return UnpredictableInstruction(); + } + if (d == n || d == t || d == t2) { + return UnpredictableInstruction(); + } + + 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); + ir.SetRegister(d, passed); + return true; +} + +bool ThumbTranslatorVisitor::thumb32_STREXH(Reg n, Reg t, Reg d) { + if (d == Reg::PC || t == Reg::PC || n == Reg::PC) { + return UnpredictableInstruction(); + } + if (d == n || d == t) { + return UnpredictableInstruction(); + } + + const auto address = ir.GetRegister(n); + const auto value = ir.LeastSignificantHalf(ir.GetRegister(t)); + const auto passed = ir.ExclusiveWriteMemory16(address, value); + ir.SetRegister(d, passed); + return true; +} + bool ThumbTranslatorVisitor::thumb32_TBB(Reg n, Reg m) { return TableBranch(*this, n, m, false); } diff --git a/externals/dynarmic/src/frontend/A32/translate/impl/translate_thumb.h b/externals/dynarmic/src/frontend/A32/translate/impl/translate_thumb.h index ce43eba50..46a35e484 100755 --- a/externals/dynarmic/src/frontend/A32/translate/impl/translate_thumb.h +++ b/externals/dynarmic/src/frontend/A32/translate/impl/translate_thumb.h @@ -186,6 +186,10 @@ struct ThumbTranslatorVisitor final { bool thumb32_LDRD_lit_2(bool U, bool W, Reg t, Reg t2, Imm<8> imm8); bool thumb32_STRD_imm_1(bool U, Reg n, Reg t, Reg t2, Imm<8> imm8); bool thumb32_STRD_imm_2(bool U, bool W, Reg n, Reg t, Reg t2, Imm<8> imm8); + bool thumb32_STREX(Reg n, Reg t, Reg d, Imm<8> imm8); + bool thumb32_STREXB(Reg n, Reg t, Reg d); + bool thumb32_STREXD(Reg n, Reg t, Reg t2, Reg d); + bool thumb32_STREXH(Reg n, Reg t, Reg d); bool thumb32_TBB(Reg n, Reg m); bool thumb32_TBH(Reg n, Reg m); diff --git a/externals/dynarmic/tests/A32/fuzz_arm.cpp b/externals/dynarmic/tests/A32/fuzz_arm.cpp index b0dcf94dc..311b6bb3a 100755 --- a/externals/dynarmic/tests/A32/fuzz_arm.cpp +++ b/externals/dynarmic/tests/A32/fuzz_arm.cpp @@ -166,6 +166,12 @@ std::vector GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s "thumb16_BKPT", "thumb16_IT", "thumb16_SETEND", + + // Exclusive load/stores + "thumb32_STREX", + "thumb32_STREXB", + "thumb32_STREXD", + "thumb32_STREXH", }; for (const auto& [fn, bitstring] : list) {