accumulator transfer instructions

This commit is contained in:
Martin Löffler 2023-01-26 06:02:11 +01:00
parent 6abdd5dff3
commit 2fff8d2448
Signed by: FatalErrorCoded
GPG key ID: FFEF368AC076566A
3 changed files with 49 additions and 15 deletions

View file

@ -1,10 +1,24 @@
use crate::{get_register, set_register, EmulatorState, Register}; use crate::{get_register, set_register, structs::get_register_pair, EmulatorState, Register};
/// Move (copy) value from source to destination register
pub fn mov(src: Register, dest: Register, state: &mut EmulatorState) { pub fn mov(src: Register, dest: Register, state: &mut EmulatorState) {
let data = get_register(src, state); let data = get_register(src, state);
set_register(dest, data, state); set_register(dest, data, state);
} }
/// Move immediate into destination register
pub fn mvi(byte: u8, dest: Register, state: &mut EmulatorState) { pub fn mvi(byte: u8, dest: Register, state: &mut EmulatorState) {
set_register(dest, byte, state); set_register(dest, byte, state);
} }
/// Store accumulator using the BC or DE register pair
pub fn stax(register: Register, state: &mut EmulatorState) {
let address = get_register_pair(register, state);
state.memory[address as usize] = state.a;
}
/// Load accumulator using the BC or DE register pair
pub fn ldax(register: Register, state: &mut EmulatorState) {
let address = get_register_pair(register, state);
state.a = state.memory[address as usize];
}

View file

@ -50,11 +50,6 @@ fn main() {
fn tick(state: &mut EmulatorState) { fn tick(state: &mut EmulatorState) {
let instruction = state.memory[state.pc as usize]; let instruction = state.memory[state.pc as usize];
let mut next_byte = || {
state.pc += 1;
state.memory[state.pc as usize]
};
match instruction { match instruction {
0x00 => {} // NOP 0x00 => {} // NOP
@ -75,7 +70,7 @@ fn tick(state: &mut EmulatorState) {
/* Data Transfer */ /* Data Transfer */
// MVI // MVI
0x06 | 0x0e | 0x16 | 0x1e | 0x26 | 0x2e | 0x36 | 0x3e => transfer::mvi( 0x06 | 0x0e | 0x16 | 0x1e | 0x26 | 0x2e | 0x36 | 0x3e => transfer::mvi(
next_byte(), state.next_byte(),
register_from_num((instruction & 0x38) >> 3), register_from_num((instruction & 0x38) >> 3),
state, state,
), ),
@ -87,6 +82,14 @@ fn tick(state: &mut EmulatorState) {
state, state,
), ),
// Accumulator transfer instructions
0x02 => transfer::stax(Register::B, state), // STAX B
0x0a => transfer::ldax(Register::B, state), // LDAX B
0x12 => transfer::stax(Register::D, state), // STAX D
0x1a => transfer::ldax(Register::D, state), // LDAX D
0x32 => state.memory[state.next_word() as usize] = state.a, // STA
0x3a => state.a = state.memory[state.next_word() as usize], // LDA
/* Maths */ /* Maths */
// INR // INR
0x04 => arithmetic::inr(Register::B, state), 0x04 => arithmetic::inr(Register::B, state),
@ -140,22 +143,22 @@ fn tick(state: &mut EmulatorState) {
0x80..=0x87 => arithmetic::add_reg(register_from_num(instruction & 0x7), false, state), // ADD 0x80..=0x87 => arithmetic::add_reg(register_from_num(instruction & 0x7), false, state), // ADD
0x88..=0x8f => arithmetic::add_reg(register_from_num(instruction & 0x7), state.cc.c, state), // ADC 0x88..=0x8f => arithmetic::add_reg(register_from_num(instruction & 0x7), state.cc.c, state), // ADC
0xc6 => arithmetic::add(next_byte(), false, state), // ADI 0xc6 => arithmetic::add(state.next_byte(), false, state), // ADI
0xce => arithmetic::add(next_byte(), state.cc.c, state), // ACI 0xce => arithmetic::add(state.next_byte(), state.cc.c, state), // ACI
0x90..=0x97 => arithmetic::sub_reg(register_from_num(instruction & 0x7), false, state), // SUB 0x90..=0x97 => arithmetic::sub_reg(register_from_num(instruction & 0x7), false, state), // SUB
0x98..=0x9f => arithmetic::sub_reg(register_from_num(instruction & 0x7), state.cc.c, state), // SBB 0x98..=0x9f => arithmetic::sub_reg(register_from_num(instruction & 0x7), state.cc.c, state), // SBB
0xd6 => arithmetic::sub(next_byte(), false, state), // SUI 0xd6 => arithmetic::sub(state.next_byte(), false, state), // SUI
0xde => arithmetic::sub(next_byte(), state.cc.c, state), // SBI 0xde => arithmetic::sub(state.next_byte(), state.cc.c, state), // SBI
0xa0..=0xa7 => arithmetic::and_reg(register_from_num(instruction & 0x7), state), // ANA 0xa0..=0xa7 => arithmetic::and_reg(register_from_num(instruction & 0x7), state), // ANA
0xa8..=0xaf => arithmetic::xor_reg(register_from_num(instruction & 0x7), state), // XRA 0xa8..=0xaf => arithmetic::xor_reg(register_from_num(instruction & 0x7), state), // XRA
0xb0..=0xb7 => arithmetic::or_reg(register_from_num(instruction & 0x7), state), // ORA 0xb0..=0xb7 => arithmetic::or_reg(register_from_num(instruction & 0x7), state), // ORA
0xb8..=0xbf => arithmetic::cmp_reg(register_from_num(instruction & 0x7), state), // CMP 0xb8..=0xbf => arithmetic::cmp_reg(register_from_num(instruction & 0x7), state), // CMP
0xe6 => arithmetic::and(next_byte(), state), // ANI 0xe6 => arithmetic::and(state.next_byte(), state), // ANI
0xee => arithmetic::xor(next_byte(), state), // XRI 0xee => arithmetic::xor(state.next_byte(), state), // XRI
0xf6 => arithmetic::or(next_byte(), state), // ORI 0xf6 => arithmetic::or(state.next_byte(), state), // ORI
0xfe => arithmetic::cmp(next_byte(), state), // CPI 0xfe => arithmetic::cmp(state.next_byte(), state), // CPI
_ => not_implemented(state), _ => not_implemented(state),
} }

View file

@ -22,6 +22,23 @@ pub struct EmulatorState {
pub memory: [u8; MEMORY_SIZE], pub memory: [u8; MEMORY_SIZE],
} }
impl EmulatorState {
// Get the next byte from memory
pub fn next_byte(&mut self) -> u8 {
self.pc += 1;
self.memory[self.pc as usize]
}
// Get the next 16-bit word from memory, in little endian order
pub fn next_word(&mut self) -> u16 {
self.pc += 2;
u16::from_le_bytes([
self.memory[self.pc as usize - 1],
self.memory[self.pc as usize],
])
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct ConditionCodes { pub struct ConditionCodes {
/// Zero (Z), set if the result is zero. /// Zero (Z), set if the result is zero.