From a4d96da84d18db2a304f3a2e451b167d35816b72 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 23 Nov 2023 18:08:44 +0100 Subject: [PATCH] SPC700: implement CALL/TCALL --- src/snes/cpu_spc700/cpu.rs | 48 +++++++++++++++++++++++++++++++ src/test/processortests_spc700.rs | 34 +++++++++++----------- 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/snes/cpu_spc700/cpu.rs b/src/snes/cpu_spc700/cpu.rs index 9abf5ec..7eb5859 100644 --- a/src/snes/cpu_spc700/cpu.rs +++ b/src/snes/cpu_spc700/cpu.rs @@ -185,6 +185,12 @@ where lo | hi << 8 } + /// Call to an address + fn call(&mut self, addr: SpcAddress) { + self.push16(self.regs.read(Register::PC)); + self.regs.write(Register::PC, addr); + } + /// Executes an instruction. fn execute_instruction(&mut self, instr: &Instruction) -> Result<()> { match instr.def.instr_type { @@ -240,6 +246,12 @@ where InstructionType::LSR => self.op_lsr(instr), InstructionType::PUSH => self.op_push(instr), InstructionType::POP => self.op_pop(instr), + InstructionType::CALL => { + self.tick_bus(1)?; + self.call(instr.imm16()); + self.tick_bus(2) + } + InstructionType::TCALL => self.op_tcall(instr), _ => todo!(), } } @@ -772,4 +784,40 @@ where self.regs.write(reg, val.into()); Ok(()) } + + /// TCALL + fn op_tcall(&mut self, instr: &Instruction) -> Result<()> { + let iaddr = match instr.def.operands[0] { + Operand::ImpliedNum(0) => 0xFFDE, + Operand::ImpliedNum(1) => 0xFFDC, + Operand::ImpliedNum(2) => 0xFFDA, + Operand::ImpliedNum(3) => 0xFFD8, + Operand::ImpliedNum(4) => 0xFFD6, + Operand::ImpliedNum(5) => 0xFFD4, + Operand::ImpliedNum(6) => 0xFFD2, + Operand::ImpliedNum(7) => 0xFFD0, + Operand::ImpliedNum(8) => 0xFFCE, + Operand::ImpliedNum(9) => 0xFFCC, + Operand::ImpliedNum(10) => 0xFFCA, + Operand::ImpliedNum(11) => 0xFFC8, + Operand::ImpliedNum(12) => 0xFFC6, + Operand::ImpliedNum(13) => 0xFFC4, + Operand::ImpliedNum(14) => 0xFFC2, + Operand::ImpliedNum(15) => 0xFFC0, + _ => unreachable!(), + }; + + // Discarded read + self.read_tick(self.regs.read(Register::PC)); + self.tick_bus(1)?; + + // Stack push happens before following the + // address indirection. + self.push16(self.regs.read(Register::PC)); + self.tick_bus(1)?; + + let addr = self.read16_tick(iaddr); + self.regs.write(Register::PC, addr); + Ok(()) + } } diff --git a/src/test/processortests_spc700.rs b/src/test/processortests_spc700.rs index 0885fbf..4437286 100644 --- a/src/test/processortests_spc700.rs +++ b/src/test/processortests_spc700.rs @@ -176,7 +176,7 @@ fn run_testcase(testcase: &Value, check_trace: bool, multi_steps: bool) { } cpu_test!(instr_00, 0x00); -//cpu_test!(instr_01, 0x01); +cpu_test!(instr_01, 0x01); cpu_test!(instr_02, 0x02); //cpu_test!(instr_03, 0x03); cpu_test!(instr_04, 0x04); @@ -194,7 +194,7 @@ cpu_test!(instr_0d, 0x0d); //cpu_test!(instr_0e, 0x0e); //cpu_test!(instr_0f, 0x0f); //cpu_test!(instr_10, 0x10); -//cpu_test!(instr_11, 0x11); +cpu_test!(instr_11, 0x11); cpu_test!(instr_12, 0x12); //cpu_test!(instr_13, 0x13); cpu_test!(instr_14, 0x14); @@ -212,7 +212,7 @@ cpu_test!(instr_1d, 0x1d); cpu_test!(instr_1e, 0x1e); //cpu_test!(instr_1f, 0x1f); cpu_test!(instr_20, 0x20); -//cpu_test!(instr_21, 0x21); +cpu_test!(instr_21, 0x21); cpu_test!(instr_22, 0x22); //cpu_test!(instr_23, 0x23); cpu_test!(instr_24, 0x24); @@ -230,7 +230,7 @@ cpu_test!(instr_2d, 0x2d); //cpu_test!(instr_2e, 0x2e); //cpu_test!(instr_2f, 0x2f); //cpu_test!(instr_30, 0x30); -//cpu_test!(instr_31, 0x31); +cpu_test!(instr_31, 0x31); cpu_test!(instr_32, 0x32); //cpu_test!(instr_33, 0x33); cpu_test!(instr_34, 0x34); @@ -246,9 +246,9 @@ cpu_test_no_trace!(instr_39, 0x39); //cpu_test!(instr_3c, 0x3c); cpu_test!(instr_3d, 0x3d); cpu_test!(instr_3e, 0x3e); -//cpu_test!(instr_3f, 0x3f); +cpu_test!(instr_3f, 0x3f); cpu_test!(instr_40, 0x40); -//cpu_test!(instr_41, 0x41); +cpu_test!(instr_41, 0x41); cpu_test!(instr_42, 0x42); //cpu_test!(instr_43, 0x43); cpu_test!(instr_44, 0x44); @@ -266,7 +266,7 @@ cpu_test!(instr_4d, 0x4d); //cpu_test!(instr_4e, 0x4e); //cpu_test!(instr_4f, 0x4f); //cpu_test!(instr_50, 0x50); -//cpu_test!(instr_51, 0x51); +cpu_test!(instr_51, 0x51); cpu_test!(instr_52, 0x52); //cpu_test!(instr_53, 0x53); cpu_test!(instr_54, 0x54); @@ -284,7 +284,7 @@ cpu_test!(instr_5d, 0x5d); cpu_test!(instr_5e, 0x5e); //cpu_test!(instr_5f, 0x5f); cpu_test!(instr_60, 0x60); -//cpu_test!(instr_61, 0x61); +cpu_test!(instr_61, 0x61); cpu_test!(instr_62, 0x62); //cpu_test!(instr_63, 0x63); cpu_test!(instr_64, 0x64); @@ -301,7 +301,7 @@ cpu_test!(instr_6d, 0x6d); //cpu_test!(instr_6e, 0x6e); //cpu_test!(instr_6f, 0x6f); //cpu_test!(instr_70, 0x70); -//cpu_test!(instr_71, 0x71); +cpu_test!(instr_71, 0x71); cpu_test!(instr_72, 0x72); //cpu_test!(instr_73, 0x73); cpu_test!(instr_74, 0x74); @@ -318,7 +318,7 @@ cpu_test!(instr_7d, 0x7d); cpu_test!(instr_7e, 0x7e); //cpu_test!(instr_7f, 0x7f); cpu_test!(instr_80, 0x80); -//cpu_test!(instr_81, 0x81); +cpu_test!(instr_81, 0x81); cpu_test!(instr_82, 0x82); //cpu_test!(instr_83, 0x83); cpu_test!(instr_84, 0x84); @@ -335,7 +335,7 @@ cpu_test!(instr_8d, 0x8d); cpu_test!(instr_8e, 0x8e); cpu_test!(instr_8f, 0x8f); //cpu_test!(instr_90, 0x90); -//cpu_test!(instr_91, 0x91); +cpu_test!(instr_91, 0x91); cpu_test!(instr_92, 0x92); //cpu_test!(instr_93, 0x93); cpu_test!(instr_94, 0x94); @@ -352,7 +352,7 @@ cpu_test!(instr_9d, 0x9d); //cpu_test!(instr_9e, 0x9e); cpu_test!(instr_9f, 0x9f); cpu_test!(instr_a0, 0xa0); -//cpu_test!(instr_a1, 0xa1); +cpu_test!(instr_a1, 0xa1); cpu_test!(instr_a2, 0xa2); //cpu_test!(instr_a3, 0xa3); cpu_test!(instr_a4, 0xa4); @@ -370,7 +370,7 @@ cpu_test!(instr_ae, 0xae); // Wait during fetch cpu_test_no_trace!(instr_af, 0xaf); //cpu_test!(instr_b0, 0xb0); -//cpu_test!(instr_b1, 0xb1); +cpu_test!(instr_b1, 0xb1); cpu_test!(instr_b2, 0xb2); //cpu_test!(instr_b3, 0xb3); cpu_test!(instr_b4, 0xb4); @@ -387,7 +387,7 @@ cpu_test!(instr_bd, 0xbd); //cpu_test!(instr_be, 0xbe); cpu_test!(instr_bf, 0xbf); cpu_test!(instr_c0, 0xc0); -//cpu_test!(instr_c1, 0xc1); +cpu_test!(instr_c1, 0xc1); cpu_test!(instr_c2, 0xc2); //cpu_test!(instr_c3, 0xc3); cpu_test!(instr_c4, 0xc4); @@ -403,7 +403,7 @@ cpu_test!(instr_cd, 0xcd); cpu_test!(instr_ce, 0xce); //cpu_test!(instr_cf, 0xcf); //cpu_test!(instr_d0, 0xd0); -//cpu_test!(instr_d1, 0xd1); +cpu_test!(instr_d1, 0xd1); cpu_test!(instr_d2, 0xd2); //cpu_test!(instr_d3, 0xd3); cpu_test!(instr_d4, 0xd4); @@ -420,7 +420,7 @@ cpu_test!(instr_dd, 0xdd); //cpu_test!(instr_de, 0xde); //cpu_test!(instr_df, 0xdf); cpu_test!(instr_e0, 0xe0); -//cpu_test!(instr_e1, 0xe1); +cpu_test!(instr_e1, 0xe1); cpu_test!(instr_e2, 0xe2); //cpu_test!(instr_e3, 0xe3); cpu_test!(instr_e4, 0xe4); @@ -436,7 +436,7 @@ cpu_test!(instr_ed, 0xed); cpu_test!(instr_ee, 0xee); //cpu_test!(instr_ef, 0xef); //cpu_test!(instr_f0, 0xf0); -//cpu_test!(instr_f1, 0xf1); +cpu_test!(instr_f1, 0xf1); cpu_test!(instr_f2, 0xf2); //cpu_test!(instr_f3, 0xf3); cpu_test!(instr_f4, 0xf4);