mirror of
https://github.com/FranLMSP/snes.git
synced 2026-10-05 00:45:18 -04:00
set_flags function
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
/// CPU Status flags for both the 65XX and SPC700 processors
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum Flags {
|
||||||
|
Negative(bool),
|
||||||
|
Overflow(bool),
|
||||||
|
MemoryAccumulatorSelect(bool),
|
||||||
|
IndexRegisterSelect(bool),
|
||||||
|
DecimalMode(bool),
|
||||||
|
IRQDisable(bool),
|
||||||
|
Zero(bool),
|
||||||
|
Carry(bool),
|
||||||
|
HalfCarry(bool),
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
pub trait CPUInstruction {
|
||||||
|
fn execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ADC {}
|
||||||
|
impl CPUInstruction for ADC {
|
||||||
|
fn execute () {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod instructions;
|
||||||
|
pub mod flags;
|
||||||
@@ -3,6 +3,8 @@ use crate::bus::Bus;
|
|||||||
use crate::utils::addressing::{AddressingMode, IndexRegister};
|
use crate::utils::addressing::{AddressingMode, IndexRegister};
|
||||||
use crate::utils::alu;
|
use crate::utils::alu;
|
||||||
|
|
||||||
|
type F = crate::common::flags::Flags;
|
||||||
|
|
||||||
impl CPU {
|
impl CPU {
|
||||||
fn get_8bit_from_address(&self, bus: &Bus, addressing_mode: AddressingMode) -> u8 {
|
fn get_8bit_from_address(&self, bus: &Bus, addressing_mode: AddressingMode) -> u8 {
|
||||||
addressing_mode.value_8bit(
|
addressing_mode.value_8bit(
|
||||||
@@ -29,34 +31,31 @@ impl CPU {
|
|||||||
// Otherwise, 16 bit addition
|
// Otherwise, 16 bit addition
|
||||||
let carry_flag = self.registers.get_carry_flag();
|
let carry_flag = self.registers.get_carry_flag();
|
||||||
let is_decimal_mode = self.registers.get_decimal_mode_flag();
|
let is_decimal_mode = self.registers.get_decimal_mode_flag();
|
||||||
let is_8bit = self.registers.get_memory_select_flag();
|
let is_16bit = self.registers.is_16bit_mode();
|
||||||
let target = self.registers.a;
|
let target = self.registers.a;
|
||||||
match is_8bit {
|
if is_16bit {
|
||||||
true => {
|
let value = self.get_16bit_from_address(bus, addressing_mode);
|
||||||
let value = self.get_8bit_from_address(bus, addressing_mode);
|
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
true => alu::adc_bcd(target, value, carry_flag),
|
||||||
true => alu::adc_bcd(target as u8, value, carry_flag),
|
false => alu::adc_bin(target, value, carry_flag),
|
||||||
false => alu::adc_bin(target as u8, value, carry_flag),
|
};
|
||||||
};
|
self.registers.a = result;
|
||||||
self.registers.set_low_a(result as u8);
|
self.registers.set_flags(&[
|
||||||
self.registers.set_carry_flag(is_carry);
|
F::Carry(is_carry), F::Negative(is_negative),
|
||||||
self.registers.set_negative_flag(is_negative);
|
F::Zero(is_zero), F::Overflow(is_overflow),
|
||||||
self.registers.set_zero_flag(is_zero);
|
]);
|
||||||
self.registers.set_overflow_flag(is_overflow);
|
} else {
|
||||||
},
|
let value = self.get_8bit_from_address(bus, addressing_mode);
|
||||||
false => {
|
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||||
let value = self.get_16bit_from_address(bus, addressing_mode);
|
true => alu::adc_bcd(target as u8, value, carry_flag),
|
||||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
false => alu::adc_bin(target as u8, value, carry_flag),
|
||||||
true => alu::adc_bcd(target, value, carry_flag),
|
};
|
||||||
false => alu::adc_bin(target, value, carry_flag),
|
self.registers.set_low_a(result as u8);
|
||||||
};
|
self.registers.set_flags(&[
|
||||||
self.registers.a = result;
|
F::Carry(is_carry), F::Negative(is_negative),
|
||||||
self.registers.set_carry_flag(is_carry);
|
F::Zero(is_zero), F::Overflow(is_overflow),
|
||||||
self.registers.set_negative_flag(is_negative);
|
]);
|
||||||
self.registers.set_zero_flag(is_zero);
|
}
|
||||||
self.registers.set_overflow_flag(is_overflow);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.increment_cycles_arithmetic(addressing_mode);
|
self.increment_cycles_arithmetic(addressing_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,34 +64,31 @@ impl CPU {
|
|||||||
// Otherwise, 16 bit addition
|
// Otherwise, 16 bit addition
|
||||||
let carry_flag = self.registers.get_carry_flag();
|
let carry_flag = self.registers.get_carry_flag();
|
||||||
let is_decimal_mode = self.registers.get_decimal_mode_flag();
|
let is_decimal_mode = self.registers.get_decimal_mode_flag();
|
||||||
let is_8bit = self.registers.get_memory_select_flag();
|
let is_16bit = self.registers.is_16bit_mode();
|
||||||
let target = self.registers.a;
|
let target = self.registers.a;
|
||||||
match is_8bit {
|
if is_16bit {
|
||||||
true => {
|
let value = self.get_16bit_from_address(bus, addressing_mode);
|
||||||
let value = self.get_8bit_from_address(bus, addressing_mode);
|
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
true => alu::sbc_bcd(target, value, carry_flag),
|
||||||
true => alu::sbc_bcd(target as u8, value, carry_flag),
|
false => alu::sbc_bin(target, value, carry_flag),
|
||||||
false => alu::sbc_bin(target as u8, value, carry_flag),
|
};
|
||||||
};
|
self.registers.a = result;
|
||||||
self.registers.set_low_a(result as u8);
|
self.registers.set_flags(&[
|
||||||
self.registers.set_carry_flag(is_carry);
|
F::Carry(is_carry), F::Negative(is_negative),
|
||||||
self.registers.set_negative_flag(is_negative);
|
F::Zero(is_zero), F::Overflow(is_overflow),
|
||||||
self.registers.set_zero_flag(is_zero);
|
]);
|
||||||
self.registers.set_overflow_flag(is_overflow);
|
} else {
|
||||||
},
|
let value = self.get_8bit_from_address(bus, addressing_mode);
|
||||||
false => {
|
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||||
let value = self.get_16bit_from_address(bus, addressing_mode);
|
true => alu::sbc_bcd(target as u8, value, carry_flag),
|
||||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
false => alu::sbc_bin(target as u8, value, carry_flag),
|
||||||
true => alu::sbc_bcd(target, value, carry_flag),
|
};
|
||||||
false => alu::sbc_bin(target, value, carry_flag),
|
self.registers.set_low_a(result as u8);
|
||||||
};
|
self.registers.set_flags(&[
|
||||||
self.registers.a = result;
|
F::Carry(is_carry), F::Negative(is_negative),
|
||||||
self.registers.set_carry_flag(is_carry);
|
F::Zero(is_zero), F::Overflow(is_overflow),
|
||||||
self.registers.set_negative_flag(is_negative);
|
]);
|
||||||
self.registers.set_zero_flag(is_zero);
|
}
|
||||||
self.registers.set_overflow_flag(is_overflow);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.increment_cycles_arithmetic(addressing_mode);
|
self.increment_cycles_arithmetic(addressing_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::common::flags::Flags;
|
||||||
|
|
||||||
pub struct Registers {
|
pub struct Registers {
|
||||||
pub sp: u16, // Stack pointer
|
pub sp: u16, // Stack pointer
|
||||||
pub x: u16, // Index X
|
pub x: u16, // Index X
|
||||||
@@ -131,6 +133,23 @@ impl Registers {
|
|||||||
pub fn direct_page_low(&self) -> u8 {
|
pub fn direct_page_low(&self) -> u8 {
|
||||||
self.d as u8
|
self.d as u8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_flags(&mut self, flags: &[Flags]) {
|
||||||
|
for flag in flags {
|
||||||
|
let flag = *flag;
|
||||||
|
match flag {
|
||||||
|
Flags::Negative(v) => self.set_negative_flag(v),
|
||||||
|
Flags::Overflow(v) => self.set_overflow_flag(v),
|
||||||
|
Flags::MemoryAccumulatorSelect(v) => self.set_memory_select_flag(v),
|
||||||
|
Flags::IndexRegisterSelect(v) => self.set_index_register_select_flag(v),
|
||||||
|
Flags::DecimalMode(v) => self.set_decimal_mode_flag(v),
|
||||||
|
Flags::IRQDisable(v) => self.set_irq_disable_flag(v),
|
||||||
|
Flags::Zero(v) => self.set_zero_flag(v),
|
||||||
|
Flags::Carry(v) => self.set_carry_flag(v),
|
||||||
|
Flags::HalfCarry(_) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -243,5 +262,28 @@ mod registers_tests {
|
|||||||
assert!(!registers.get_overflow_flag());
|
assert!(!registers.get_overflow_flag());
|
||||||
assert_eq!(registers.p, 0b0000_0000);
|
assert_eq!(registers.p, 0b0000_0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_flags() {
|
||||||
|
let mut registers = Registers::new();
|
||||||
|
|
||||||
|
registers.p = 0x00;
|
||||||
|
registers .set_flags(&[
|
||||||
|
Flags::Carry(true),
|
||||||
|
Flags::Zero(true),
|
||||||
|
]);
|
||||||
|
assert!(registers.get_carry_flag());
|
||||||
|
assert!(registers.get_zero_flag());
|
||||||
|
assert_eq!(registers.p, 0b0000_0011);
|
||||||
|
|
||||||
|
registers.p = 0xFF;
|
||||||
|
registers .set_flags(&[
|
||||||
|
Flags::Carry(false),
|
||||||
|
Flags::Zero(false),
|
||||||
|
]);
|
||||||
|
assert!(!registers.get_carry_flag());
|
||||||
|
assert!(!registers.get_zero_flag());
|
||||||
|
assert_eq!(registers.p, 0b1111_1100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod bus;
|
pub mod bus;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
pub mod common;
|
||||||
|
|||||||
Reference in New Issue
Block a user