mod add;
pub mod call;
mod cmp;
mod jg;
mod jl;
mod jmp;
mod jng;
mod jnl;
mod jnz;
mod jz;
mod mov;
mod sub;
use crate::error::Error;
use crate::processor::Processor;
use crate::register::Width;
use std::fmt::Debug;
pub trait Execute: Debug {
fn execute(&self, processor: &mut Processor) -> Result<(), Error>;
}
#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub enum Operand {
#[default]
None,
Value(u64),
Register(Width),
Memory(Width),
MemoryRegister(Width),
}
#[derive(Debug, PartialEq, Eq)]
pub enum Instruction {
Call(Operand),
Mov(Operand, Operand),
Jmp(Operand),
Jz(Operand),
Jnz(Operand),
Cmp(Operand, Operand),
Add(Operand, Operand, Operand),
Sub(Operand, Operand, Operand),
Jg(Operand),
Jl(Operand),
Jng(Operand),
Jnl(Operand),
}
impl Instruction {
pub fn executable(self) -> Box<dyn Execute> {
match self {
Instruction::Call(index) => Box::from(call::Call::new(index)),
Instruction::Mov(source, destination) => Box::from(mov::Mov::new(source, destination)),
Instruction::Jmp(source) => Box::from(jmp::Jmp::new(source)),
Instruction::Jz(source) => Box::from(jz::Jz::new(source)),
Instruction::Jnz(source) => Box::from(jnz::Jnz::new(source)),
Instruction::Cmp(value, comparator) => Box::from(cmp::Cmp::new(value, comparator)),
Instruction::Add(value, source, destination) => {
Box::from(add::Add::new(value, source, destination))
}
Instruction::Sub(value, source, destination) => {
Box::from(sub::Sub::new(value, source, destination))
}
Instruction::Jg(source) => Box::from(jg::Jg::new(source)),
Instruction::Jl(source) => Box::from(jl::Jl::new(source)),
Instruction::Jng(source) => Box::from(jng::Jng::new(source)),
Instruction::Jnl(source) => Box::from(jnl::Jnl::new(source)),
}
}
}
#[macro_export]
macro_rules! get_memory_value_by_width {
($processor:expr, $memory:expr) => {
match $memory {
Width::Byte(index) => $processor.memory()?.get_u8(*index) as u64,
Width::Word(index) => $processor.memory()?.get_u16(*index) as u64,
Width::DWord(index) => $processor.memory()?.get_u32(*index) as u64,
Width::QWord(index) => $processor.memory()?.get_u64(*index),
}
};
}
#[macro_export]
macro_rules! get_memory_value {
($processor:expr, $memory:expr, $index:expr) => {
match $memory {
Width::Byte(_) => $processor.memory()?.get_u8($index) as u64,
Width::Word(_) => $processor.memory()?.get_u16($index) as u64,
Width::DWord(_) => $processor.memory()?.get_u32($index) as u64,
Width::QWord(_) => $processor.memory()?.get_u64($index),
}
};
}
#[macro_export]
macro_rules! assign_memory_value_by_width {
($processor:expr, $memory:expr, $source:expr) => {
match $memory {
Width::Byte(index) => $processor.memory_mut()?.put_u8(*index, $source as u8),
Width::Word(index) => $processor.memory_mut()?.put_u16(*index, $source as u16),
Width::DWord(index) => $processor.memory_mut()?.put_u32(*index, $source as u32),
Width::QWord(index) => $processor.memory_mut()?.put_u64(*index, $source),
}
};
}
#[macro_export]
macro_rules! assign_memory_value {
($processor:expr, $memory:expr, $index:expr, $source:expr) => {
match $memory {
Width::Byte(_) => $processor.memory_mut()?.put_u8($index, $source as u8),
Width::Word(_) => $processor.memory_mut()?.put_u16($index, $source as u16),
Width::DWord(_) => $processor.memory_mut()?.put_u32($index, $source as u32),
Width::QWord(_) => $processor.memory_mut()?.put_u64($index, $source),
}
};
}