diff --git a/crates/xenia-cpu/src/interpreter.rs b/crates/xenia-cpu/src/interpreter.rs index 29d1ebb..0e150e8 100644 --- a/crates/xenia-cpu/src/interpreter.rs +++ b/crates/xenia-cpu/src/interpreter.rs @@ -112,10 +112,8 @@ fn execute(ctx: &mut PpcContext, mem: &dyn MemoryAccess, instr: &DecodedInstr) - match instr.opcode { // ===== ALU: Immediate ===== PpcOpcode::addi => { - // PPCBUG-001: 32-bit ABI. `li rT, -1` (= addi rT, r0, -1) must produce - // 0x00000000_FFFFFFFF, not 0xFFFFFFFF_FFFFFFFF (sign-extended simm16). let ra_val = if instr.ra() == 0 { 0 } else { ctx.gpr[instr.ra()] }; - ctx.gpr[instr.rd()] = ra_val.wrapping_add(instr.simm16() as i64 as u64) as u32 as u64; + ctx.gpr[instr.rd()] = ra_val.wrapping_add(instr.simm16() as i64 as u64); ctx.pc += 4; } PpcOpcode::addis => { @@ -5570,9 +5568,11 @@ mod tests { } #[test] - fn addi_li_neg_one_zero_extends_upper() { - // PPCBUG-001: `li r3, -1` (= addi r3, r0, -1) must produce - // 0x00000000_FFFFFFFF, not 0xFFFFFFFF_FFFFFFFF. + fn addi_li_neg_one_sign_extends_per_powerisa() { + // SWAPBUG-001 / PPCBUG-001 revert: `li r3, -1` (= addi r3, r0, -1) + // must sign-extend simm16 to 64 bits per PowerISA, producing + // 0xFFFFFFFF_FFFFFFFF. The pre-revert form truncated to 32 bits, + // which broke the swap path (canary-divergent and load-bearing). let mut ctx = PpcContext::new(); let mut mem = TestMem::new(); // addi r3, r0, -1: opcode 14, simm16 = 0xFFFF @@ -5580,7 +5580,7 @@ mod tests { write_instr(&mut mem, 0, raw); ctx.pc = 0; step(&mut ctx, &mut mem); - assert_eq!(ctx.gpr[3], 0x0000_0000_FFFF_FFFFu64); + assert_eq!(ctx.gpr[3], 0xFFFF_FFFF_FFFF_FFFFu64); } #[test]