ft(interpreter): impl all low-hanging fruit instructions

This commit is contained in:
2025-06-11 23:29:34 +09:00
parent 4cea76bd1c
commit 5942270f63
4 changed files with 105 additions and 4 deletions

View File

@@ -110,6 +110,20 @@ impl Computer {
self.op(op, flag_set, false, dest, src);
}
/// Perform test operation, which acts like [`Self::and()`], but without
/// saving the result and only setting [`Self::flags`].
pub fn test(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> ArithmeticResult = |lhs, rhs| lhs & rhs;
let flag_set: fn(&mut Flags, ArithmeticResult, Lhs, Rhs) = |flags, result, _, _| {
flags.cf = false;
flags.of = false;
flags.zf = result.zero();
flags.sf = result.msb();
flags.pf = result.parity();
};
self.op(op, flag_set, false, dest, src);
}
/// Perform `dest` = `dest` + `src` + CF. Sets flags.
pub fn adc(&mut self, dest: ModRmTarget, src: Operand) {
let cf = self.flags.cf as u8;

View File

@@ -3,7 +3,7 @@ use std::{fmt::Debug, process::exit};
use crate::{
instructions::{Instruction, Mnemonic},
interpreter::interrupt::Mess1,
interpreter::{interrupt::Mess1, memory::Memory},
operands::{Byte, ImmediateOperand, ModRmTarget},
};
@@ -366,10 +366,40 @@ impl Interpreter {
/*
* Test
*/
Mnemonic::TEST(dest, src) => self
.computer
.test(dest, Operand::ModRmTarget(ModRmTarget::Register(src))),
Mnemonic::TEST_Ib(dest, src) => self
.computer
.test(dest, Operand::Immediate(ImmediateOperand::Byte(src))),
Mnemonic::TEST_Iv(dest, src) => self
.computer
.test(dest, Operand::Immediate(ImmediateOperand::Word(src))),
Mnemonic::TEST_ALIb(src_byte) => self.computer.test(
ModRmTarget::Register(crate::register::Register::AL),
Operand::Immediate(ImmediateOperand::Byte(src_byte)),
),
Mnemonic::TEST_AXIv(src_word) => self.computer.test(
ModRmTarget::Register(crate::register::Register::AX),
Operand::Immediate(ImmediateOperand::Word(src_word)),
),
/*
* XCHG
*/
Mnemonic::XCHG(target, reg) => {
let tmp = self.computer.read_modrm(target);
self.computer
.write_modrm(target, self.computer.regs.read(reg));
self.computer.regs.write(reg, tmp);
}
Mnemonic::XCHG_AX(reg) => {
let tmp = self.computer.regs.read(reg);
self.computer
.regs
.write(reg, self.computer.regs.ax.read().into());
self.computer.regs.write(reg, tmp);
}
/*
* MOV
@@ -411,14 +441,37 @@ impl Interpreter {
/*
* LEA
*/
Mnemonic::LEA(target, reg) => {
let val = match target {
ModRmTarget::Memory(idx) => Memory::calc_memidx(&self.computer.regs, idx),
ModRmTarget::Register(reg) => self.computer.regs.read(reg),
};
self.computer.regs.write(reg, val);
}
/*
* Sign extensions
*/
Mnemonic::CBW => {
if ImmediateOperand::Byte(self.computer.regs.ax.lower).msb() {
// extend sign bit into AX, i.e. all bits set
self.computer.regs.ax.upper = 0xff;
}
}
Mnemonic::CWD => {
if ImmediateOperand::Word(self.computer.regs.ax.read()).msb() {
// extend sign bit into DX, i.e. all bits set
self.computer.regs.dx.write(0xffff);
}
}
/*
* Wait
*/
Mnemonic::WAIT => {
log::info!("wait");
continue;
}
/*
* Push/Pop Flags
@@ -439,6 +492,14 @@ impl Interpreter {
/*
* Not/Neg
*/
Mnemonic::NOT(target) => {
self.computer
.write_modrm(target, !self.computer.read_modrm(target));
}
Mnemonic::NEG(target) => {
let val = !self.computer.read_modrm(target);
self.computer.write_modrm(target, val + 0b1);
}
/*
* MUL
@@ -451,6 +512,10 @@ impl Interpreter {
/*
* HLT
*/
Mnemonic::HLT => {
eprintln!("Processor halted... exiting.");
exit(1);
}
/*
* Shift and Rotate
@@ -472,6 +537,13 @@ impl Interpreter {
/*
* Flag manipulation
*/
Mnemonic::CLC => self.computer.flags.cf = false,
Mnemonic::STC => self.computer.flags.cf = true,
Mnemonic::CLI => self.computer.flags.r#if = false,
Mnemonic::STI => self.computer.flags.r#if = true,
Mnemonic::CLD => self.computer.flags.df = false,
Mnemonic::STD => self.computer.flags.df = true,
Mnemonic::CMC => self.computer.flags.cf = !self.computer.flags.cf,
/*
* Repeat prefixes
@@ -484,6 +556,10 @@ impl Interpreter {
/*
* Misc
*/
Mnemonic::LOCK => {
log::info!("lock#");
continue;
}
_ => log::info!("no action done"),
}
}

View File

@@ -66,8 +66,8 @@ impl Memory {
}
}
/// Calculate the absolute Memory Index from a [`MemoryIndex`] struct.
fn calc_memidx(
/// Calculate the absolute memory address from a [`MemoryIndex`] struct.
pub fn calc_memidx(
regs: &crate::interpreter::register::Register,
idx: MemoryIndex,
) -> ImmediateOperand {

View File

@@ -7,7 +7,7 @@ use crate::register::SegmentRegister;
use crate::{disasm::DisasmError, register::Register};
use core::fmt;
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Sub};
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Sub};
pub type Byte = u8; // b
pub type IByte = i8; // used for displacements of memory access
@@ -334,6 +334,17 @@ impl BitXor for ImmediateOperand {
}
}
impl Not for ImmediateOperand {
type Output = Self;
fn not(self) -> Self::Output {
match self {
ImmediateOperand::Byte(b) => ImmediateOperand::Byte(!b),
ImmediateOperand::Word(w) => ImmediateOperand::Word(!w),
}
}
}
impl fmt::Display for ImmediateOperand {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {