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 ) } }