stack instructions

This commit is contained in:
Martin Löffler 2023-01-28 05:39:05 +01:00
parent 6d26e7de54
commit 8b86db359e
Signed by: FatalErrorCoded
GPG key ID: FFEF368AC076566A
3 changed files with 83 additions and 2 deletions

View file

@ -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);
}
}

View file

@ -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),

View file

@ -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]