From 95b769d227028087edb721954d16264811dc2b0d Mon Sep 17 00:00:00 2001 From: Denis Nutiu Date: Wed, 4 Dec 2024 00:07:33 +0200 Subject: [PATCH] decode instruction using pattern matching --- src/emulator.rs | 19 ++++++------------- src/instruction.rs | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/emulator.rs b/src/emulator.rs index d71ca42..c904803 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -1,5 +1,5 @@ use crate::display::Display; -use crate::instruction::Instruction; +use crate::instruction::{Instruction, ProcessorInstruction}; use crate::stack::Stack; use anyhow::anyhow; use log::{debug, info, warn}; @@ -112,18 +112,15 @@ where } fn execute_instruction(&mut self, instruction: Instruction) -> Result<(), anyhow::Error> { - match instruction.raw() { - // Clear Display - 0x00E0 => { + match instruction.processor_instruction() { + ProcessorInstruction::ClearScreen => { info!("clear display"); self.display.clear() } - // Jump - 0x1000..=0x1FFF => { - info!("jump to {}", instruction); + ProcessorInstruction::Jump(address) => { + todo!("implement jump") } - // Unknown instruction - _ => { + ProcessorInstruction::UnknownInstruction => { warn!("Unknown instruction: {:04x}, skipping.", instruction); } } @@ -142,10 +139,6 @@ where ])) } - fn decode_instruction(&mut self, _instruction: Instruction) -> Result<(), anyhow::Error> { - todo!("must implement"); - } - /// Loads the ROM found at the rom path in the emulator's RAM memory. fn load_rom(&mut self, rom_file: T) -> Result<(), anyhow::Error> where diff --git a/src/instruction.rs b/src/instruction.rs index 9993145..bcf0c6e 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -1,23 +1,59 @@ use std::fmt; use std::fmt::{Display, Formatter, LowerHex}; +#[derive(Debug, Clone, Copy)] +pub enum ProcessorInstruction { + /// Clears the screen + ClearScreen, + /// Jumps to a given address + Jump(u16), + UnknownInstruction +} + #[derive(Debug)] pub struct Instruction { data: u16, + processor_instruction: ProcessorInstruction } impl Instruction { /// Creates a new instruction instance. pub(crate) fn new(data: [u8; 2]) -> Self { + let data = (data[0] as u16) << 8u8 | (data[1] as u16); Instruction { - data: (data[0] as u16) << 8u8 | (data[1] as u16), + data, + processor_instruction: Instruction::decode_instruction(data), } } - /// raw returns the raw instruction data. pub fn raw(&self) -> u16 { self.data } + + /// Returns the processor instruction. + pub fn processor_instruction(&self) -> ProcessorInstruction { + self.processor_instruction + } + + /// Decodes the raw instruction data into a processor instruction. + fn decode_instruction(data: u16) -> ProcessorInstruction { + match data { + // Clear Display + 0x00E0 => { + ProcessorInstruction::ClearScreen + } + // Jump + 0x1000..=0x1FFF => { + ProcessorInstruction::Jump(data & 0xFFF) + } + // Unknown instruction + _ => { + ProcessorInstruction::UnknownInstruction + } + } + } + + } impl Display for Instruction {