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 arithmetic;
|
||||||
|
pub mod branch;
|
||||||
pub mod transfer;
|
pub mod transfer;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue