From 8b86db359e8bc754d9c02755e263201c1690f75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20L=C3=B6ffler?= Date: Sat, 28 Jan 2023 05:39:05 +0100 Subject: [PATCH] stack instructions --- src/emulator/instructions/transfer.rs | 73 ++++++++++++++++++++++++++- src/emulator/main.rs | 10 ++++ src/emulator/structs.rs | 2 +- 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/emulator/instructions/transfer.rs b/src/emulator/instructions/transfer.rs index db7102e..4075ac6 100644 --- a/src/emulator/instructions/transfer.rs +++ b/src/emulator/instructions/transfer.rs @@ -1,4 +1,7 @@ -use crate::{get_register, get_register_pair, set_register, EmulatorState, Register}; +use crate::{ + get_register, get_register_pair, set_register, structs::set_register_pair, EmulatorState, + Register, +}; /// Move (copy) value from source to destination register pub fn mov(src: Register, dest: Register, state: &mut EmulatorState) { @@ -34,3 +37,71 @@ pub fn lhld(address: u16, state: &mut EmulatorState) { state.l = state.memory[address as usize]; state.h = state.memory[address as usize + 1]; } + +/* STACK */ +/// Push a 16-bit value from a register pair onto the stack +pub fn push_reg(register: Register, state: &mut EmulatorState) { + push(get_register_pair(register, state), state); +} + +pub fn push(value: u16, state: &mut EmulatorState) { + (state.sp, ..) = state.sp.overflowing_sub(2); + state.write_word(state.sp, value); +} + +/// Pop a 16-bit value from the stack into a register pair +pub fn pop_reg(register: Register, state: &mut EmulatorState) { + set_register_pair(register, pop(state), state); +} + +pub fn pop(state: &mut EmulatorState) -> u16 { + let value = state.read_word(state.sp); + (state.sp, ..) = state.sp.overflowing_add(2); + value +} + +#[cfg(test)] +mod tests { + use crate::EmulatorState; + + #[test] + fn push() { + // From the altairclone.com 8080 programmers manual: + // (1) The most significant 8 bits of data are stored at the + // memory address one less than the contents of the + // stack pointer. + // (2) The least significant 8 bits of data are stored at the + // memory address two less than the contents of the + // stack pointer. + // (3) The stack pointer is automatically decremented by two. + let mut state = EmulatorState { + sp: 0x12, + ..Default::default() + }; + + super::push(0x1234, &mut state); + assert_eq!(state.sp, 0x10); + assert_eq!(state.memory[0x10..=0x11], [0x34, 0x12]); + } + + #[test] + fn pop() { + // From the altairclone.com 8080 programmers manual: + // (1) The second register of the pair, or the least significant + // 8 bits of the program counter, are loaded from the + // memory address held in the stack pointer. + // (2) The first register of the pair, or the most significant + // 8 bits of the program counter, are loaded from the + // memory address one greater than the address held in + // the stack pointer. + // (3) The stack pointer is automatically incremented by two. + let mut state = EmulatorState { + sp: 0x10, + ..Default::default() + }; + + state.memory[0x10] = 0x34; + state.memory[0x11] = 0x12; + assert_eq!(super::pop(&mut state), 0x1234); + } +} diff --git a/src/emulator/main.rs b/src/emulator/main.rs index 378a6b5..d2aa2b9 100644 --- a/src/emulator/main.rs +++ b/src/emulator/main.rs @@ -80,6 +80,16 @@ fn tick(state: &mut EmulatorState) { 0x22 => transfer::shld(state.next_word(), state), // SHLD 0x2a => transfer::lhld(state.next_word(), state), // LHLD + // Stack instructions + 0xc1 => transfer::pop_reg(Register::B, state), // POP B + 0xc5 => transfer::push_reg(Register::B, state), // PUSH B + 0xd1 => transfer::pop_reg(Register::D, state), // POP D + 0xd5 => transfer::push_reg(Register::D, state), // PUSH D + 0xe1 => transfer::pop_reg(Register::H, state), // POP H + 0xe5 => transfer::push_reg(Register::H, state), // PUSH H + 0xf1 => transfer::pop_reg(Register::A, state), // POP PSW + 0xf5 => transfer::push_reg(Register::A, state), // PUSH PSW + /* Maths */ // INR 0x04 => arithmetic::inr(Register::B, state), diff --git a/src/emulator/structs.rs b/src/emulator/structs.rs index 4d586d7..a129516 100644 --- a/src/emulator/structs.rs +++ b/src/emulator/structs.rs @@ -241,7 +241,7 @@ mod tests { fn write_word() { let mut state = EmulatorState::default(); state.write_word(0x10, 0x1234); - assert_eq!([0x34, 0x12], state.memory[0x10..0x12]); + assert_eq!(state.memory[0x10..=0x11], [0x34, 0x12]); } #[test]