From 5e5a6e2092af12e2c6dadca06bbcbeec2cf73c9b Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 24 Nov 2023 20:45:47 +0100 Subject: [PATCH] SPC700: implement ADDW --- src/snes/cpu_spc700/cpu.rs | 29 ++++++++++++++++++++++-- src/snes/cpu_spc700/instruction_table.rs | 2 +- src/test/processortests_spc700.rs | 2 +- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/snes/cpu_spc700/cpu.rs b/src/snes/cpu_spc700/cpu.rs index da82344..adbe11c 100644 --- a/src/snes/cpu_spc700/cpu.rs +++ b/src/snes/cpu_spc700/cpu.rs @@ -263,6 +263,7 @@ where InstructionType::BVC => self.op_branch(instr, !self.regs.test_flag(Flag::V)), InstructionType::BVS => self.op_branch(instr, self.regs.test_flag(Flag::V)), InstructionType::BRA => self.op_branch(instr, true), + InstructionType::ADDW => self.op_addw(instr), _ => todo!(), } } @@ -548,7 +549,7 @@ where let c = if self.regs.test_flag(Flag::C) { 1 } else { 0 }; let result = a as u16 + b as u16 + c as u16; - let result_h = (((a & 0x0F) + (b & 0x0F) + c) & 0x10) == 0x10; + let result_h = (a ^ b ^ result as u8) & 0x10 != 0; let result_v = !(a ^ b) & (a ^ result as u8) & 0x80 != 0; match instr.def.operands[0] { @@ -580,7 +581,7 @@ where let c = if self.regs.test_flag(Flag::C) { 1 } else { 0 }; let result = a as i16 + (!b) as i16 + c as i16; - let result_h = (((a & 0x0F) + (!b & 0x0F) + c) & 0x10) == 0x10; + let result_h = (a ^ !b ^ result as u8) & 0x10 != 0; let result_v = !(a ^ !b) & (a ^ result as u8) & 0x80 != 0; match instr.def.operands[0] { @@ -878,4 +879,28 @@ where self.tick_bus(2)?; Ok(()) } + + /// ADDW + fn op_addw(&mut self, instr: &Instruction) -> Result<()> { + let a = self.regs.read(Register::YA); + // Only direct page mode + let b = self.read16_tick_a8_delay(self.map_pageflag(instr.imm8(0))); + + let (result, result_c) = a.overflowing_add(b); + + // Half-carry on high byte + let result_h = (a ^ b ^ result) & 0x1000 != 0; + let result_v = !(a ^ b) & (a ^ result) & 0x8000 != 0; + + self.regs.write(Register::YA, result); + self.regs.write_flags(&[ + (Flag::C, result_c), + (Flag::H, result_h), + (Flag::V, result_v), + (Flag::N, (result & 0x8000) != 0), + (Flag::Z, result == 0), + ]); + + Ok(()) + } } diff --git a/src/snes/cpu_spc700/instruction_table.rs b/src/snes/cpu_spc700/instruction_table.rs index 12b7f95..f393844 100644 --- a/src/snes/cpu_spc700/instruction_table.rs +++ b/src/snes/cpu_spc700/instruction_table.rs @@ -998,7 +998,7 @@ pub const INSTRUCTION_TABLE: [InstructionDef; 256] = [ "ADDW YA, @", InstructionType::ADDW, 2, - [Operand::None, Operand::DirectPage] + [Operand::Register(Register::YA), Operand::DirectPage] ), // 0x7B - ROR d+X // N.....ZC, 2 bytes, 5 cycles diff --git a/src/test/processortests_spc700.rs b/src/test/processortests_spc700.rs index 9663a73..42e111d 100644 --- a/src/test/processortests_spc700.rs +++ b/src/test/processortests_spc700.rs @@ -311,7 +311,7 @@ cpu_test!(instr_77, 0x77); cpu_test!(instr_78, 0x78); // Read indirection during fetch cpu_test_no_trace!(instr_79, 0x79); -//cpu_test!(instr_7a, 0x7a); +cpu_test!(instr_7a, 0x7a); //cpu_test!(instr_7b, 0x7b); //cpu_test!(instr_7c, 0x7c); cpu_test!(instr_7d, 0x7d);