forked from Lea/invadeez
stack instructions
This commit is contained in:
parent
6d26e7de54
commit
8b86db359e
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in a new issue