ft: impl ret

This commit is contained in:
2025-06-17 12:02:08 +09:00
parent 7f4d79d840
commit 18cc460d40
2 changed files with 30 additions and 32 deletions

View File

@@ -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())
}
}

View File

@@ -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