194 lines
7.0 KiB
Rust
194 lines
7.0 KiB
Rust
use crate::operands::{Byte, ImmediateOperand, Word};
|
|
use core::fmt;
|
|
|
|
use super::interpreter::InterpreterError;
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct Register {
|
|
pub ax: AX,
|
|
pub bx: BX,
|
|
pub cx: CX,
|
|
pub dx: DX,
|
|
pub sp: Word,
|
|
pub bp: Word,
|
|
pub si: Word,
|
|
pub di: Word,
|
|
}
|
|
|
|
impl Register {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
ax: AX::new(),
|
|
bx: BX::new(),
|
|
cx: CX::new(),
|
|
dx: DX::new(),
|
|
sp: 0xffda,
|
|
bp: 0,
|
|
si: 0,
|
|
di: 0,
|
|
}
|
|
}
|
|
|
|
/// Decrement stack pointer
|
|
pub fn push(&mut self) -> Result<(), InterpreterError> {
|
|
if self.sp < 2 {
|
|
return Err(InterpreterError::InvalidRegisterState(*self));
|
|
} else {
|
|
self.sp -= 2;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Increment stack pointer
|
|
pub fn pop(&mut self) -> Result<(), InterpreterError> {
|
|
if self.sp > 0xffff - 2 {
|
|
return Err(InterpreterError::InvalidRegisterState(*self));
|
|
} else {
|
|
self.sp += 2;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Read value from a [`crate::register::Register`].
|
|
pub fn read(&self, reg: crate::register::Register) -> ImmediateOperand {
|
|
match reg {
|
|
crate::register::Register::AX => ImmediateOperand::Word(self.ax.read()),
|
|
crate::register::Register::BX => ImmediateOperand::Word(self.bx.read()),
|
|
crate::register::Register::CX => ImmediateOperand::Word(self.cx.read()),
|
|
crate::register::Register::DX => ImmediateOperand::Word(self.dx.read()),
|
|
crate::register::Register::AH => ImmediateOperand::Byte(self.ax.upper),
|
|
crate::register::Register::AL => ImmediateOperand::Byte(self.ax.lower),
|
|
crate::register::Register::BH => ImmediateOperand::Byte(self.bx.upper),
|
|
crate::register::Register::BL => ImmediateOperand::Byte(self.bx.lower),
|
|
crate::register::Register::CH => ImmediateOperand::Byte(self.cx.upper),
|
|
crate::register::Register::CL => ImmediateOperand::Byte(self.cx.lower),
|
|
crate::register::Register::DH => ImmediateOperand::Byte(self.dx.upper),
|
|
crate::register::Register::DL => ImmediateOperand::Byte(self.dx.lower),
|
|
crate::register::Register::DI => ImmediateOperand::Word(self.di),
|
|
crate::register::Register::SI => ImmediateOperand::Word(self.si),
|
|
crate::register::Register::BP => ImmediateOperand::Word(self.bp),
|
|
crate::register::Register::SP => ImmediateOperand::Word(self.sp),
|
|
}
|
|
}
|
|
|
|
/// Write an [`ImmediateOperand`] to a [`crate::register::Register`].
|
|
pub fn write(&mut self, reg: crate::register::Register, val: ImmediateOperand) {
|
|
match val {
|
|
ImmediateOperand::Byte(byte) => match reg {
|
|
crate::register::Register::AX => self.ax.lower = byte,
|
|
crate::register::Register::BX => self.bx.lower = byte,
|
|
crate::register::Register::CX => self.cx.lower = byte,
|
|
crate::register::Register::DX => self.dx.lower = byte,
|
|
crate::register::Register::AH => self.ax.upper = byte,
|
|
crate::register::Register::AL => self.ax.lower = byte,
|
|
crate::register::Register::BH => self.bx.upper = byte,
|
|
crate::register::Register::BL => self.bx.lower = byte,
|
|
crate::register::Register::CH => self.cx.upper = byte,
|
|
crate::register::Register::CL => self.cx.lower = byte,
|
|
crate::register::Register::DH => self.dx.upper = byte,
|
|
crate::register::Register::DL => self.dx.lower = byte,
|
|
crate::register::Register::DI => self.di = Word::from_le_bytes([0x0, byte]),
|
|
crate::register::Register::SI => self.si = Word::from_le_bytes([0x0, byte]),
|
|
crate::register::Register::BP => self.bp = Word::from_le_bytes([0x0, byte]),
|
|
crate::register::Register::SP => self.sp = Word::from_le_bytes([0x0, byte]),
|
|
},
|
|
ImmediateOperand::Word(word) => {
|
|
let [low, high] = word.to_le_bytes();
|
|
match reg {
|
|
crate::register::Register::AX => self.ax.write(word),
|
|
crate::register::Register::BX => self.bx.write(word),
|
|
crate::register::Register::CX => self.cx.write(word),
|
|
crate::register::Register::DX => self.dx.write(word),
|
|
crate::register::Register::AH => self.ax.upper = high,
|
|
crate::register::Register::AL => self.ax.lower = low,
|
|
crate::register::Register::BH => self.ax.upper = high,
|
|
crate::register::Register::BL => self.ax.lower = low,
|
|
crate::register::Register::CH => self.ax.upper = high,
|
|
crate::register::Register::CL => self.ax.lower = low,
|
|
crate::register::Register::DH => self.ax.upper = high,
|
|
crate::register::Register::DL => self.ax.lower = low,
|
|
crate::register::Register::DI => self.di = word,
|
|
crate::register::Register::SI => self.si = word,
|
|
crate::register::Register::BP => self.bp = word,
|
|
crate::register::Register::SP => self.sp = word,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Register {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"AX({}) BX({}) CX({}) DX({}) SP({:04x}) BP({:04x}) SI({:04x}) DI({:04x})",
|
|
self.ax, self.bx, self.cx, self.dx, self.sp, self.bp, self.si, self.di
|
|
)
|
|
}
|
|
}
|
|
|
|
macro_rules! gen_regs {
|
|
($ident:ident) => {
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct $ident {
|
|
pub upper: Byte,
|
|
pub lower: Byte,
|
|
}
|
|
|
|
impl $ident {
|
|
pub fn new() -> Self {
|
|
Self { upper: 0, lower: 0 }
|
|
}
|
|
|
|
pub fn read(self) -> Word {
|
|
Word::from_le_bytes([self.lower, self.upper])
|
|
}
|
|
|
|
pub fn write(&mut self, word: Word) {
|
|
let [low, high]: [u8; 2] = word.to_le_bytes();
|
|
self.lower = low;
|
|
self.upper = high;
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for $ident {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(f, "{:04x}", Word::from_le_bytes([self.lower, self.upper]))
|
|
}
|
|
}
|
|
};
|
|
}
|
|
gen_regs!(AX);
|
|
gen_regs!(BX);
|
|
gen_regs!(CX);
|
|
gen_regs!(DX);
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct SegmentRegister {
|
|
pub ds: Word,
|
|
pub es: Word,
|
|
pub ss: Word,
|
|
pub cs: Word,
|
|
}
|
|
|
|
impl SegmentRegister {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
ds: 0,
|
|
es: 0,
|
|
ss: 0,
|
|
cs: 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for SegmentRegister {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"DS({}) ES({}) SS({}) CS({})",
|
|
self.ds, self.es, self.ss, self.cs
|
|
)
|
|
}
|
|
}
|