mirror of
https://github.com/FranLMSP/snes.git
synced 2026-01-01 07:21:35 -05:00
Fixes for MVN and MVP instuctions
This commit is contained in:
@@ -187,9 +187,9 @@ pub fn map_opcode_to_instruction(opcode: u8) -> Box<dyn CPUInstruction> {
|
||||
0x5E => Box::new(LSR{addressing_mode: A::AbsoluteIndexed(I::X)}),
|
||||
0x56 => Box::new(LSR{addressing_mode: A::DirectPageIndexed(I::X)}),
|
||||
// MVN
|
||||
0x54 => Box::new(MVN{}), // TODO: Broken
|
||||
0x54 => Box::new(MVN{}),
|
||||
// MVP
|
||||
0x44 => Box::new(MVP{}), // TODO: Broken
|
||||
0x44 => Box::new(MVP{}),
|
||||
// NOP
|
||||
0xEA => Box::new(NOP{}),
|
||||
// ORA
|
||||
|
||||
@@ -27,3 +27,28 @@ pub fn do_move(registers: &mut Registers, bus: &mut Bus, is_next: bool) {
|
||||
let (bytes, cycles) = cycles::increment_cycles_move(count);
|
||||
registers.increment_pc(bytes); registers.cycles += cycles;
|
||||
}
|
||||
|
||||
|
||||
pub fn tick_move(registers: &mut Registers, bus: &mut Bus, is_next: bool) {
|
||||
let pc = registers.get_pc_address();
|
||||
// We assume that the 3 bytes of the instructions were already fetched
|
||||
let source_bank = bus.read(pc.wrapping_sub(1));
|
||||
let dest_bank = bus.read(pc.wrapping_sub(2));
|
||||
let source_address = ((source_bank as u32) << 16) | (registers.x as u32);
|
||||
let dest_address = ((dest_bank as u32) << 16) | (registers.y as u32);
|
||||
let byte = bus.read(source_address);
|
||||
bus.write(dest_address, byte);
|
||||
if is_next {
|
||||
registers.x = registers.x.wrapping_add(1);
|
||||
registers.y = registers.y.wrapping_add(1);
|
||||
} else {
|
||||
registers.x = registers.x.wrapping_sub(1);
|
||||
registers.y = registers.y.wrapping_sub(1);
|
||||
}
|
||||
registers.a = registers.a.wrapping_sub(1);
|
||||
if registers.a == 0xFFFF {
|
||||
registers.dbr = dest_bank;
|
||||
registers.is_moving = false;
|
||||
}
|
||||
registers.cycles += 7;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::cpu::{bus::Bus, registers::Registers};
|
||||
|
||||
use super::{CPUInstruction, move_common};
|
||||
use crate::cpu::cycles;
|
||||
use super::CPUInstruction;
|
||||
use super::decoder_common;
|
||||
|
||||
static INSTR_NAME: &str = "MVN";
|
||||
@@ -8,8 +9,11 @@ static INSTR_NAME: &str = "MVN";
|
||||
pub struct MVN {}
|
||||
|
||||
impl CPUInstruction for MVN {
|
||||
fn execute(&self, registers: &mut Registers, bus: &mut Bus) {
|
||||
move_common::do_move(registers, bus, true);
|
||||
fn execute(&self, registers: &mut Registers, _bus: &mut Bus) {
|
||||
let (bytes, _) = cycles::increment_cycles_move(1);
|
||||
registers.increment_pc(bytes);
|
||||
registers.is_moving = true;
|
||||
registers.is_move_next = true;
|
||||
}
|
||||
|
||||
fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::cpu::cycles;
|
||||
use crate::cpu::{bus::Bus, registers::Registers};
|
||||
|
||||
use super::{CPUInstruction, move_common};
|
||||
use super::CPUInstruction;
|
||||
use super::decoder_common;
|
||||
|
||||
static INSTR_NAME: &str = "MVP";
|
||||
@@ -8,8 +9,11 @@ static INSTR_NAME: &str = "MVP";
|
||||
pub struct MVP {}
|
||||
|
||||
impl CPUInstruction for MVP {
|
||||
fn execute(&self, registers: &mut Registers, bus: &mut Bus) {
|
||||
move_common::do_move(registers, bus, false);
|
||||
fn execute(&self, registers: &mut Registers, _bus: &mut Bus) {
|
||||
let (bytes, _) = cycles::increment_cycles_move(1);
|
||||
registers.increment_pc(bytes);
|
||||
registers.is_moving = true;
|
||||
registers.is_move_next = false;
|
||||
}
|
||||
|
||||
fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{registers::Registers, bus::Bus, cycles, dma, instructions::mapper::map_opcode_to_instruction};
|
||||
use super::{bus::Bus, cycles, dma, instructions::{mapper::map_opcode_to_instruction, move_common}, registers::Registers};
|
||||
|
||||
pub struct CPU {
|
||||
pub registers: Registers,
|
||||
@@ -39,6 +39,11 @@ impl CPU {
|
||||
self.registers.increment_pc(bytes); self.registers.cycles += cycles;
|
||||
return false;
|
||||
}
|
||||
if self.registers.is_moving {
|
||||
let is_next = self.registers.is_move_next;
|
||||
move_common::tick_move(&mut self.registers, bus, is_next);
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ pub struct Registers {
|
||||
pub emulation_mode: bool,
|
||||
pub is_cpu_stopped: bool,
|
||||
pub is_cpu_waiting_interrupt: bool,
|
||||
pub is_moving: bool, // TODO: refactor these states with an enum
|
||||
pub is_move_next: bool, // TODO: refactor these states with an enum
|
||||
pub cycles: usize,
|
||||
}
|
||||
|
||||
@@ -31,6 +33,8 @@ impl Registers {
|
||||
emulation_mode: true,
|
||||
is_cpu_stopped: false,
|
||||
is_cpu_waiting_interrupt: false,
|
||||
is_moving: false,
|
||||
is_move_next: false,
|
||||
cycles: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use snes_core::cpu::bus::Bus;
|
||||
use snes_core::cpu::registers::Registers;
|
||||
use snes_core::cpu::CPU;
|
||||
/// https://github.com/TomHarte/ProcessorTests/tree/main/65816
|
||||
|
||||
use snes_core::emulator::Emulator;
|
||||
@@ -91,6 +92,7 @@ fn main() -> Result<()> {
|
||||
let mut total_passed = 0;
|
||||
|
||||
for test in &tests.0 {
|
||||
emulator.cpu = CPU::new();
|
||||
let mut did_test_fail = false;
|
||||
println!("running test case {}", test.name);
|
||||
|
||||
@@ -110,6 +112,9 @@ fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
emulator.tick();
|
||||
while emulator.cpu.registers.is_moving {
|
||||
emulator.tick();
|
||||
}
|
||||
|
||||
let is_emu_mode = emulator.cpu.registers.emulation_mode;
|
||||
let is_16index = emulator.cpu.registers.is_16bit_index();
|
||||
|
||||
Reference in New Issue
Block a user