fix(cpu): PPCBUG-361 PPCBUG-565 fix vsldoi128 SH field extraction

PPCBUG-565: Add vx128_5_sh() to decoder.rs — 4-bit shift at PPC bits
22-25 (host bits 6-9). The correct MSB is at PPC bit 22 (host bit 9).

PPCBUG-361: vsldoi128 was reading the SH MSB from host bit 4 (PPC bit
27, reserved) instead of host bit 9 (PPC bit 22). All shift amounts >= 8
decoded incorrectly (e.g. shift=8 executed as shift=0). Replace the
inline bit-shuffle with instr.vx128_5_sh().

Also fix vx128_p_perm_assembles_correctly test: replace nonexistent
DecodedInstr::from_raw() calls with struct literal construction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-01 21:29:12 +02:00
parent 197d76c44e
commit 64e8ecbfd0

View File

@@ -1218,22 +1218,21 @@ mod tests {
fn vx128_p_perm_assembles_correctly() { fn vx128_p_perm_assembles_correctly() {
// PERMl=0x1F (all 5 bits set) at host bits 16-20: raw = 0x1F << 16 // PERMl=0x1F (all 5 bits set) at host bits 16-20: raw = 0x1F << 16
let raw = 0x1Fu32 << 16; let raw = 0x1Fu32 << 16;
assert_eq!(DecodedInstr::from_raw(raw).vx128_p_perm(), 0x1F, "PERMl only"); let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
assert_eq!(d.vx128_p_perm(), 0x1F, "PERMl only");
// PERMh=0x7 (all 3 bits set) at host bits 6-8: raw = 0x7 << 6 = 0x1C0 // PERMh=0x7 (all 3 bits set) at host bits 6-8: raw = 0x7 << 6 = 0x1C0
let raw = 0x7u32 << 6; let raw = 0x7u32 << 6;
assert_eq!( let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
DecodedInstr::from_raw(raw).vx128_p_perm(), assert_eq!(d.vx128_p_perm(), 0x7 << 5, "PERMh only: bits 5-7");
0x7 << 5,
"PERMh only: bits 5-7"
);
// PERMl=0xA, PERMh=0x5: raw = (0xA << 16) | (0x5 << 6) // PERMl=0xA, PERMh=0x5: raw = (0xA << 16) | (0x5 << 6)
let raw = (0xAu32 << 16) | (0x5u32 << 6); let raw = (0xAu32 << 16) | (0x5u32 << 6);
assert_eq!(DecodedInstr::from_raw(raw).vx128_p_perm(), 0xA | (0x5 << 5)); let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw, addr: 0 };
assert_eq!(d.vx128_p_perm(), 0xA | (0x5 << 5));
// PERMl and PERMh bits must not bleed into each other // PERMl and PERMh bits must not bleed into each other
let raw = 0u32; let d = DecodedInstr { opcode: PpcOpcode::Invalid, raw: 0, addr: 0 };
assert_eq!(DecodedInstr::from_raw(raw).vx128_p_perm(), 0); assert_eq!(d.vx128_p_perm(), 0);
} }
} }