branching instructions

that's all of the 8080 instruction set besides the I/O instructions

god bless
This commit is contained in:
Martin Löffler 2023-01-28 07:31:19 +01:00
parent 01b87ade6d
commit 465aadd54e
Signed by: FatalErrorCoded
GPG key ID: FFEF368AC076566A
4 changed files with 102 additions and 3 deletions

View file

@ -0,0 +1,52 @@
use crate::transfer::{pop, push};
use crate::{get_register_pair, EmulatorState, Register};
/// Jump (set PC) to specified address
pub fn jump(address: u16, state: &mut EmulatorState) {
state.pc = address;
}
/// Jump to a specified address only if `cond` is true
pub fn jump_cond(address: u16, cond: bool, state: &mut EmulatorState) {
if cond {
jump(address, state);
}
}
/// Push the current PC to the stack and jump to the specified address
pub fn call(address: u16, state: &mut EmulatorState) {
push(state.pc, state);
jump(address, state);
}
// Push the current PC to the stack and jump to the specified address if `cond` is true
pub fn call_cond(address: u16, cond: bool, state: &mut EmulatorState) {
if cond {
call(address, state);
}
}
// Pop a value from the stack and jump to it
pub fn ret(state: &mut EmulatorState) {
jump(pop(state), state);
}
// Pop a value from the stack and jump to it if `cond` is true
pub fn ret_cond(cond: bool, state: &mut EmulatorState) {
if cond {
ret(state)
}
}
/// "Restart" at (call) a specific interrupt vector
///
/// Panics if `vector` is 8 or above
pub fn restart(vector: u8, state: &mut EmulatorState) {
assert!(vector < 8, "Illegal restart vector");
call((vector * 8) as u16, state);
}
/// Load a new program counter from the HL register pair
pub fn pchl(state: &mut EmulatorState) {
state.pc = get_register_pair(Register::H, state);
}

View file

@ -1,2 +1,3 @@
pub mod arithmetic; pub mod arithmetic;
pub mod branch;
pub mod transfer; pub mod transfer;

View file

@ -1,6 +1,5 @@
use crate::{ use crate::{
get_register, get_register_pair, set_register, structs::set_register_pair, EmulatorState, get_register, get_register_pair, set_register, set_register_pair, EmulatorState, Register,
Register,
}; };
/// Move (copy) value from source to destination register /// Move (copy) value from source to destination register

View file

@ -1,4 +1,4 @@
use instructions::{arithmetic, transfer}; use instructions::{arithmetic, branch, transfer};
use std::{env, fs}; use std::{env, fs};
use crate::structs::*; use crate::structs::*;
@ -164,6 +164,53 @@ fn tick(state: &mut EmulatorState) {
0xf6 => arithmetic::or(state.next_byte(), state), // ORI 0xf6 => arithmetic::or(state.next_byte(), state), // ORI
0xfe => arithmetic::cmp(state.next_byte(), state), // CPI 0xfe => arithmetic::cmp(state.next_byte(), state), // CPI
/* Branch instructions */
// Jumps
0xc2 => branch::jump_cond(state.next_word(), !state.cc.z, state), // JNZ
0xc3 => branch::jump(state.next_word(), state), // JMP
0xca => branch::jump_cond(state.next_word(), state.cc.z, state), // JZ
0xd2 => branch::jump_cond(state.next_word(), !state.cc.c, state), // JNC
0xda => branch::jump_cond(state.next_word(), state.cc.c, state), // JC
0xe2 => branch::jump_cond(state.next_word(), !state.cc.p, state), // JPO
0xea => branch::jump_cond(state.next_word(), state.cc.p, state), // JPE
0xf2 => branch::jump_cond(state.next_word(), !state.cc.s, state), // JP
0xfa => branch::jump_cond(state.next_word(), state.cc.s, state), // JM
// Calls
0xc4 => branch::call_cond(state.next_word(), !state.cc.z, state), // CNZ
0xcc => branch::call_cond(state.next_word(), state.cc.z, state), // CZ
0xcd => branch::call(state.next_word(), state), // CALL
0xd4 => branch::call_cond(state.next_word(), !state.cc.c, state), // CNC
0xdc => branch::call_cond(state.next_word(), state.cc.c, state), // CC
0xe4 => branch::call_cond(state.next_word(), !state.cc.p, state), // CPO
0xec => branch::call_cond(state.next_word(), state.cc.p, state), // CPE
0xf4 => branch::call_cond(state.next_word(), !state.cc.s, state), // CP
0xfc => branch::call_cond(state.next_word(), state.cc.s, state), // CM
// Returns
0xc0 => branch::ret_cond(!state.cc.z, state), // RNZ
0xc8 => branch::ret_cond(state.cc.z, state), // RZ
0xc9 => branch::ret(state), // RET
0xd0 => branch::ret_cond(!state.cc.c, state), // RNC
0xd8 => branch::ret_cond(state.cc.c, state), // RC
0xe0 => branch::ret_cond(!state.cc.p, state), // RPO
0xe8 => branch::ret_cond(state.cc.p, state), // RPE
0xf0 => branch::ret_cond(!state.cc.s, state), // RP
0xf8 => branch::ret_cond(state.cc.s, state), // RM
// Restarts
0xc7 => branch::restart(0, state),
0xcf => branch::restart(1, state),
0xd7 => branch::restart(2, state),
0xdf => branch::restart(3, state),
0xe7 => branch::restart(4, state),
0xef => branch::restart(5, state),
0xf7 => branch::restart(6, state),
0xff => branch::restart(7, state),
// PCHL
0xe9 => branch::pchl(state),
_ => not_implemented(state), _ => not_implemented(state),
} }