Skip to content

Commit

Permalink
pushes and pops
Browse files Browse the repository at this point in the history
  • Loading branch information
pcasaretto committed Apr 9, 2024
1 parent b7b6dd8 commit b1c518f
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 1 deletion.
11 changes: 11 additions & 0 deletions src/instructions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod int;
mod jmp;
mod ld;
mod nop;
mod stack;
mod sub;

use super::*;
Expand Down Expand Up @@ -153,6 +154,16 @@ pub fn from_byte(byte: u8) -> Box<dyn Fn(&mut CPU)> {
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()),

Expand Down
63 changes: 63 additions & 0 deletions src/instructions/stack.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub enum RegisterTarget {

#[derive(Debug, Copy, Clone)]
pub enum Register16bTarget {
AF,
BC,
DE,
HL,
Expand Down Expand Up @@ -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]),
Expand All @@ -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,
Expand Down

0 comments on commit b1c518f

Please sign in to comment.