ft(interpreter): impl all low-hanging fruit instructions
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user