From 4cea76bd1c6001e298afdd2d6d33c21874054074 Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Wed, 11 Jun 2025 17:40:38 +0900 Subject: [PATCH] chore(interpreter): always sign-extend ImmediateOperand::Byte when cast --- src/operands.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/operands.rs b/src/operands.rs index 4b9b425..109ef66 100644 --- a/src/operands.rs +++ b/src/operands.rs @@ -16,11 +16,12 @@ pub type IWord = i16; // used for displacement of memory access pub type DWord = u32; #[derive(Debug, Clone, Ord, Eq, PartialEq, PartialOrd, Copy)] -/// Encodes either Byte- or Word-sized immediate operands. -/// Also sometimes used to decide if an instruction is Byte- or Word-sized, -/// which is usually indicated by using a value of 0 and the disregarding -/// the value when read. -/// Can either be interpreted as signed or unsigned, depending on the context. +/// Universal type to encode either Byte- or Word-sized immediate operands. +/// Mostly used to: +/// - Encode immediates, where instructions exist for both widths. +/// - Encode instruction width, to select either the 8- or 16-bit register. +/// - Encode raw immediate values, to make use of all implemented functions +/// of this type. pub enum ImmediateOperand { Byte(Byte), Word(Word), @@ -44,7 +45,8 @@ impl ImmediateOperand { /// Interprets [`Self::Byte`] as [`Self::Word`]. /// Returns word, if already a [`Self::Word`]. - pub fn as_word(self) -> Self { + /// CAUTION: You probably want to use [`Self::sign_extend()`] instead. + fn as_word(self) -> Self { match self { Self::Byte(b) => Self::Word(b as Word), Self::Word(_) => self, @@ -87,6 +89,7 @@ impl ImmediateOperand { } /// Check if most significant bit is set. + /// If the number is interpreted as signed, this acts as the sign bit. pub fn msb(&self) -> bool { match self { Self::Byte(byte) => return (byte >> 7) == 1, @@ -107,6 +110,15 @@ impl From for ImmediateOperand { } } +impl Into for ImmediateOperand { + fn into(self) -> u16 { + match self { + ImmediateOperand::Byte(_) => self.sign_extend().into(), + ImmediateOperand::Word(w) => w, + } + } +} + impl Into for ImmediateOperand { fn into(self) -> usize { match self {