forked from Lea/invadeez
branching instructions
that's all of the 8080 instruction set besides the I/O instructions god bless
This commit is contained in:
parent
01b87ade6d
commit
465aadd54e
52
src/emulator/instructions/branch.rs
Normal file
52
src/emulator/instructions/branch.rs
Normal 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);
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
pub mod arithmetic;
|
||||
pub mod branch;
|
||||
pub mod transfer;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::{
|
||||
get_register, get_register_pair, set_register, structs::set_register_pair, EmulatorState,
|
||||
Register,
|
||||
get_register, get_register_pair, set_register, set_register_pair, EmulatorState, Register,
|
||||
};
|
||||
|
||||
/// Move (copy) value from source to destination register
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use instructions::{arithmetic, transfer};
|
||||
use instructions::{arithmetic, branch, transfer};
|
||||
use std::{env, fs};
|
||||
|
||||
use crate::structs::*;
|
||||
|
@ -164,6 +164,53 @@ fn tick(state: &mut EmulatorState) {
|
|||
0xf6 => arithmetic::or(state.next_byte(), state), // ORI
|
||||
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),
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue