ft: impl most arithmatic ops, dec, inc

This commit is contained in:
2025-06-10 20:57:31 +09:00
parent 037d74ac6a
commit 7479021d36
3 changed files with 436 additions and 48 deletions

View File

@@ -40,37 +40,74 @@ impl Computer {
flags.zf = result.zero();
flags.sf = result.msb();
flags.pf = result.parity();
// flags.af =
};
self.op(op, flag_set, dest, src);
self.op(op, flag_set, true, dest, src);
}
/// Perform binary `dest` = `dest` - `src`. Sets flags.
pub fn sub(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs - rhs;
let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| ();
self.op(op, flag_set, dest, src);
self.op(op, flag_set, true, dest, src);
}
/// Perform binary `dest` = `dest` | `src`. Sets flags.
pub fn or(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs | rhs;
let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| ();
self.op(op, flag_set, true, dest, src);
}
/// Perform binary `dest` = `dest` & `src`. Sets flags.
pub fn and(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs & rhs;
let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| ();
self.op(op, flag_set, true, dest, src);
}
/// Perform binary `dest` = `dest` ^ `src`. Sets flags.
pub fn xor(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs ^ rhs;
let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| ();
self.op(op, flag_set, true, dest, src);
}
/// Perform compare operation, which acts like [`Self::sub()`], but without
/// saving the result and only setting [`Self::flags`].
pub fn cmp(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs - rhs;
let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| ();
self.op(op, flag_set, false, dest, src);
}
/// Applies a binary operator [`O`] to the value of two [`Operand`]s, saves
/// it to `dest` and sets flags, according to [`F`].
/// it to `dest`, if `write` is set, and sets flags, according to [`F`].
/// A result can never be saved to an immediate Operand, so `dest` can only
/// be a [`ModRmTarget`].
fn op<O, F>(&mut self, op: O, flag_set: F, dest: ModRmTarget, src: Operand)
fn op<O, F>(&mut self, op: O, flag_set: F, write: bool, dest: ModRmTarget, src: Operand)
where
O: Fn(Lhs, Rhs) -> Result,
F: Fn(&mut Flags, Result, Lhs, Rhs),
{
match src {
Operand::ModRmTarget(src_target) => self.op_modrm(op, flag_set, dest, src_target),
Operand::Immediate(src_operand) => self.op_imm(op, flag_set, dest, src_operand),
Operand::ModRmTarget(src_target) => {
self.op_modrm(op, flag_set, write, dest, src_target)
}
Operand::Immediate(src_operand) => self.op_imm(op, flag_set, write, dest, src_operand),
}
}
/// Applies a binary operator [`O`] to two memory locations, pointed to by a
/// [`ModRmTargets`]s, saves it to dest and sets flags, according to [`F`].
fn op_modrm<O, F>(&mut self, op: O, flag_set: F, dest: ModRmTarget, src: ModRmTarget)
where
/// [`ModRmTargets`]s, saves it to dest, if `write` is set, and sets flags,
/// according to [`F`].
fn op_modrm<O, F>(
&mut self,
op: O,
flag_set: F,
write: bool,
dest: ModRmTarget,
src: ModRmTarget,
) where
O: Fn(Lhs, Rhs) -> Result,
F: Fn(&mut Flags, Result, Lhs, Rhs),
{
@@ -85,7 +122,9 @@ impl Computer {
let lhs = self.memory.read(&self.regs, dest_memory_idx);
let rhs = self.regs.read(src_register);
let result = op(lhs, rhs);
self.memory.write(&self.regs, dest_memory_idx, result);
if write {
self.memory.write(&self.regs, dest_memory_idx, result);
}
flag_set(&mut self.flags, result, lhs, rhs);
}
},
@@ -95,7 +134,9 @@ impl Computer {
let lhs = self.regs.read(dest_register);
let rhs = self.memory.read(&self.regs, src_memory_index);
let result = op(lhs, rhs);
self.regs.write(dest_register, result);
if write {
self.regs.write(dest_register, result);
}
flag_set(&mut self.flags, result, lhs, rhs);
}
// reg, reg
@@ -103,7 +144,9 @@ impl Computer {
let lhs = self.regs.read(dest_register);
let rhs = self.regs.read(src_register);
let result = op(lhs, rhs);
self.regs.write(dest_register, result);
if write {
self.regs.write(dest_register, result);
}
flag_set(&mut self.flags, result, lhs, rhs);
}
},
@@ -111,10 +154,16 @@ impl Computer {
}
/// Applies a binary operator [`O`] to [`ImmediateOperand`] and a location
/// pointed to by a [`ModRmTarget`], saves it to dest and sets flags,
/// according to [`F`].
fn op_imm<O, F>(&mut self, op: O, flag_set: F, dest: ModRmTarget, src: ImmediateOperand)
where
/// pointed to by a [`ModRmTarget`], saves it to dest, if `write` is set
/// and sets flags, according to [`F`].
fn op_imm<O, F>(
&mut self,
op: O,
flag_set: F,
write: bool,
dest: ModRmTarget,
src: ImmediateOperand,
) where
O: Fn(Lhs, Rhs) -> Result,
F: Fn(&mut Flags, Result, Lhs, Rhs),
{
@@ -122,13 +171,17 @@ impl Computer {
ModRmTarget::Memory(dest_mem) => {
let lhs = self.memory.read(&self.regs, dest_mem);
let result = op(lhs, src);
self.memory.write(&self.regs, dest_mem, result);
if write {
self.memory.write(&self.regs, dest_mem, result);
}
flag_set(&mut self.flags, result, lhs, src);
}
ModRmTarget::Register(dest_reg) => {
let lhs = self.regs.read(dest_reg);
let result = op(lhs, src);
self.regs.write(dest_reg, result);
if write {
self.regs.write(dest_reg, result);
}
flag_set(&mut self.flags, result, lhs, src);
}
}

View File

@@ -89,6 +89,64 @@ impl Interpreter {
/*
* OR
*/
Mnemonic::OR_FromReg(dest, src) => self
.computer
.or(dest, Operand::ModRmTarget(ModRmTarget::Register(src))),
Mnemonic::OR_ToReg(src, dest) => self
.computer
.or(ModRmTarget::Register(dest), Operand::ModRmTarget(src)),
Mnemonic::OR_Ib(dest, src) => self
.computer
.or(dest, Operand::Immediate(ImmediateOperand::Byte(src))),
Mnemonic::OR_Iv(dest, src) => self
.computer
.or(dest, Operand::Immediate(ImmediateOperand::Word(src))),
Mnemonic::OR_ALIb(src_byte) => self.computer.or(
ModRmTarget::Register(crate::register::Register::AL),
Operand::Immediate(ImmediateOperand::Byte(src_byte)),
),
Mnemonic::OR_AXIv(src_word) => self.computer.or(
ModRmTarget::Register(crate::register::Register::AX),
Operand::Immediate(ImmediateOperand::Word(src_word)),
),
/*
* ADC
*/
/*
* SBB
*/
/*
* AND
*/
Mnemonic::AND_FromReg(dest, src) => self
.computer
.and(dest, Operand::ModRmTarget(ModRmTarget::Register(src))),
Mnemonic::AND_ToReg(src, dest) => self
.computer
.and(ModRmTarget::Register(dest), Operand::ModRmTarget(src)),
Mnemonic::AND_Ib(dest, src) => self
.computer
.and(dest, Operand::Immediate(ImmediateOperand::Byte(src))),
Mnemonic::AND_Iv(dest, src) => self
.computer
.and(dest, Operand::Immediate(ImmediateOperand::Word(src))),
Mnemonic::AND_ALIb(src_byte) => self.computer.and(
ModRmTarget::Register(crate::register::Register::AL),
Operand::Immediate(ImmediateOperand::Byte(src_byte)),
),
Mnemonic::AND_AXIv(src_word) => self.computer.and(
ModRmTarget::Register(crate::register::Register::AX),
Operand::Immediate(ImmediateOperand::Word(src_word)),
),
/*
* Override
*/
/*
* Decimal Adjust
*/
/*
* SUB
@@ -114,11 +172,195 @@ impl Interpreter {
Operand::Immediate(ImmediateOperand::Word(src_word)),
),
/*
* XOR
*/
Mnemonic::XOR_FromReg(dest, src) => self
.computer
.xor(dest, Operand::ModRmTarget(ModRmTarget::Register(src))),
Mnemonic::XOR_ToReg(src, dest) => self
.computer
.xor(ModRmTarget::Register(dest), Operand::ModRmTarget(src)),
Mnemonic::XOR_Ib(dest, src) => self
.computer
.xor(dest, Operand::Immediate(ImmediateOperand::Byte(src))),
Mnemonic::XOR_Iv(dest, src) => self
.computer
.xor(dest, Operand::Immediate(ImmediateOperand::Word(src))),
Mnemonic::XOR_ALIb(src_byte) => self.computer.xor(
ModRmTarget::Register(crate::register::Register::AL),
Operand::Immediate(ImmediateOperand::Byte(src_byte)),
),
Mnemonic::XOR_AXIv(src_word) => self.computer.xor(
ModRmTarget::Register(crate::register::Register::AX),
Operand::Immediate(ImmediateOperand::Word(src_word)),
),
/*
* CMP
*/
Mnemonic::CMP_FromReg(dest, src) => self
.computer
.cmp(dest, Operand::ModRmTarget(ModRmTarget::Register(src))),
Mnemonic::CMP_ToReg(src, dest) => self
.computer
.cmp(ModRmTarget::Register(dest), Operand::ModRmTarget(src)),
Mnemonic::CMP_Ib(dest, src) => self
.computer
.cmp(dest, Operand::Immediate(ImmediateOperand::Byte(src))),
Mnemonic::CMP_Iv(dest, src) => self
.computer
.cmp(dest, Operand::Immediate(ImmediateOperand::Word(src))),
Mnemonic::CMP_ALIb(src_byte) => self.computer.cmp(
ModRmTarget::Register(crate::register::Register::AL),
Operand::Immediate(ImmediateOperand::Byte(src_byte)),
),
Mnemonic::CMP_AXIv(src_word) => self.computer.cmp(
ModRmTarget::Register(crate::register::Register::AX),
Operand::Immediate(ImmediateOperand::Word(src_word)),
),
/*
* INC
*/
Mnemonic::INC_Reg(reg) => self
.computer
.regs
.write(reg, self.computer.regs.read(reg) + 1),
Mnemonic::INC_Mod(target) => match target {
ModRmTarget::Memory(idx) => {
let val = self.computer.memory.read(&mut self.computer.regs, idx);
self.computer
.memory
.write(&mut self.computer.regs, idx, val + 1);
}
ModRmTarget::Register(reg) => self
.computer
.regs
.write(reg, self.computer.regs.read(reg) + 1),
},
/*
* DEC
*/
Mnemonic::DEC_Reg(reg) => self
.computer
.regs
.write(reg, self.computer.regs.read(reg) - 1),
Mnemonic::DEC_Mod(target) => match target {
ModRmTarget::Memory(idx) => {
let val = self.computer.memory.read(&mut self.computer.regs, idx);
self.computer
.memory
.write(&mut self.computer.regs, idx, val - 1);
}
ModRmTarget::Register(reg) => self
.computer
.regs
.write(reg, self.computer.regs.read(reg) - 1),
},
/*
* Jumps
*/
/*
* Test
*/
/*
* XCHG
*/
/*
* MOV
*/
Mnemonic::MOV_BXIv(word) => self.computer.regs.bx.write(word),
/*
* LEA
*/
/*
* Sign extensions
*/
/*
* Call
*/
/*
* Jump
*/
/*
* Wait
*/
/*
* Push/Pop Flags
*/
/*
* String Byte Operations
*/
/*
* RET
*/
/*
* Load ES/DS Register
*/
/*
* Not/Neg
*/
/*
* MUL
*/
/*
* DIV
*/
/*
* HLT
*/
/*
* Shift and Rotate
*/
/*
* IN
*/
/*
* OUT
*/
/*
* INT
*/
Mnemonic::INT(id) => self.interpret_interrupt(id)?,
/*
* Flag manipulation
*/
/*
* Repeat prefixes
*/
/*
* Adjust
*/
/*
* Misc
*/
_ => log::info!("no action done"),
}
}