fix(interpreter): correctly sign extend cmp byte

This commit is contained in:
2025-07-06 22:35:39 +09:00
parent aba85c9a48
commit 68fb5b7b56
2 changed files with 20 additions and 2 deletions

View File

@@ -668,7 +668,7 @@ impl Disassembler {
// byte extended version // byte extended version
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?; let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let imm = self.parse_byte()?; let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))? Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm).sign_extend())?
} }
0x84 => modrm_8b_register!(self, TEST), 0x84 => modrm_8b_register!(self, TEST),

View File

@@ -239,7 +239,25 @@ impl Computer {
dest: ModRmTarget, dest: ModRmTarget,
src: ArithmeticOperand, src: ArithmeticOperand,
) -> Result<(), InterpreterError> { ) -> Result<(), InterpreterError> {
let op: fn(Lhs, Rhs) -> ArithmeticResult = |lhs, rhs| lhs - rhs; let op: fn(Lhs, Rhs) -> ArithmeticResult = |lhs, rhs| {
// 0x80, with modrm byte selecting mem read from [%bx] is the only
// grp1 instruction, which does not state sign-extension, meaning
// that rhs really is just a byte, which means only the low byte
// of lhs should be compared to.
// With out this match here, the sub logic would sign extend the
// rhs to a word, which is not the desired logic.
match lhs {
ImmediateOperand::Word(lhsw) => match rhs {
ImmediateOperand::Byte(_) => {
let [low, _] = lhsw.to_be_bytes();
return ImmediateOperand::Byte(low) - rhs;
}
_ => {}
},
_ => {}
}
lhs - rhs
};
let flag_set: fn(&mut Flags, ArithmeticResult, Lhs, Rhs) = |flags, result, lhs, rhs| { let flag_set: fn(&mut Flags, ArithmeticResult, Lhs, Rhs) = |flags, result, lhs, rhs| {
// log::info!("{:?} {:?} {}", lhs, rhs, lhs < rhs); // log::info!("{:?} {:?} {}", lhs, rhs, lhs < rhs);
flags.cf = lhs < rhs; flags.cf = lhs < rhs;