fix(interpreter): correctly sign extend cmp byte
This commit is contained in:
@@ -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),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user