mirror of
https://github.com/FranLMSP/snes.git
synced 2026-08-03 08:30:01 -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::alu;
|
||||
|
||||
type F = crate::common::flags::Flags;
|
||||
|
||||
impl CPU {
|
||||
fn get_8bit_from_address(&self, bus: &Bus, addressing_mode: AddressingMode) -> u8 {
|
||||
addressing_mode.value_8bit(
|
||||
@@ -29,34 +31,31 @@ impl CPU {
|
||||
// Otherwise, 16 bit addition
|
||||
let carry_flag = self.registers.get_carry_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;
|
||||
match is_8bit {
|
||||
true => {
|
||||
let value = self.get_8bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||
true => alu::adc_bcd(target as u8, value, carry_flag),
|
||||
false => alu::adc_bin(target as u8, value, carry_flag),
|
||||
};
|
||||
self.registers.set_low_a(result as u8);
|
||||
self.registers.set_carry_flag(is_carry);
|
||||
self.registers.set_negative_flag(is_negative);
|
||||
self.registers.set_zero_flag(is_zero);
|
||||
self.registers.set_overflow_flag(is_overflow);
|
||||
},
|
||||
false => {
|
||||
let value = self.get_16bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||
true => alu::adc_bcd(target, value, carry_flag),
|
||||
false => alu::adc_bin(target, value, carry_flag),
|
||||
};
|
||||
self.registers.a = result;
|
||||
self.registers.set_carry_flag(is_carry);
|
||||
self.registers.set_negative_flag(is_negative);
|
||||
self.registers.set_zero_flag(is_zero);
|
||||
self.registers.set_overflow_flag(is_overflow);
|
||||
}
|
||||
};
|
||||
if is_16bit {
|
||||
let value = self.get_16bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||
true => alu::adc_bcd(target, value, carry_flag),
|
||||
false => alu::adc_bin(target, value, carry_flag),
|
||||
};
|
||||
self.registers.a = result;
|
||||
self.registers.set_flags(&[
|
||||
F::Carry(is_carry), F::Negative(is_negative),
|
||||
F::Zero(is_zero), F::Overflow(is_overflow),
|
||||
]);
|
||||
} else {
|
||||
let value = self.get_8bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||
true => alu::adc_bcd(target as u8, value, carry_flag),
|
||||
false => alu::adc_bin(target as u8, value, carry_flag),
|
||||
};
|
||||
self.registers.set_low_a(result as u8);
|
||||
self.registers.set_flags(&[
|
||||
F::Carry(is_carry), F::Negative(is_negative),
|
||||
F::Zero(is_zero), F::Overflow(is_overflow),
|
||||
]);
|
||||
}
|
||||
self.increment_cycles_arithmetic(addressing_mode);
|
||||
}
|
||||
|
||||
@@ -65,34 +64,31 @@ impl CPU {
|
||||
// Otherwise, 16 bit addition
|
||||
let carry_flag = self.registers.get_carry_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;
|
||||
match is_8bit {
|
||||
true => {
|
||||
let value = self.get_8bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||
true => alu::sbc_bcd(target as u8, value, carry_flag),
|
||||
false => alu::sbc_bin(target as u8, value, carry_flag),
|
||||
};
|
||||
self.registers.set_low_a(result as u8);
|
||||
self.registers.set_carry_flag(is_carry);
|
||||
self.registers.set_negative_flag(is_negative);
|
||||
self.registers.set_zero_flag(is_zero);
|
||||
self.registers.set_overflow_flag(is_overflow);
|
||||
},
|
||||
false => {
|
||||
let value = self.get_16bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||
true => alu::sbc_bcd(target, value, carry_flag),
|
||||
false => alu::sbc_bin(target, value, carry_flag),
|
||||
};
|
||||
self.registers.a = result;
|
||||
self.registers.set_carry_flag(is_carry);
|
||||
self.registers.set_negative_flag(is_negative);
|
||||
self.registers.set_zero_flag(is_zero);
|
||||
self.registers.set_overflow_flag(is_overflow);
|
||||
}
|
||||
};
|
||||
if is_16bit {
|
||||
let value = self.get_16bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||
true => alu::sbc_bcd(target, value, carry_flag),
|
||||
false => alu::sbc_bin(target, value, carry_flag),
|
||||
};
|
||||
self.registers.a = result;
|
||||
self.registers.set_flags(&[
|
||||
F::Carry(is_carry), F::Negative(is_negative),
|
||||
F::Zero(is_zero), F::Overflow(is_overflow),
|
||||
]);
|
||||
} else {
|
||||
let value = self.get_8bit_from_address(bus, addressing_mode);
|
||||
let (result, is_carry, is_negative, is_zero, is_overflow) = match is_decimal_mode {
|
||||
true => alu::sbc_bcd(target as u8, value, carry_flag),
|
||||
false => alu::sbc_bin(target as u8, value, carry_flag),
|
||||
};
|
||||
self.registers.set_low_a(result as u8);
|
||||
self.registers.set_flags(&[
|
||||
F::Carry(is_carry), F::Negative(is_negative),
|
||||
F::Zero(is_zero), F::Overflow(is_overflow),
|
||||
]);
|
||||
}
|
||||
self.increment_cycles_arithmetic(addressing_mode);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use crate::common::flags::Flags;
|
||||
|
||||
pub struct Registers {
|
||||
pub sp: u16, // Stack pointer
|
||||
pub x: u16, // Index X
|
||||
@@ -131,6 +133,23 @@ impl Registers {
|
||||
pub fn direct_page_low(&self) -> 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)]
|
||||
@@ -243,5 +262,28 @@ mod registers_tests {
|
||||
assert!(!registers.get_overflow_flag());
|
||||
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 bus;
|
||||
pub mod utils;
|
||||
pub mod common;
|
||||
|
||||
Reference in New Issue
Block a user