ft: impl ret
This commit is contained in:
@@ -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<Word, InterpreterError> {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user