implement Jump, SetRegister, AddValueToRegister
This commit is contained in:
parent
95b769d227
commit
bc56fca299
2 changed files with 58 additions and 5 deletions
|
@ -2,7 +2,7 @@ use crate::display::Display;
|
||||||
use crate::instruction::{Instruction, ProcessorInstruction};
|
use crate::instruction::{Instruction, ProcessorInstruction};
|
||||||
use crate::stack::Stack;
|
use crate::stack::Stack;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use log::{debug, info, warn};
|
use log::{debug, info, trace, warn};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -98,12 +98,17 @@ where
|
||||||
|
|
||||||
/// Emulation loop executes the fetch -> decode -> execute pipeline
|
/// Emulation loop executes the fetch -> decode -> execute pipeline
|
||||||
fn emulation_loop<T>(&mut self) -> Result<(), anyhow::Error> {
|
fn emulation_loop<T>(&mut self) -> Result<(), anyhow::Error> {
|
||||||
|
let mut last_program_counter = self.program_counter;
|
||||||
loop {
|
loop {
|
||||||
// fetch instruction
|
// fetch instruction
|
||||||
let instruction = self.fetch_instruction()?;
|
let instruction = self.fetch_instruction()?;
|
||||||
self.program_counter += 2;
|
self.program_counter += 2;
|
||||||
|
|
||||||
debug!("PC={} {:04x}", self.program_counter, instruction);
|
if last_program_counter != self.program_counter {
|
||||||
|
debug!("PC={} {:04x}", self.program_counter, instruction);
|
||||||
|
}
|
||||||
|
last_program_counter = self.program_counter;
|
||||||
|
|
||||||
|
|
||||||
// decode & execute
|
// decode & execute
|
||||||
self.execute_instruction(instruction)?;
|
self.execute_instruction(instruction)?;
|
||||||
|
@ -114,11 +119,20 @@ where
|
||||||
fn execute_instruction(&mut self, instruction: Instruction) -> Result<(), anyhow::Error> {
|
fn execute_instruction(&mut self, instruction: Instruction) -> Result<(), anyhow::Error> {
|
||||||
match instruction.processor_instruction() {
|
match instruction.processor_instruction() {
|
||||||
ProcessorInstruction::ClearScreen => {
|
ProcessorInstruction::ClearScreen => {
|
||||||
info!("clear display");
|
trace!("Clear display");
|
||||||
self.display.clear()
|
self.display.clear()
|
||||||
}
|
}
|
||||||
ProcessorInstruction::Jump(address) => {
|
ProcessorInstruction::Jump(address) => {
|
||||||
todo!("implement jump")
|
trace!("Jump to address {:04x}", address);
|
||||||
|
self.program_counter = address
|
||||||
|
}
|
||||||
|
ProcessorInstruction::SetRegister(register, data) => {
|
||||||
|
trace!("Set register {} to data {:04x}", register, data);
|
||||||
|
self.registers[register] = data
|
||||||
|
}
|
||||||
|
ProcessorInstruction::AddValueToRegister(register, data) => {
|
||||||
|
trace!("Add to register {} data {:04x}", register, data);
|
||||||
|
self.registers[register] += data
|
||||||
}
|
}
|
||||||
ProcessorInstruction::UnknownInstruction => {
|
ProcessorInstruction::UnknownInstruction => {
|
||||||
warn!("Unknown instruction: {:04x}, skipping.", instruction);
|
warn!("Unknown instruction: {:04x}, skipping.", instruction);
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Display, Formatter, LowerHex};
|
use std::fmt::{Display, Formatter, LowerHex};
|
||||||
|
use log::info;
|
||||||
|
/*
|
||||||
|
Although every instruction will have a first nibble that tells you what kind of instruction it is,
|
||||||
|
the rest of the nibbles will have different meanings. To differentiate these meanings,
|
||||||
|
we usually call them different things, but all of them can be any hexadecimal number from 0 to F:
|
||||||
|
|
||||||
|
X: The second nibble. Used to look up one of the 16 registers (VX) from V0 through VF.
|
||||||
|
Y: The third nibble. Also used to look up one of the 16 registers (VY) from V0 through VF.
|
||||||
|
N: The fourth nibble. A 4-bit number.
|
||||||
|
NN: The second byte (third and fourth nibbles). An 8-bit immediate number.
|
||||||
|
NNN: The second, third and fourth nibbles. A 12-bit immediate memory address.
|
||||||
|
*/
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum ProcessorInstruction {
|
pub enum ProcessorInstruction {
|
||||||
|
@ -7,6 +19,10 @@ pub enum ProcessorInstruction {
|
||||||
ClearScreen,
|
ClearScreen,
|
||||||
/// Jumps to a given address
|
/// Jumps to a given address
|
||||||
Jump(u16),
|
Jump(u16),
|
||||||
|
/// Sets the register in the first argument to the given value
|
||||||
|
SetRegister(usize, u8),
|
||||||
|
/// Adds the value to the register
|
||||||
|
AddValueToRegister(usize, u8),
|
||||||
UnknownInstruction
|
UnknownInstruction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +60,17 @@ impl Instruction {
|
||||||
}
|
}
|
||||||
// Jump
|
// Jump
|
||||||
0x1000..=0x1FFF => {
|
0x1000..=0x1FFF => {
|
||||||
ProcessorInstruction::Jump(data & 0xFFF)
|
// 1NNN
|
||||||
|
ProcessorInstruction::Jump(Self::grab_inner_data(data))
|
||||||
|
}
|
||||||
|
// Set Register
|
||||||
|
0x6000..=0x6FFF => {
|
||||||
|
// 6XNN
|
||||||
|
ProcessorInstruction::SetRegister(Self::grab_first_nibble(data), Self::grab_last_byte(data))
|
||||||
|
}
|
||||||
|
0x7000..0x7FFF => {
|
||||||
|
// 7XNN
|
||||||
|
ProcessorInstruction::AddValueToRegister(Self::grab_first_nibble(data), Self::grab_last_byte(data))
|
||||||
}
|
}
|
||||||
// Unknown instruction
|
// Unknown instruction
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -53,7 +79,20 @@ impl Instruction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Grabs the inner data from the data, ignores the opcode.
|
||||||
|
fn grab_inner_data(data: u16) -> u16 {
|
||||||
|
data & 0x0FFF
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Grabs the last byte from the data.
|
||||||
|
fn grab_last_byte(data: u16) -> u8 {
|
||||||
|
(data & 0x00FF) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Grabs the first nibble from the data.
|
||||||
|
fn grab_first_nibble(data: u16) -> usize {
|
||||||
|
((data & 0x0F00) >> 8) as usize
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Instruction {
|
impl Display for Instruction {
|
||||||
|
|
Loading…
Reference in a new issue