set_flags function

This commit is contained in:
2022-11-23 21:57:41 -05:00
parent fa230e4a52
commit fbee6fa8e9
6 changed files with 118 additions and 54 deletions
+14
View File
@@ -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),
}
+9
View File
@@ -0,0 +1,9 @@
pub trait CPUInstruction {
fn execute();
}
pub struct ADC {}
impl CPUInstruction for ADC {
fn execute () {
}
}
+2
View File
@@ -0,0 +1,2 @@
pub mod instructions;
pub mod flags;
+50 -54
View File
@@ -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);
}
+42
View File
@@ -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
View File
@@ -1,3 +1,4 @@
pub mod cpu;
pub mod bus;
pub mod utils;
pub mod common;