ft: impl ret
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use core::fmt;
|
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};
|
use super::{flags::Flags, interpreter::InterpreterError, memory::Memory, register::Register};
|
||||||
|
|
||||||
@@ -11,13 +11,6 @@ pub enum ArithmeticOperand {
|
|||||||
ModRmTarget(ModRmTarget),
|
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 ArithmeticResult = ImmediateOperand;
|
||||||
type Lhs = ImmediateOperand;
|
type Lhs = ImmediateOperand;
|
||||||
type Rhs = ImmediateOperand;
|
type Rhs = ImmediateOperand;
|
||||||
@@ -45,19 +38,10 @@ impl Computer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve value from stack and increment stack pointer.
|
/// 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)?;
|
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()?;
|
self.regs.pop()?;
|
||||||
|
Ok(word)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform binary `dest` = `dest` + `src`. Sets flags.
|
/// Perform binary `dest` = `dest` + `src`. Sets flags.
|
||||||
@@ -163,7 +147,9 @@ impl Computer {
|
|||||||
}
|
}
|
||||||
ArithmeticOperand::ModRmTarget(mod_rm_target) => {
|
ArithmeticOperand::ModRmTarget(mod_rm_target) => {
|
||||||
ArithmeticOperand::Immediate(match 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,
|
ModRmTarget::Register(reg) => self.regs.read(reg) + cf,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -189,7 +175,9 @@ impl Computer {
|
|||||||
}
|
}
|
||||||
ArithmeticOperand::ModRmTarget(mod_rm_target) => {
|
ArithmeticOperand::ModRmTarget(mod_rm_target) => {
|
||||||
ArithmeticOperand::Immediate(match 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,
|
ModRmTarget::Register(reg) => self.regs.read(reg) + cf,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -243,7 +231,7 @@ impl Computer {
|
|||||||
/// Read an [`ImmediateOperand`] from [`Self::memory`] or [`Self::regs`].
|
/// Read an [`ImmediateOperand`] from [`Self::memory`] or [`Self::regs`].
|
||||||
pub fn read_modrm(&self, target: ModRmTarget) -> ImmediateOperand {
|
pub fn read_modrm(&self, target: ModRmTarget) -> ImmediateOperand {
|
||||||
match target {
|
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),
|
ModRmTarget::Register(reg) => self.regs.read(reg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,10 +253,6 @@ mod tests {
|
|||||||
let mut c = Computer::new();
|
let mut c = Computer::new();
|
||||||
let val = ImmediateOperand::Word(0x1234);
|
let val = ImmediateOperand::Word(0x1234);
|
||||||
c.push_stack(val).unwrap();
|
c.push_stack(val).unwrap();
|
||||||
|
assert_eq!(val, c.pop_stack().unwrap().into())
|
||||||
let target = PopTarget::Register(crate::register::Register::AX);
|
|
||||||
c.pop_stack(target).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(val, c.regs.read(crate::register::Register::AX))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::{env::current_dir, fmt::Debug, process::exit};
|
use std::{fmt::Debug, process::exit};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instructions::{Instruction, Mnemonic},
|
instructions::{Instruction, Mnemonic},
|
||||||
interpreter::{computer::PopTarget, interrupt::Mess1, memory::Memory},
|
interpreter::{interrupt::Mess1, memory::Memory},
|
||||||
operands::{Byte, ImmediateOperand, ModRmTarget, Word},
|
operands::{Byte, ImmediateOperand, ModRmTarget, Word},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,8 +114,16 @@ impl Interpreter {
|
|||||||
/*
|
/*
|
||||||
* POP
|
* POP
|
||||||
*/
|
*/
|
||||||
Mnemonic::POP_R(reg) => self.computer.pop_stack(PopTarget::Register(reg))?,
|
Mnemonic::POP_R(reg) => {
|
||||||
Mnemonic::POP_M(idx) => self.computer.pop_stack(PopTarget::MemoryIndex(idx))?,
|
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!(),
|
Mnemonic::POP_S(_) => todo!(),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -508,7 +516,9 @@ impl Interpreter {
|
|||||||
*/
|
*/
|
||||||
Mnemonic::LEA(target, reg) => {
|
Mnemonic::LEA(target, reg) => {
|
||||||
let val = match target {
|
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),
|
ModRmTarget::Register(reg) => self.computer.regs.read(reg),
|
||||||
};
|
};
|
||||||
self.computer.regs.write(reg, val);
|
self.computer.regs.write(reg, val);
|
||||||
@@ -549,6 +559,10 @@ impl Interpreter {
|
|||||||
/*
|
/*
|
||||||
* RET
|
* RET
|
||||||
*/
|
*/
|
||||||
|
Mnemonic::RET => {
|
||||||
|
let offset = self.computer.pop_stack()?;
|
||||||
|
Self::ip_jump(&self.instructions, &mut ip, offset as usize);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load ES/DS Register
|
* Load ES/DS Register
|
||||||
|
|||||||
Reference in New Issue
Block a user