From 4acda223db8b814445deac9727d54a0b9e61f231 Mon Sep 17 00:00:00 2001 From: "Herman S." <429230+has207@users.noreply.github.com> Date: Wed, 8 Apr 2026 00:05:29 +0900 Subject: [PATCH] [CPU] Remove ATOMIC_EXCHANGE opcode (dead code) --- src/xenia/cpu/backend/a64/a64_seq_memory.cc | 95 ------------------- src/xenia/cpu/backend/x64/x64_seq_memory.cc | 62 ------------ src/xenia/cpu/hir/hir_builder.cc | 11 --- src/xenia/cpu/hir/hir_builder.h | 1 - src/xenia/cpu/hir/opcodes.h | 1 - src/xenia/cpu/hir/opcodes.inl | 6 -- .../cpu/testing/backend_integration_test.cc | 39 -------- 7 files changed, 215 deletions(-) diff --git a/src/xenia/cpu/backend/a64/a64_seq_memory.cc b/src/xenia/cpu/backend/a64/a64_seq_memory.cc index 501fb74f3..47d04a71f 100644 --- a/src/xenia/cpu/backend/a64/a64_seq_memory.cc +++ b/src/xenia/cpu/backend/a64/a64_seq_memory.cc @@ -867,101 +867,6 @@ struct MEMSET_I64 EMITTER_OPCODE_TABLE(OPCODE_MEMSET, MEMSET_I64); // ============================================================================ -// OPCODE_ATOMIC_EXCHANGE -// ============================================================================ -// Note: src1 is a HOST address (not guest), matching the x64 backend. -struct ATOMIC_EXCHANGE_I8 - : Sequence> { - static void Emit(A64Emitter& e, const EmitArgType& i) { - // src1 is already a host address. - if (i.src1.is_constant) { - e.mov(e.x4, i.src1.constant()); - } else { - e.mov(e.x4, i.src1); - } - if (i.src2.is_constant) { - e.mov(e.w0, static_cast( - static_cast(i.src2.constant()) & 0xFF)); - } else { - e.and_(e.w0, i.src2, 0xFF); - } - - if (e.IsFeatureEnabled(kA64EmitLSE)) { - e.swpalb(e.w0, i.dest, ptr(e.x4)); - return; - } - - auto& retry = e.NewCachedLabel(); - e.L(retry); - e.ldaxrb(e.w1, ptr(e.x4)); - e.stlxrb(e.w2, e.w0, ptr(e.x4)); - e.cbnz(e.w2, retry); - e.mov(i.dest, e.w1); - } -}; -struct ATOMIC_EXCHANGE_I16 - : Sequence> { - static void Emit(A64Emitter& e, const EmitArgType& i) { - if (i.src1.is_constant) { - e.mov(e.x4, i.src1.constant()); - } else { - e.mov(e.x4, i.src1); - } - if (i.src2.is_constant) { - e.mov(e.w0, static_cast( - static_cast(i.src2.constant()) & 0xFFFF)); - } else { - e.and_(e.w0, i.src2, 0xFFFF); - } - - if (e.IsFeatureEnabled(kA64EmitLSE)) { - e.swpalh(e.w0, i.dest, ptr(e.x4)); - return; - } - - auto& retry = e.NewCachedLabel(); - e.L(retry); - e.ldaxrh(e.w1, ptr(e.x4)); - e.stlxrh(e.w2, e.w0, ptr(e.x4)); - e.cbnz(e.w2, retry); - e.mov(i.dest, e.w1); - } -}; -struct ATOMIC_EXCHANGE_I32 - : Sequence> { - static void Emit(A64Emitter& e, const EmitArgType& i) { - // src1 is a host address (not guest). - if (i.src1.is_constant) { - e.mov(e.x4, i.src1.constant()); - } else { - e.mov(e.x4, i.src1); - } - if (i.src2.is_constant) { - e.mov(e.w0, - static_cast(static_cast(i.src2.constant()))); - } else { - e.mov(e.w0, i.src2); - } - - if (e.IsFeatureEnabled(kA64EmitLSE)) { - e.swpal(e.w0, i.dest, ptr(e.x4)); - return; - } - - auto& retry = e.NewCachedLabel(); - e.L(retry); - e.ldaxr(e.w1, ptr(e.x4)); - e.stlxr(e.w2, e.w0, ptr(e.x4)); - e.cbnz(e.w2, retry); - e.mov(i.dest, e.w1); - } -}; -EMITTER_OPCODE_TABLE(OPCODE_ATOMIC_EXCHANGE, ATOMIC_EXCHANGE_I8, - ATOMIC_EXCHANGE_I16, ATOMIC_EXCHANGE_I32); - // ============================================================================ // OPCODE_ATOMIC_COMPARE_EXCHANGE // ============================================================================ diff --git a/src/xenia/cpu/backend/x64/x64_seq_memory.cc b/src/xenia/cpu/backend/x64/x64_seq_memory.cc index b543a57b8..ffccd4c31 100644 --- a/src/xenia/cpu/backend/x64/x64_seq_memory.cc +++ b/src/xenia/cpu/backend/x64/x64_seq_memory.cc @@ -295,68 +295,6 @@ RegExp ComputeMemoryAddressOffset(X64Emitter& e, const T& guest, } } -// ============================================================================ -// OPCODE_ATOMIC_EXCHANGE -// ============================================================================ -// Note that the address we use here is a real, host address! -// This is weird, and should be fixed. -template -void EmitAtomicExchangeXX(X64Emitter& e, const ARGS& i) { - if (i.dest == i.src1) { - e.mov(e.rax, i.src1); - if (i.dest != i.src2) { - if (i.src2.is_constant) { - e.mov(i.dest, i.src2.constant()); - } else { - e.mov(i.dest, i.src2); - } - } - e.lock(); - e.xchg(e.dword[e.rax], i.dest); - } else { - if (i.dest != i.src2) { - if (i.src2.is_constant) { - e.mov(i.dest, i.src2.constant()); - } else { - e.mov(i.dest, i.src2); - } - } - e.lock(); - e.xchg(e.dword[i.src1.reg()], i.dest); - } -} -struct ATOMIC_EXCHANGE_I8 - : Sequence> { - static void Emit(X64Emitter& e, const EmitArgType& i) { - EmitAtomicExchangeXX(e, i); - } -}; -struct ATOMIC_EXCHANGE_I16 - : Sequence> { - static void Emit(X64Emitter& e, const EmitArgType& i) { - EmitAtomicExchangeXX(e, i); - } -}; -struct ATOMIC_EXCHANGE_I32 - : Sequence> { - static void Emit(X64Emitter& e, const EmitArgType& i) { - EmitAtomicExchangeXX(e, i); - } -}; -struct ATOMIC_EXCHANGE_I64 - : Sequence> { - static void Emit(X64Emitter& e, const EmitArgType& i) { - EmitAtomicExchangeXX(e, i); - } -}; -EMITTER_OPCODE_TABLE(OPCODE_ATOMIC_EXCHANGE, ATOMIC_EXCHANGE_I8, - ATOMIC_EXCHANGE_I16, ATOMIC_EXCHANGE_I32, - ATOMIC_EXCHANGE_I64); - struct LVL_V128 : Sequence> { static void Emit(X64Emitter& e, const EmitArgType& i) { e.mov(e.edx, 0xf); diff --git a/src/xenia/cpu/hir/hir_builder.cc b/src/xenia/cpu/hir/hir_builder.cc index 44ac5d936..26bd58195 100644 --- a/src/xenia/cpu/hir/hir_builder.cc +++ b/src/xenia/cpu/hir/hir_builder.cc @@ -2225,17 +2225,6 @@ Value* HIRBuilder::Unpack(Value* value, uint32_t pack_flags) { return i->dest; } -Value* HIRBuilder::AtomicExchange(Value* address, Value* new_value) { - ASSERT_ADDRESS_TYPE(address); - ASSERT_INTEGER_TYPE(new_value); - Instr* i = - AppendInstr(OPCODE_ATOMIC_EXCHANGE_info, 0, AllocValue(new_value->type)); - i->set_src1(address); - i->set_src2(new_value); - i->src3.value = NULL; - return i->dest; -} - Value* HIRBuilder::AtomicCompareExchange(Value* address, Value* old_value, Value* new_value) { ASSERT_ADDRESS_TYPE(address); diff --git a/src/xenia/cpu/hir/hir_builder.h b/src/xenia/cpu/hir/hir_builder.h index 2621148ef..e8a80415a 100644 --- a/src/xenia/cpu/hir/hir_builder.h +++ b/src/xenia/cpu/hir/hir_builder.h @@ -297,7 +297,6 @@ class HIRBuilder { Value* Pack(Value* value1, Value* value2, uint32_t pack_flags = 0); Value* Unpack(Value* value, uint32_t pack_flags = 0); - Value* AtomicExchange(Value* address, Value* new_value); Value* AtomicCompareExchange(Value* address, Value* old_value, Value* new_value); Value* AtomicAdd(Value* address, Value* value); diff --git a/src/xenia/cpu/hir/opcodes.h b/src/xenia/cpu/hir/opcodes.h index 5a1bdc53b..43be8810a 100644 --- a/src/xenia/cpu/hir/opcodes.h +++ b/src/xenia/cpu/hir/opcodes.h @@ -282,7 +282,6 @@ enum Opcode { OPCODE_PACK, // break up into smaller operations and add a float16 convert // opcode OPCODE_UNPACK, - OPCODE_ATOMIC_EXCHANGE, OPCODE_ATOMIC_COMPARE_EXCHANGE, OPCODE_SET_ROUNDING_MODE, OPCODE_VECTOR_DENORMFLUSH, // converts denormals to signed zeros in a vector diff --git a/src/xenia/cpu/hir/opcodes.inl b/src/xenia/cpu/hir/opcodes.inl index c5c089e85..255b4fb80 100644 --- a/src/xenia/cpu/hir/opcodes.inl +++ b/src/xenia/cpu/hir/opcodes.inl @@ -650,12 +650,6 @@ DEFINE_OPCODE( OPCODE_SIG_V_V, 0) -DEFINE_OPCODE( - OPCODE_ATOMIC_EXCHANGE, - "atomic_exchange", - OPCODE_SIG_V_V_V, - OPCODE_FLAG_VOLATILE) - DEFINE_OPCODE( OPCODE_ATOMIC_COMPARE_EXCHANGE, "atomic_compare_exchange", diff --git a/src/xenia/cpu/testing/backend_integration_test.cc b/src/xenia/cpu/testing/backend_integration_test.cc index fdcf9414a..e907b0bf7 100644 --- a/src/xenia/cpu/testing/backend_integration_test.cc +++ b/src/xenia/cpu/testing/backend_integration_test.cc @@ -646,45 +646,6 @@ TEST_CASE("SET_NJM_OFF", "[backend]") { #endif } -// ============================================================================= -// Atomic Exchange I32 -// ============================================================================= -// Tests that AtomicExchange correctly swaps a value in memory and returns -// the old value. -// NOTE: OPCODE_ATOMIC_EXCHANGE uses a HOST address (not guest), per the -// x64 backend comment: "the address we use here is a real, host address!" -TEST_CASE("ATOMIC_EXCHANGE_I32", "[backend]") { - TestFunction test([](HIRBuilder& b) { - // r[4] holds the host address directly. - auto addr = LoadGPR(b, 4); - auto new_val = b.Truncate(LoadGPR(b, 5), hir::INT32_TYPE); - auto old_val = b.AtomicExchange(addr, new_val); - StoreGPR(b, 3, b.ZeroExtend(old_val, hir::INT64_TYPE)); - b.Return(); - }); - - // Allocate guest memory and compute the host pointer. - uint32_t guest_addr = test.memory->SystemHeapAlloc(4); - REQUIRE(guest_addr != 0); - auto* host_ptr = test.memory->TranslateVirtual(guest_addr); - - test.Run( - [&](PPCContext* ctx) { - *reinterpret_cast(host_ptr) = 0xAABBCCDD; - // Pass the HOST address in r[4]. - ctx->r[4] = reinterpret_cast(host_ptr); - ctx->r[5] = 0x11223344; - }, - [&](PPCContext* ctx) { - // r[3] should have the old value. - REQUIRE(static_cast(ctx->r[3]) == 0xAABBCCDD); - // Memory should now have the new value. - REQUIRE(*reinterpret_cast(host_ptr) == 0x11223344); - }); - - test.memory->SystemHeapFree(guest_addr); -} - // ============================================================================= // DOT_PRODUCT_3 — inline NEON dot product of first 3 vector elements // =============================================================================