From bf83c4e9f5b21cb525f1275dfa13d4a56e78c102 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Tue, 24 Mar 2026 13:38:11 -0700 Subject: [PATCH] [a64] Implement `OPCODE_CACHE_CONTROL` store --- src/xenia/cpu/backend/a64/a64_seq_memory.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/xenia/cpu/backend/a64/a64_seq_memory.cc b/src/xenia/cpu/backend/a64/a64_seq_memory.cc index 0c2a93ce3..32c94521a 100644 --- a/src/xenia/cpu/backend/a64/a64_seq_memory.cc +++ b/src/xenia/cpu/backend/a64/a64_seq_memory.cc @@ -76,7 +76,7 @@ struct CACHE_CONTROL : Sequence> { static void Emit(A64Emitter& e, const EmitArgType& i) { - bool is_prefetch = false, is_prefetchw = false; + bool is_clflush = false, is_prefetch = false, is_prefetchw = false; switch (CacheControlType(i.instr->flags)) { case CacheControlType::CACHE_CONTROL_TYPE_DATA_TOUCH: is_prefetch = true; @@ -86,15 +86,18 @@ struct CACHE_CONTROL break; case CacheControlType::CACHE_CONTROL_TYPE_DATA_STORE: case CacheControlType::CACHE_CONTROL_TYPE_DATA_STORE_AND_FLUSH: - // ARM64 dc instructions aren't available in xbyak_aarch64. - // These are mostly hints anyway; skip. - return; + is_clflush = true; + break; default: return; } auto addr = ComputeMemoryAddress(e, i.src1); e.add(e.x0, e.GetMembaseReg(), addr); size_t cache_line_size = i.src2.value; + if (is_clflush) { + // dc civac, x0 + e.sys(0b011, 0b0111, 0b1110, 0b001, e.x0); + } if (is_prefetch) { e.prfm(Xbyak_aarch64::PLDL1KEEP, ptr(e.x0)); } else if (is_prefetchw) { @@ -102,6 +105,10 @@ struct CACHE_CONTROL } if (cache_line_size >= 128) { e.eor(e.x0, e.x0, 64); + if (is_clflush) { + // dc civac, x0 + e.sys(0b011, 0b0111, 0b1110, 0b001, e.x0); + } if (is_prefetch) { e.prfm(Xbyak_aarch64::PLDL1KEEP, ptr(e.x0)); } else if (is_prefetchw) {