fix(disasm): PPCBUG-641+649 sync/lwsync L-field discrimination

PPCBUG-641: PpcOpcode::sync emitted "sync" regardless of the L-field at
PPC bit 10. The Xbox 360 acquire barrier (encoding 0x7C2004AC, L=1) is
lwsync, used in every spinlock. The disassembly DB stored every lwsync
as `mnemonic='sync'`, so `SELECT WHERE mnemonic='lwsync'` returned zero
rows regardless of binary content.

PPCBUG-649 (companion): the golden fixture for lwsync had no ext_mnemonic
field, pinning the wrong output and defeating regression detection.

Fix: in disasm.rs, gate on `(instr.raw >> 21) & 1` (PPC bit 10) — when
set, emit the lwsync extended form. Update extended_mnemonics.json
fixture to expect `ext_mnemonic: "lwsync"`.

Note: this is the disassembler-side fix only. The interpreter-side
PPCBUG-088 (lwsync vs sync semantics) is separate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-02 10:43:24 +02:00
parent d4f6ea787b
commit 2be25bdd41
2 changed files with 12 additions and 2 deletions

View File

@@ -361,7 +361,15 @@ pub fn format(instr: &DecodedInstr) -> DisasmText {
PpcOpcode::dcbz => fmt_cache(instr, "dcbz"),
PpcOpcode::dcbz128 => fmt_cache(instr, "dcbz128"),
PpcOpcode::icbi => fmt_cache(instr, "icbi"),
PpcOpcode::sync => base("sync", String::new(), 0),
PpcOpcode::sync => {
// L-field at PPC bit 10 (host bit 21) selects lwsync (L=1), the
// acquire barrier in every Xbox 360 spinlock. PPCBUG-641.
if (instr.raw >> 21) & 1 == 1 {
with_ext("sync", String::new(), 0, "lwsync", String::new(), 0)
} else {
base("sync", String::new(), 0)
}
}
PpcOpcode::eieio => base("eieio", String::new(), 0),
PpcOpcode::isync => base("isync", String::new(), 0),

View File

@@ -525,7 +525,9 @@
"raw": "0x7C2004AC",
"addr": "0x82000000",
"mnemonic": "sync",
"operands": ""
"operands": "",
"ext_mnemonic": "lwsync",
"ext_operands": ""
},
{
"label": "trap",