diff --git a/src/interpreter/computer.rs b/src/interpreter/computer.rs index cff82e6..6e7af7d 100644 --- a/src/interpreter/computer.rs +++ b/src/interpreter/computer.rs @@ -1,6 +1,6 @@ use core::fmt; -use crate::operands::{ImmediateOperand, MemoryIndex, ModRmTarget}; +use crate::operands::{ImmediateOperand, ModRmTarget, Word}; use super::{flags::Flags, interpreter::InterpreterError, memory::Memory, register::Register}; @@ -11,13 +11,6 @@ pub enum ArithmeticOperand { ModRmTarget(ModRmTarget), } -/// Wrapper for easier argument passing of polymorph pop operations. -#[derive(Debug, Clone)] -pub enum PopTarget { - Register(crate::register::Register), - MemoryIndex(MemoryIndex), -} - type ArithmeticResult = ImmediateOperand; type Lhs = ImmediateOperand; type Rhs = ImmediateOperand; @@ -45,19 +38,10 @@ impl Computer { } /// Retrieve value from stack and increment stack pointer. - pub fn pop_stack(&mut self, target: PopTarget) -> Result<(), InterpreterError> { + pub fn pop_stack(&mut self) -> Result { let word = self.memory.read_raw(self.regs.sp)?; - - match target { - PopTarget::Register(reg) => self.regs.write(reg, word.into()), - PopTarget::MemoryIndex(mem_idx) => self - .memory - .write_raw(Memory::calc_memidx(&self.regs, mem_idx).into(), word.into())?, - } - self.regs.pop()?; - - Ok(()) + Ok(word) } /// Perform binary `dest` = `dest` + `src`. Sets flags. @@ -163,7 +147,9 @@ impl Computer { } ArithmeticOperand::ModRmTarget(mod_rm_target) => { ArithmeticOperand::Immediate(match mod_rm_target { - ModRmTarget::Memory(idx) => self.memory.read(&self.regs, idx) + cf, + ModRmTarget::Memory(idx) => { + (self.memory.read(&self.regs, idx) + cf as u16).into() + } ModRmTarget::Register(reg) => self.regs.read(reg) + cf, }) } @@ -189,7 +175,9 @@ impl Computer { } ArithmeticOperand::ModRmTarget(mod_rm_target) => { ArithmeticOperand::Immediate(match mod_rm_target { - ModRmTarget::Memory(idx) => self.memory.read(&self.regs, idx) + cf, + ModRmTarget::Memory(idx) => { + (self.memory.read(&self.regs, idx) + cf as u16).into() + } ModRmTarget::Register(reg) => self.regs.read(reg) + cf, }) } @@ -243,7 +231,7 @@ impl Computer { /// Read an [`ImmediateOperand`] from [`Self::memory`] or [`Self::regs`]. pub fn read_modrm(&self, target: ModRmTarget) -> ImmediateOperand { match target { - ModRmTarget::Memory(idx) => self.memory.read(&self.regs, idx), + ModRmTarget::Memory(idx) => self.memory.read(&self.regs, idx).into(), ModRmTarget::Register(reg) => self.regs.read(reg), } } @@ -265,10 +253,6 @@ mod tests { let mut c = Computer::new(); let val = ImmediateOperand::Word(0x1234); c.push_stack(val).unwrap(); - - let target = PopTarget::Register(crate::register::Register::AX); - c.pop_stack(target).unwrap(); - - assert_eq!(val, c.regs.read(crate::register::Register::AX)) + assert_eq!(val, c.pop_stack().unwrap().into()) } } diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index aacacc4..a169496 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -1,9 +1,9 @@ use core::fmt; -use std::{env::current_dir, fmt::Debug, process::exit}; +use std::{fmt::Debug, process::exit}; use crate::{ instructions::{Instruction, Mnemonic}, - interpreter::{computer::PopTarget, interrupt::Mess1, memory::Memory}, + interpreter::{interrupt::Mess1, memory::Memory}, operands::{Byte, ImmediateOperand, ModRmTarget, Word}, }; @@ -114,8 +114,16 @@ impl Interpreter { /* * POP */ - Mnemonic::POP_R(reg) => self.computer.pop_stack(PopTarget::Register(reg))?, - Mnemonic::POP_M(idx) => self.computer.pop_stack(PopTarget::MemoryIndex(idx))?, + Mnemonic::POP_R(reg) => { + let val = self.computer.pop_stack()?.into(); + self.computer.regs.write(reg, val); + } + Mnemonic::POP_M(idx) => { + let val = self.computer.pop_stack()?.into(); + self.computer + .memory + .write_raw(Memory::calc_memidx(&self.computer.regs, idx).into(), val)? + } Mnemonic::POP_S(_) => todo!(), /* @@ -508,7 +516,9 @@ impl Interpreter { */ Mnemonic::LEA(target, reg) => { let val = match target { - ModRmTarget::Memory(idx) => Memory::calc_memidx(&self.computer.regs, idx), + ModRmTarget::Memory(idx) => { + Memory::calc_memidx(&self.computer.regs, idx).into() + } ModRmTarget::Register(reg) => self.computer.regs.read(reg), }; self.computer.regs.write(reg, val); @@ -549,6 +559,10 @@ impl Interpreter { /* * RET */ + Mnemonic::RET => { + let offset = self.computer.pop_stack()?; + Self::ip_jump(&self.instructions, &mut ip, offset as usize); + } /* * Load ES/DS Register