1use 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 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}