ft: impl most arithmatic ops, dec, inc
This commit is contained in:
@@ -40,37 +40,74 @@ impl Computer {
|
|||||||
flags.zf = result.zero();
|
flags.zf = result.zero();
|
||||||
flags.sf = result.msb();
|
flags.sf = result.msb();
|
||||||
flags.pf = result.parity();
|
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.
|
/// Perform binary `dest` = `dest` - `src`. Sets flags.
|
||||||
pub fn sub(&mut self, dest: ModRmTarget, src: Operand) {
|
pub fn sub(&mut self, dest: ModRmTarget, src: Operand) {
|
||||||
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs - rhs;
|
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs - rhs;
|
||||||
let flag_set: fn(&mut Flags, Result, 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
|
/// 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
|
/// A result can never be saved to an immediate Operand, so `dest` can only
|
||||||
/// be a [`ModRmTarget`].
|
/// 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
|
where
|
||||||
O: Fn(Lhs, Rhs) -> Result,
|
O: Fn(Lhs, Rhs) -> Result,
|
||||||
F: Fn(&mut Flags, Result, Lhs, Rhs),
|
F: Fn(&mut Flags, Result, Lhs, Rhs),
|
||||||
{
|
{
|
||||||
match src {
|
match src {
|
||||||
Operand::ModRmTarget(src_target) => self.op_modrm(op, flag_set, dest, src_target),
|
Operand::ModRmTarget(src_target) => {
|
||||||
Operand::Immediate(src_operand) => self.op_imm(op, flag_set, dest, src_operand),
|
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
|
/// 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`].
|
/// [`ModRmTargets`]s, saves it to dest, if `write` is set, and sets flags,
|
||||||
fn op_modrm<O, F>(&mut self, op: O, flag_set: F, dest: ModRmTarget, src: ModRmTarget)
|
/// according to [`F`].
|
||||||
where
|
fn op_modrm<O, F>(
|
||||||
|
&mut self,
|
||||||
|
op: O,
|
||||||
|
flag_set: F,
|
||||||
|
write: bool,
|
||||||
|
dest: ModRmTarget,
|
||||||
|
src: ModRmTarget,
|
||||||
|
) where
|
||||||
O: Fn(Lhs, Rhs) -> Result,
|
O: Fn(Lhs, Rhs) -> Result,
|
||||||
F: Fn(&mut Flags, Result, Lhs, Rhs),
|
F: Fn(&mut Flags, Result, Lhs, Rhs),
|
||||||
{
|
{
|
||||||
@@ -85,7 +122,9 @@ impl Computer {
|
|||||||
let lhs = self.memory.read(&self.regs, dest_memory_idx);
|
let lhs = self.memory.read(&self.regs, dest_memory_idx);
|
||||||
let rhs = self.regs.read(src_register);
|
let rhs = self.regs.read(src_register);
|
||||||
let result = op(lhs, rhs);
|
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);
|
flag_set(&mut self.flags, result, lhs, rhs);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -95,7 +134,9 @@ impl Computer {
|
|||||||
let lhs = self.regs.read(dest_register);
|
let lhs = self.regs.read(dest_register);
|
||||||
let rhs = self.memory.read(&self.regs, src_memory_index);
|
let rhs = self.memory.read(&self.regs, src_memory_index);
|
||||||
let result = op(lhs, rhs);
|
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);
|
flag_set(&mut self.flags, result, lhs, rhs);
|
||||||
}
|
}
|
||||||
// reg, reg
|
// reg, reg
|
||||||
@@ -103,7 +144,9 @@ impl Computer {
|
|||||||
let lhs = self.regs.read(dest_register);
|
let lhs = self.regs.read(dest_register);
|
||||||
let rhs = self.regs.read(src_register);
|
let rhs = self.regs.read(src_register);
|
||||||
let result = op(lhs, rhs);
|
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);
|
flag_set(&mut self.flags, result, lhs, rhs);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -111,10 +154,16 @@ impl Computer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Applies a binary operator [`O`] to [`ImmediateOperand`] and a location
|
/// Applies a binary operator [`O`] to [`ImmediateOperand`] and a location
|
||||||
/// pointed to by a [`ModRmTarget`], saves it to dest and sets flags,
|
/// pointed to by a [`ModRmTarget`], saves it to dest, if `write` is set
|
||||||
/// according to [`F`].
|
/// and sets flags, according to [`F`].
|
||||||
fn op_imm<O, F>(&mut self, op: O, flag_set: F, dest: ModRmTarget, src: ImmediateOperand)
|
fn op_imm<O, F>(
|
||||||
where
|
&mut self,
|
||||||
|
op: O,
|
||||||
|
flag_set: F,
|
||||||
|
write: bool,
|
||||||
|
dest: ModRmTarget,
|
||||||
|
src: ImmediateOperand,
|
||||||
|
) where
|
||||||
O: Fn(Lhs, Rhs) -> Result,
|
O: Fn(Lhs, Rhs) -> Result,
|
||||||
F: Fn(&mut Flags, Result, Lhs, Rhs),
|
F: Fn(&mut Flags, Result, Lhs, Rhs),
|
||||||
{
|
{
|
||||||
@@ -122,13 +171,17 @@ impl Computer {
|
|||||||
ModRmTarget::Memory(dest_mem) => {
|
ModRmTarget::Memory(dest_mem) => {
|
||||||
let lhs = self.memory.read(&self.regs, dest_mem);
|
let lhs = self.memory.read(&self.regs, dest_mem);
|
||||||
let result = op(lhs, src);
|
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);
|
flag_set(&mut self.flags, result, lhs, src);
|
||||||
}
|
}
|
||||||
ModRmTarget::Register(dest_reg) => {
|
ModRmTarget::Register(dest_reg) => {
|
||||||
let lhs = self.regs.read(dest_reg);
|
let lhs = self.regs.read(dest_reg);
|
||||||
let result = op(lhs, src);
|
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);
|
flag_set(&mut self.flags, result, lhs, src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,64 @@ impl Interpreter {
|
|||||||
/*
|
/*
|
||||||
* OR
|
* 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
|
* SUB
|
||||||
@@ -114,11 +172,195 @@ impl Interpreter {
|
|||||||
Operand::Immediate(ImmediateOperand::Word(src_word)),
|
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
|
* MOV
|
||||||
*/
|
*/
|
||||||
Mnemonic::MOV_BXIv(word) => self.computer.regs.bx.write(word),
|
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)?,
|
Mnemonic::INT(id) => self.interpret_interrupt(id)?,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flag manipulation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Repeat prefixes
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Misc
|
||||||
|
*/
|
||||||
_ => log::info!("no action done"),
|
_ => log::info!("no action done"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
151
src/operands.rs
151
src/operands.rs
@@ -7,7 +7,7 @@ use crate::register::SegmentRegister;
|
|||||||
|
|
||||||
use crate::{disasm::DisasmError, register::Register};
|
use crate::{disasm::DisasmError, register::Register};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::ops::{Add, Div, Mul, Sub};
|
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Sub};
|
||||||
|
|
||||||
pub type Byte = u8; // b
|
pub type Byte = u8; // b
|
||||||
pub type IByte = i8; // used for displacements of memory access
|
pub type IByte = i8; // used for displacements of memory access
|
||||||
@@ -102,16 +102,17 @@ impl Add for ImmediateOperand {
|
|||||||
match self {
|
match self {
|
||||||
ImmediateOperand::Byte(lhsb) => match other {
|
ImmediateOperand::Byte(lhsb) => match other {
|
||||||
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_add(rhsb)),
|
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_add(rhsb)),
|
||||||
_ => panic!("Cannot add Word to Byte"),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(lhsw) => lhsw.wrapping_add(rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
ImmediateOperand::Word(lhsw) => match other {
|
ImmediateOperand::Word(lhsw) => match other {
|
||||||
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_add(rhsw)),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_add(rhsw)),
|
||||||
ImmediateOperand::Byte(_) => {
|
ImmediateOperand::Byte(_) => ImmediateOperand::Word(match other.sign_extend() {
|
||||||
ImmediateOperand::Word(lhsw.wrapping_add(match other.sign_extend() {
|
ImmediateOperand::Word(rhsw) => lhsw.wrapping_add(rhsw),
|
||||||
ImmediateOperand::Word(w) => w,
|
_ => panic!("unreachable"),
|
||||||
_ => panic!("Sign-extended Word is a Byte"),
|
}),
|
||||||
}))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +143,16 @@ impl Add<Displacement> for ImmediateOperand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Add<Byte> for ImmediateOperand {
|
||||||
|
type Output = ImmediateOperand;
|
||||||
|
|
||||||
|
fn add(self, imm: Byte) -> Self::Output {
|
||||||
|
match self {
|
||||||
|
Self::Byte(b) => Self::Byte(b.wrapping_add(imm)),
|
||||||
|
Self::Word(w) => Self::Word(w.wrapping_add(imm as Word)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Sub for ImmediateOperand {
|
impl Sub for ImmediateOperand {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@@ -149,21 +160,32 @@ impl Sub for ImmediateOperand {
|
|||||||
match self {
|
match self {
|
||||||
ImmediateOperand::Byte(lhsb) => match other {
|
ImmediateOperand::Byte(lhsb) => match other {
|
||||||
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_sub(rhsb)),
|
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_sub(rhsb)),
|
||||||
_ => panic!("Cannot substract Word from Byte"),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(lhsw) => lhsw.wrapping_sub(rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
ImmediateOperand::Word(lhsw) => match other {
|
ImmediateOperand::Word(lhsw) => match other {
|
||||||
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_sub(rhsw)),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_sub(rhsw)),
|
||||||
ImmediateOperand::Byte(_) => {
|
ImmediateOperand::Byte(_) => ImmediateOperand::Word(match other.sign_extend() {
|
||||||
ImmediateOperand::Word(lhsw.wrapping_sub(match other.sign_extend() {
|
ImmediateOperand::Word(rhsw) => lhsw.wrapping_sub(rhsw),
|
||||||
ImmediateOperand::Word(w) => w,
|
_ => panic!("unreachable"),
|
||||||
_ => panic!("Sign-extended Word is a Byte"),
|
}),
|
||||||
}))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sub<Byte> for ImmediateOperand {
|
||||||
|
type Output = ImmediateOperand;
|
||||||
|
|
||||||
|
fn sub(self, imm: Byte) -> Self::Output {
|
||||||
|
match self {
|
||||||
|
Self::Byte(b) => Self::Byte(b.wrapping_sub(imm)),
|
||||||
|
Self::Word(w) => Self::Word(w.wrapping_sub(imm as Word)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Mul for ImmediateOperand {
|
impl Mul for ImmediateOperand {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@@ -171,16 +193,17 @@ impl Mul for ImmediateOperand {
|
|||||||
match self {
|
match self {
|
||||||
ImmediateOperand::Byte(lhsb) => match other {
|
ImmediateOperand::Byte(lhsb) => match other {
|
||||||
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_mul(rhsb)),
|
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_mul(rhsb)),
|
||||||
_ => panic!("Cannot multiply Byte with Word"),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(lhsw) => lhsw.wrapping_mul(rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
ImmediateOperand::Word(lhsw) => match other {
|
ImmediateOperand::Word(lhsw) => match other {
|
||||||
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_mul(rhsw)),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_mul(rhsw)),
|
||||||
ImmediateOperand::Byte(_) => {
|
ImmediateOperand::Byte(_) => ImmediateOperand::Word(match other.sign_extend() {
|
||||||
ImmediateOperand::Word(lhsw.wrapping_mul(match other.sign_extend() {
|
ImmediateOperand::Word(rhsw) => lhsw.wrapping_mul(rhsw),
|
||||||
ImmediateOperand::Word(w) => w,
|
_ => panic!("unreachable"),
|
||||||
_ => panic!("Sign-extended Word is a Byte"),
|
}),
|
||||||
}))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,16 +216,86 @@ impl Div for ImmediateOperand {
|
|||||||
match self {
|
match self {
|
||||||
ImmediateOperand::Byte(lhsb) => match other {
|
ImmediateOperand::Byte(lhsb) => match other {
|
||||||
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_div(rhsb)),
|
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_div(rhsb)),
|
||||||
_ => panic!("Cannot divide Byte with Word"),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(lhsw) => lhsw.wrapping_div(rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
ImmediateOperand::Word(lhsw) => match other {
|
ImmediateOperand::Word(lhsw) => match other {
|
||||||
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_div(rhsw)),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_div(rhsw)),
|
||||||
ImmediateOperand::Byte(_) => {
|
ImmediateOperand::Byte(_) => ImmediateOperand::Word(match other.sign_extend() {
|
||||||
ImmediateOperand::Word(lhsw.wrapping_div(match other.sign_extend() {
|
ImmediateOperand::Word(rhsw) => lhsw.wrapping_div(rhsw),
|
||||||
ImmediateOperand::Word(w) => w,
|
_ => panic!("unreachable"),
|
||||||
_ => panic!("Sign-extended Word is a Byte"),
|
}),
|
||||||
}))
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitOr for ImmediateOperand {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn bitor(self, other: Self) -> Self {
|
||||||
|
match self {
|
||||||
|
ImmediateOperand::Byte(lhsb) => match other {
|
||||||
|
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb | rhsb),
|
||||||
|
ImmediateOperand::Word(rhsw) => match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(lhsw) => ImmediateOperand::Word(lhsw | rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ImmediateOperand::Word(lhsw) => match other {
|
||||||
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw | rhsw),
|
||||||
|
ImmediateOperand::Byte(_) => match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw | rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitAnd for ImmediateOperand {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn bitand(self, other: Self) -> Self {
|
||||||
|
match self {
|
||||||
|
ImmediateOperand::Byte(lhsb) => match other {
|
||||||
|
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb & rhsb),
|
||||||
|
ImmediateOperand::Word(rhsw) => match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(lhsw) => ImmediateOperand::Word(lhsw & rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ImmediateOperand::Word(lhsw) => match other {
|
||||||
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw & rhsw),
|
||||||
|
ImmediateOperand::Byte(_) => match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw & rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitXor for ImmediateOperand {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn bitxor(self, other: Self) -> Self {
|
||||||
|
match self {
|
||||||
|
ImmediateOperand::Byte(lhsb) => match other {
|
||||||
|
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb ^ rhsb),
|
||||||
|
ImmediateOperand::Word(rhsw) => match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(lhsw) => ImmediateOperand::Word(lhsw ^ rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ImmediateOperand::Word(lhsw) => match other {
|
||||||
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw ^ rhsw),
|
||||||
|
ImmediateOperand::Byte(_) => match other.sign_extend() {
|
||||||
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw ^ rhsw),
|
||||||
|
_ => panic!("unreachable"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user