ADC function

This commit is contained in:
2022-06-26 20:23:26 -05:00
parent 4f802b33e2
commit c7a38ecc95
+90 -24
View File
@@ -8,6 +8,7 @@ struct Registers {
pbr: u8, // Program bank register pbr: u8, // Program bank register
dbr: u8, // Data bank register dbr: u8, // Data bank register
pc: u16, // Program counter pc: u16, // Program counter
emulation_mode: bool, // Program counter
} }
impl Registers { impl Registers {
@@ -22,17 +23,10 @@ impl Registers {
pbr: 0, pbr: 0,
dbr: 0, dbr: 0,
pc: 0, pc: 0,
emulation_mode: false,
} }
} }
pub fn get_p(&self) -> u8 {
self.p
}
pub fn set_p(&mut self, val: u8) {
self.p = val;
}
pub fn get_carry_flag(&self) -> bool { pub fn get_carry_flag(&self) -> bool {
(self.p & 0b0000_0001) == 1 (self.p & 0b0000_0001) == 1
} }
@@ -78,6 +72,15 @@ impl Registers {
self.p = self.p | ((val as u8) << 4); self.p = self.p | ((val as u8) << 4);
} }
pub fn get_memory_select_flag(&self) -> bool {
((self.p & 0b0010_0000) >> 5) == 1
}
pub fn set_memory_select_flag(&mut self, val: bool) {
self.p = self.p & 0b1101_1111;
self.p = self.p | ((val as u8) << 5);
}
pub fn get_overflow_flag(&self) -> bool { pub fn get_overflow_flag(&self) -> bool {
((self.p & 0b0100_0000) >> 6) == 1 ((self.p & 0b0100_0000) >> 6) == 1
} }
@@ -110,8 +113,39 @@ impl CPU {
} }
} }
pub fn adc(&mut self, value: u16) {
let carry = self.registers.get_carry_flag();
let carry_result = match self.registers.a.checked_add(value) {
None => true,
Some(res) => match res.checked_add(carry as u16) {
None => true,
Some(_) => false,
},
};
self.registers.a = self.registers.a
.wrapping_add(value)
.wrapping_add(carry as u16);
self.registers.set_carry_flag(carry_result);
}
pub fn adc_const(&mut self, value: u16) { pub fn adc_const(&mut self, value: u16) {
self.registers.pc.wrapping_add(2);
self.cycles += 2; self.cycles += 2;
if self.registers.get_memory_select_flag() {
self.registers.pc.wrapping_add(1);
self.cycles += 1;
}
if self.registers.get_decimal_mode_flag() {
self.cycles += 1;
}
self.adc(value);
}
pub fn decode_instruction(&mut self, opcode: u8) {
match opcode {
0x69 => self.adc_const(0x00), // TODO: read value from Bus
_ => (),
}
} }
} }
@@ -120,11 +154,36 @@ impl CPU {
mod cpu_instructions_tests { mod cpu_instructions_tests {
use super::*; use super::*;
#[test] #[test]
fn test_adc_const() { fn test_adc() {
let mut cpu = CPU::new(); let mut cpu = CPU::new();
assert!(true); cpu.registers.a = 0x00;
cpu.adc(0x40);
assert_eq!(cpu.registers.a, 0x40);
assert!(!cpu.registers.get_carry_flag());
cpu.registers.a = 0xFFFF;
cpu.adc(0x01);
assert_eq!(cpu.registers.a, 0x0000);
assert!(cpu.registers.get_carry_flag());
cpu.registers.a = 0xFFFF;
cpu.registers.set_carry_flag(true);
cpu.adc(0x01);
assert_eq!(cpu.registers.a, 0x0001);
assert!(cpu.registers.get_carry_flag());
cpu.registers.a = 0xFFFD;
cpu.registers.set_carry_flag(true);
cpu.adc(0x01);
assert_eq!(cpu.registers.a, 0xFFFF);
assert!(!cpu.registers.get_carry_flag());
cpu.registers.a = 0x0000;
cpu.registers.set_carry_flag(true);
cpu.adc(0x01);
assert_eq!(cpu.registers.a, 0x0002);
assert!(!cpu.registers.get_carry_flag());
} }
} }
@@ -137,49 +196,56 @@ mod cpu_registers_tests {
#[test] #[test]
fn test_status_registers() { fn test_status_registers() {
let mut registers = Registers::new(); let mut registers = Registers::new();
registers.set_p(0x00); registers.p = 0x00;
registers.set_carry_flag(true); registers.set_carry_flag(true);
assert!(registers.get_carry_flag()); assert!(registers.get_carry_flag());
assert_eq!(registers.get_p(), 0b0000_0001); assert_eq!(registers.p, 0b0000_0001);
registers.set_carry_flag(false); registers.set_carry_flag(false);
assert!(!registers.get_carry_flag()); assert!(!registers.get_carry_flag());
assert_eq!(registers.get_p(), 0b0000_0000); assert_eq!(registers.p, 0b0000_0000);
registers.set_zero_flag(true); registers.set_zero_flag(true);
assert!(registers.get_zero_flag()); assert!(registers.get_zero_flag());
assert_eq!(registers.get_p(), 0b0000_0010); assert_eq!(registers.p, 0b0000_0010);
registers.set_zero_flag(false); registers.set_zero_flag(false);
assert!(!registers.get_zero_flag()); assert!(!registers.get_zero_flag());
assert_eq!(registers.get_p(), 0b0000_0000); assert_eq!(registers.p, 0b0000_0000);
registers.set_irq_disable_flag(true); registers.set_irq_disable_flag(true);
assert!(registers.get_irq_disable_flag()); assert!(registers.get_irq_disable_flag());
assert_eq!(registers.get_p(), 0b0000_0100); assert_eq!(registers.p, 0b0000_0100);
registers.set_irq_disable_flag(false); registers.set_irq_disable_flag(false);
assert!(!registers.get_irq_disable_flag()); assert!(!registers.get_irq_disable_flag());
assert_eq!(registers.get_p(), 0b0000_0000); assert_eq!(registers.p, 0b0000_0000);
registers.set_decimal_mode_flag(true); registers.set_decimal_mode_flag(true);
assert!(registers.get_decimal_mode_flag()); assert!(registers.get_decimal_mode_flag());
assert_eq!(registers.get_p(), 0b0000_1000); assert_eq!(registers.p, 0b0000_1000);
registers.set_decimal_mode_flag(false); registers.set_decimal_mode_flag(false);
assert!(!registers.get_decimal_mode_flag()); assert!(!registers.get_decimal_mode_flag());
assert_eq!(registers.get_p(), 0b0000_0000); assert_eq!(registers.p, 0b0000_0000);
registers.set_memory_select_flag(true);
assert!(registers.get_memory_select_flag());
assert_eq!(registers.p, 0b0010_0000);
registers.set_memory_select_flag(false);
assert!(!registers.get_memory_select_flag());
assert_eq!(registers.p, 0b0000_0000);
registers.set_break_instruction_flag(true); registers.set_break_instruction_flag(true);
assert!(registers.get_break_instruction_flag()); assert!(registers.get_break_instruction_flag());
assert_eq!(registers.get_p(), 0b0001_0000); assert_eq!(registers.p, 0b0001_0000);
registers.set_break_instruction_flag(false); registers.set_break_instruction_flag(false);
assert!(!registers.get_break_instruction_flag()); assert!(!registers.get_break_instruction_flag());
assert_eq!(registers.get_p(), 0b0000_0000); assert_eq!(registers.p, 0b0000_0000);
registers.set_overflow_flag(true); registers.set_overflow_flag(true);
assert!(registers.get_overflow_flag()); assert!(registers.get_overflow_flag());
assert_eq!(registers.get_p(), 0b0100_0000); assert_eq!(registers.p, 0b0100_0000);
registers.set_overflow_flag(false); registers.set_overflow_flag(false);
assert!(!registers.get_overflow_flag()); assert!(!registers.get_overflow_flag());
assert_eq!(registers.get_p(), 0b0000_0000); assert_eq!(registers.p, 0b0000_0000);
} }
} }