chore(interpreter): always sign-extend ImmediateOperand::Byte when cast

This commit is contained in:
2025-06-11 17:40:38 +09:00
parent 7691b4b2ab
commit 4cea76bd1c

View File

@@ -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<Word> for ImmediateOperand {
}
}
impl Into<Word> for ImmediateOperand {
fn into(self) -> u16 {
match self {
ImmediateOperand::Byte(_) => self.sign_extend().into(),
ImmediateOperand::Word(w) => w,
}
}
}
impl Into<usize> for ImmediateOperand {
fn into(self) -> usize {
match self {