Compare commits

..

No commits in common. "c35340ecce38ab2af0cc4444ee920251129f941e" and "7737ab8de555f650f517b0e096084125a92074db" have entirely different histories.

3 changed files with 34 additions and 84 deletions

View file

@ -1,5 +1,4 @@
use crate::structs::{get_register_pair, set_register, set_register_pair};
use crate::{get_register, EmulatorState, Register};
use crate::{get_register, structs::set_register, EmulatorState, Register};
/// Sets the condition code flags according to `result`. `flags` parameter
/// indicates which flags will be set, 0b1111 will set all (Z, S, C, P)
@ -21,7 +20,7 @@ fn set_cc(state: &mut EmulatorState, result: u16, flags: u8) {
/// Add values of `register` and `A`
pub fn add(register: Register, state: &mut EmulatorState) {
let result = get_register(register, state) as u16 + state.a as u16;
let result = get_register(&register, state) as u16 + state.a as u16;
set_cc(state, result, 0b1111);
state.a = (result & 0xff) as u8;
}
@ -35,7 +34,7 @@ pub fn adi(byte: u8, state: &mut EmulatorState) {
/// Add values of `register` and `A` and add +1 if carry bit is set
pub fn adc(register: Register, state: &mut EmulatorState) {
let result = get_register(register, state) as u16 + state.a as u16 + u16::from(state.cc.c);
let result = get_register(&register, state) as u16 + state.a as u16 + u16::from(state.cc.c);
set_cc(state, result, 0b1111);
state.a = (result & 0xff) as u8;
}
@ -49,22 +48,30 @@ pub fn aci(byte: u8, state: &mut EmulatorState) {
/// Double precision add - Add B&C, D&E or H&L to H&L
pub fn dad(register: Register, state: &mut EmulatorState) {
let num = get_register_pair(register, state);
let num = match register {
Register::B => u16::from_le_bytes([state.c, state.b]),
Register::D => u16::from_le_bytes([state.e, state.d]),
Register::H => u16::from_le_bytes([state.l, state.h]),
Register::SP => state.sp,
_ => panic!("Cannot perform DAD on register {:?}", register),
};
let (result, overflow) = num.overflowing_add(u16::from_le_bytes([state.l, state.h]));
state.cc.c = overflow;
set_register_pair(register, result, state);
state.h = (result >> 8) as u8;
state.l = result as u8;
}
/// Increase register
pub fn inr(register: Register, state: &mut EmulatorState) {
let (result, _) = get_register(register, state).overflowing_add(1);
let (result, _) = get_register(&register, state).overflowing_add(1);
set_cc(state, result as u16, 0b1101);
set_register(register, result, state);
set_register(&register, result, state);
}
/// Decrease register
pub fn dcr(register: Register, state: &mut EmulatorState) {
let (result, _) = get_register(register, state).overflowing_sub(1);
let (result, _) = get_register(&register, state).overflowing_sub(1);
set_cc(state, result as u16, 0b1101);
set_register(register, result, state);
set_register(&register, result, state);
}

View file

@ -58,20 +58,6 @@ fn tick(state: &mut EmulatorState) {
match instruction {
0x00 => {} // NOP
/* Special */
0xfb => state.ei = true, // EI
0xf3 => state.ei = false, // DI
0x76 => {
if state.ei {
todo!()
} else {
// HLT
println!("HLT called after DI; exiting.");
print_state(state);
std::process::exit(0);
}
}
/* Maths */
// INR
0x04 => arithmetic::inr(Register::B, state),
@ -104,6 +90,20 @@ fn tick(state: &mut EmulatorState) {
0xc6 => arithmetic::adi(next_byte(), state), // ADI
0xce => arithmetic::aci(next_byte(), state), // ACI
/* Special */
0xfb => state.ei = true, // EI
0xf3 => state.ei = false, // DI
0x76 => {
if state.ei {
todo!()
} else {
// HLT
println!("HLT called after DI; exiting.");
print_state(state);
std::process::exit(0);
}
}
_ => not_implemented(state),
}

View file

@ -1,6 +1,5 @@
use crate::MEMORY_SIZE;
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct EmulatorState {
pub a: u8,
pub b: u8,
@ -22,7 +21,6 @@ pub struct EmulatorState {
pub memory: [u8; MEMORY_SIZE],
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct ConditionCodes {
/// Zero (Z), set if the result is zero.
pub z: bool,
@ -37,7 +35,7 @@ pub struct ConditionCodes {
// ac: bool,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[derive(PartialEq, Debug)]
pub enum Register {
B,
C,
@ -65,7 +63,7 @@ pub fn register_from_num(b: u8) -> Register {
}
}
pub fn get_register(register: Register, state: &EmulatorState) -> u8 {
pub fn get_register(register: &Register, state: &EmulatorState) -> u8 {
match register {
Register::B => state.b,
Register::C => state.c,
@ -79,7 +77,7 @@ pub fn get_register(register: Register, state: &EmulatorState) -> u8 {
}
}
pub fn set_register(register: Register, value: u8, state: &mut EmulatorState) {
pub fn set_register(register: &Register, value: u8, state: &mut EmulatorState) {
match register {
Register::B => state.b = value,
Register::C => state.c = value,
@ -93,61 +91,6 @@ pub fn set_register(register: Register, value: u8, state: &mut EmulatorState) {
};
}
pub fn get_register_pair(register: Register, state: &mut EmulatorState) -> u16 {
match register {
Register::B => u16::from_le_bytes([state.c, state.b]),
Register::D => u16::from_le_bytes([state.e, state.d]),
Register::H => u16::from_le_bytes([state.l, state.h]),
Register::A => {
// the PSW looks like this: SZ0A0P1C
let flags: u8 = u8::from(state.cc.s) << 7 // bit 7
| u8::from(state.cc.z) << 6 // bit 6
//| u8::from(state.cc.a) << 4 // bit 4
| u8::from(state.cc.p) << 2 // bit 2
| 0x02 // bit 1
| u8::from(state.cc.c); // bit 0
u16::from_le_bytes([flags, state.a])
}
Register::SP => state.sp,
_ => unreachable!(),
}
}
pub fn set_register_pair(register: Register, value: u16, state: &mut EmulatorState) {
let arr = value.to_le_bytes();
let high = arr[1];
let low = arr[0];
match register {
Register::B => {
state.b = high;
state.c = low;
}
Register::D => {
state.d = high;
state.e = low;
}
Register::H => {
state.h = high;
state.l = low;
}
Register::A => {
state.a = high;
// the PSW looks like this: SZ0A0P1C
state.cc.s = low & 0b1000_0000 > 0;
state.cc.z = low & 0b0100_0000 > 0;
debug_assert!(low & 0b0010_0000 == 0, "malformed PSW");
//state.cc.a = low & 0b0001_0000 > 0;
debug_assert!(low & 0b0000_1000 == 0, "malformed PSW");
state.cc.p = low & 0b0000_0100 > 0;
debug_assert!(low & 0b0000_0010 > 0, "malformed PSW");
state.cc.c = low & 0b0000_0001 > 0;
}
Register::SP => state.sp = value,
_ => unreachable!(),
}
}
/// Print values of registers and flags to stdout
pub fn print_state(state: &EmulatorState) {
// State