From 803c6267d2cab4b33310bb27d574ce750622d41d Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Wed, 2 Jul 2025 20:32:13 +0900 Subject: [PATCH] ft(interpreter): impl mul and div --- src/interpreter/interpreter.rs | 32 ++++++++++++++++++++++ src/operands.rs | 49 ++++++++++++++++++---------------- 2 files changed, 58 insertions(+), 23 deletions(-) diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index b69ec7b..f1e2bd3 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -668,10 +668,42 @@ impl Interpreter { /* * MUL */ + Mnemonic::MUL(target) => { + let src = self.computer.read_modrm(target)?; + let dest = self.computer.regs.ax.read(); + let (ax, dx) = src.mul(dest.into()); + self.computer.regs.ax.write(ax); + self.computer.regs.dx.write(dx); + self.computer.flags.of = if dx == 0 { false } else { true }; + self.computer.flags.cf = if dx == 0 { false } else { true }; + } + Mnemonic::IMUL(_) => todo!(), /* * DIV */ + Mnemonic::DIV(target) => { + // byte: Unsigned divide AX by r/m8, with result stored in AL ← Quotient, AH ← Remainder. + // word: Unsigned divide DX:AX by r/m16, with result stored in AX ← Quotient, DX ← Remainder. + let src = self.computer.read_modrm(target)?; + let ax = self.computer.regs.ax.read(); + match src { + ImmediateOperand::Byte(b) => { + self.computer.regs.ax.lower = (ax / b as Word) as Byte; + self.computer.regs.ax.upper = (ax % b as Word) as Byte; + } + ImmediateOperand::Word(w) => { + let dx = self.computer.regs.dx.read(); + let num: u32 = ((dx as u32) << 16) | (ax as u32); + let quot: u16 = (num / w as u32) as Word; + let rem: u16 = (num % w as u32) as Word; + + self.computer.regs.ax.write(quot); + self.computer.regs.dx.write(rem); + } + } + } + Mnemonic::IDIV(_) => todo!(), /* * HLT diff --git a/src/operands.rs b/src/operands.rs index e157246..809f10d 100644 --- a/src/operands.rs +++ b/src/operands.rs @@ -107,6 +107,32 @@ impl ImmediateOperand { Self::Word(word) => return (word >> 15) == 1, } } + + /// Multiply values and return the extended u32, split into two words. + pub fn mul(&self, other: Self) -> (Word, Word) { + let result: u32 = match self { + Self::Byte(lhsb) => match other { + Self::Byte(rhsb) => *lhsb as u32 * rhsb as u32, + Self::Word(rhsw) => match other.sign_extend() { + Self::Word(lhsw) => lhsw as u32 * rhsw as u32, + _ => panic!("unreachable"), + }, + }, + Self::Word(lhsw) => match other { + Self::Word(rhsw) => *lhsw as u32 * rhsw as u32, + Self::Byte(_) => match other.sign_extend() { + Self::Word(rhsw) => *lhsw as u32 * rhsw as u32, + _ => panic!("unreachable"), + }, + }, + }; + + let bytes = result.to_le_bytes(); + let lower = Word::from_le_bytes([bytes[0], bytes[1]]); + let upper = Word::from_le_bytes([bytes[2], bytes[3]]); + + (lower, upper) + } } impl PartialOrd for ImmediateOperand { @@ -262,29 +288,6 @@ impl Sub for ImmediateOperand { } } } -impl Mul for ImmediateOperand { - type Output = Self; - - fn mul(self, other: Self) -> Self { - match self { - ImmediateOperand::Byte(lhsb) => match other { - ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_mul(rhsb)), - 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(rhsw) => ImmediateOperand::Word(lhsw.wrapping_mul(rhsw)), - ImmediateOperand::Byte(_) => ImmediateOperand::Word(match other.sign_extend() { - ImmediateOperand::Word(rhsw) => lhsw.wrapping_mul(rhsw), - _ => panic!("unreachable"), - }), - }, - } - } -} - impl Shl for ImmediateOperand { type Output = Self;