From b1c518fcc847157b8afc8cda21d5ffef5523b975 Mon Sep 17 00:00:00 2001 From: pcasaretto Date: Tue, 9 Apr 2024 00:02:47 -0300 Subject: [PATCH] pushes and pops --- src/instructions/mod.rs | 11 +++++++ src/instructions/stack.rs | 63 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 7 ++++- 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/instructions/stack.rs diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index a4db3d3..817336a 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -8,6 +8,7 @@ mod int; mod jmp; mod ld; mod nop; +mod stack; mod sub; use super::*; @@ -153,6 +154,16 @@ pub fn from_byte(byte: u8) -> Box { 0xA6 => Box::new(and::and_mem_at_r16(Register16bTarget::HL)), 0xA7 => Box::new(and::and(RegisterTarget::A)), + 0xC1 => Box::new(stack::pop(Register16bTarget::BC)), + 0xD1 => Box::new(stack::pop(Register16bTarget::DE)), + 0xE1 => Box::new(stack::pop(Register16bTarget::HL)), + 0xF1 => Box::new(stack::pop(Register16bTarget::AF)), + + 0xC5 => Box::new(stack::push(Register16bTarget::BC)), + 0xD5 => Box::new(stack::push(Register16bTarget::DE)), + 0xE5 => Box::new(stack::push(Register16bTarget::HL)), + 0xF5 => Box::new(stack::push(Register16bTarget::AF)), + 0xCD => Box::new(call::call_a16()), 0xC9 => Box::new(call::ret()), diff --git a/src/instructions/stack.rs b/src/instructions/stack.rs new file mode 100644 index 0000000..ad7b535 --- /dev/null +++ b/src/instructions/stack.rs @@ -0,0 +1,63 @@ +use crate::{Register16bTarget, CPU}; + +pub fn push(reg: Register16bTarget) -> impl Fn(&mut CPU) { + move |cpu: &mut CPU| { + let value = cpu.registers.get_u16(reg); + let [high, low] = value.to_be_bytes(); + cpu.registers.sp = cpu.registers.sp.wrapping_sub(1); + cpu.bus.write_byte(cpu.registers.sp, high); + cpu.registers.sp = cpu.registers.sp.wrapping_sub(1); + cpu.bus.write_byte(cpu.registers.sp, low); + } +} + +pub fn pop(reg: Register16bTarget) -> impl Fn(&mut CPU) { + move |cpu: &mut CPU| { + let low = cpu.bus.read_byte(cpu.registers.sp); + cpu.registers.sp = cpu.registers.sp.wrapping_add(1); + let high = cpu.bus.read_byte(cpu.registers.sp); + cpu.registers.sp = cpu.registers.sp.wrapping_add(1); + cpu.registers.set_u16(reg, u16::from_be_bytes([high, low])); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{FlagsRegister, Registers}; + + #[test] + fn test_push() { + let mut cpu = CPU { + registers: Registers { + sp: 0xFFFE, + b: 0x01, + c: 0x02, + ..Default::default() + }, + ..Default::default() + }; + push(Register16bTarget::BC)(&mut cpu); + assert_eq!(cpu.registers.sp, 0xFFFC); + assert_eq!(cpu.bus.memory[0xFFFD], 0x01); + assert_eq!(cpu.bus.memory[0xFFFC], 0x02); + } + + #[test] + fn test_pop() { + let mut cpu = CPU { + registers: Registers { + sp: 0xFFFC, + b: 0x00, + c: 0x00, + ..Default::default() + }, + ..Default::default() + }; + cpu.bus.memory[0xFFFC] = 0x01; + cpu.bus.memory[0xFFFD] = 0x02; + pop(Register16bTarget::BC)(&mut cpu); + assert_eq!(cpu.registers.get_u16(Register16bTarget::BC), 0x0201); + assert_eq!(cpu.registers.sp, 0xFFFE); + } +} diff --git a/src/lib.rs b/src/lib.rs index 910a0a3..1704dac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ pub enum RegisterTarget { #[derive(Debug, Copy, Clone)] pub enum Register16bTarget { + AF, BC, DE, HL, @@ -60,6 +61,7 @@ impl Registers { pub fn get_u16(&self, target: Register16bTarget) -> u16 { match target { + Register16bTarget::AF => u16::from_be_bytes([self.a, u8::from(self.f)]), Register16bTarget::BC => u16::from_be_bytes([self.b, self.c]), Register16bTarget::DE => u16::from_be_bytes([self.d, self.e]), Register16bTarget::HL => u16::from_be_bytes([self.h, self.l]), @@ -83,11 +85,14 @@ impl Registers { self.l = low; } Register16bTarget::SP => self.sp = value, + Register16bTarget::AF => { + panic!("Cannot set AF register") + } } } } -#[derive(Default)] +#[derive(Default, Copy, Clone)] pub struct FlagsRegister { pub zero: bool, pub subtract: bool,