ft: impl most arithmatic ops, dec, inc
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user