From bdf64db79eca302aa0687c3c18a50274a918da86 Mon Sep 17 00:00:00 2001 From: "Herman S." <429230+has207@users.noreply.github.com> Date: Tue, 24 Mar 2026 15:25:33 +0900 Subject: [PATCH] [A64] Fix CNTLZ_I8/I16 returning 32 for zero input Add sentinel bits after the left-shift so clz stops at the correct count (8 or 16) instead of counting through all 32 bits of the widened register. Unlikely to hit in practice since PPC only has cntlzw/cntlzd, but corrects existing sub-word variants. --- src/xenia/cpu/backend/a64/a64_sequences.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/xenia/cpu/backend/a64/a64_sequences.cc b/src/xenia/cpu/backend/a64/a64_sequences.cc index 8bcdc3768..129e0c17d 100644 --- a/src/xenia/cpu/backend/a64/a64_sequences.cc +++ b/src/xenia/cpu/backend/a64/a64_sequences.cc @@ -2402,7 +2402,10 @@ struct CNTLZ_I8 : Sequence> { e.mov(i.dest, static_cast(count)); } else { // clz operates on 32-bit, so shift left 24 to put byte in top. + // OR a sentinel bit at position 23 so that a zero byte yields 8, + // not 32. e.lsl(e.w0, i.src1, 24); + e.orr(e.w0, e.w0, 1u << 23); e.clz(i.dest, e.w0); } } @@ -2418,7 +2421,9 @@ struct CNTLZ_I16 : Sequence> { } e.mov(i.dest, static_cast(count)); } else { + // Sentinel bit at position 15 caps the result at 16 for zero input. e.lsl(e.w0, i.src1, 16); + e.orr(e.w0, e.w0, 1u << 15); e.clz(i.dest, e.w0); } }