x86emu/emulator/
cond.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use super::Emulator;
5use super::InternalError;
6use crate::Cpu;
7use iced_x86::ConditionCode;
8use iced_x86::Instruction;
9use x86defs::RFlags;
10
11impl<T: Cpu> Emulator<'_, T> {
12    pub(super) async fn setcc(
13        &mut self,
14        instr: &Instruction,
15    ) -> Result<(), InternalError<T::Error>> {
16        let value = eval_cond(instr, self.cpu.rflags());
17        self.write_op_0(instr, value as u64).await?;
18        Ok(())
19    }
20
21    pub(super) async fn cmovcc(
22        &mut self,
23        instr: &Instruction,
24    ) -> Result<(), InternalError<T::Error>> {
25        // CMOV always writes to the destination register. This may seem like a no-op on false conditions, but
26        // actually can cause truncation when the destination is a 32-bit register.
27        let src_op = if eval_cond(instr, self.cpu.rflags()) {
28            1
29        } else {
30            0
31        };
32        let value = self.op_value(instr, src_op).await?;
33        self.write_op_0(instr, value).await?;
34        Ok(())
35    }
36}
37
38fn eval_cond(instr: &Instruction, flags: RFlags) -> bool {
39    match instr.condition_code() {
40        ConditionCode::a => !flags.carry() && !flags.zero(),
41        ConditionCode::ae => !flags.carry(),
42        ConditionCode::b => flags.carry(),
43        ConditionCode::be => flags.carry() || flags.zero(),
44        ConditionCode::e => flags.zero(),
45        ConditionCode::g => !flags.zero() && flags.sign() == flags.overflow(),
46        ConditionCode::ge => flags.sign() == flags.overflow(),
47        ConditionCode::l => flags.sign() != flags.overflow(),
48        ConditionCode::le => flags.zero() || flags.sign() != flags.overflow(),
49        ConditionCode::ne => !flags.zero(),
50        ConditionCode::no => !flags.overflow(),
51        ConditionCode::np => !flags.parity(),
52        ConditionCode::ns => !flags.sign(),
53        ConditionCode::o => flags.overflow(),
54        ConditionCode::p => flags.parity(),
55        ConditionCode::s => flags.sign(),
56        ConditionCode::None => unreachable!(),
57    }
58}