Conditional Move

Encoding

EncodingOperand 1Operand 2
rmModRM.reg[w]ModRM.r/m[r]

Description

The CMOVcc set of instructions conditionally moves the source operand into the destination operand. The exact condition is determined by the condition code (cc) field of the opcode (bits 0..3).

The condition code's four bits are three bits determining the condition, and one bit that, if set, inverts the result of the condition. For example, CMOVNE's opcode (0x45) is simply CMOVE's opcode (0x44) with the least significant bit set (to invert the condition). As such, instead of checking if EFLAGS.ZF is set (as CMOVE would do), it is checked to see if it is cleared.

The condition bits (bits 0..3) determine the condition according to this table (x is the invert bit):

Condition Code BitsCondition if x = 0Condition if x = 1
000xEFLAGS.OF = 1EFLAGS.OF = 0
001xEFLAGS.CF = 1EFLAGS.CF = 0
010xEFLAGS.ZF = 1EFLAGS.ZF = 0
011xEFLAGS.CF = 1 and EFLAGS.ZF = 1EFLAGS.CF = 0 and EFLAGS.ZF = 0
100xEFLAGS.SF = 1EFLAGS.SF = 0
101xEFLAGS.PF = 1EFLAGS.PF = 0
110xEFLAGS.SFEFLAGS.OFEFLAGS.SF = EFLAGS.OF
111xEFLAGS.ZF = 0 and EFLAGS.SFEFLAGS.OFEFLAGS.ZF = 1 and EFLAGS.SF = EFLAGS.OF

Operation

void CMOVcc(ref U16 dest, U16 src, bool condition)
{
    if (condition)
        dest = src;
}
void CMOVcc(ref U32 dest, U32 src, bool condition)
{
    if (condition)
        dest = src;
}
void CMOVcc(ref U64 dest, U64 src, bool condition)
{
    if (condition)
        dest = src;
}

public void CMOVO(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, EFLAGS.OF);
public void CMOVO(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, EFLAGS.OF);
public void CMOVO(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, EFLAGS.OF);

public void CMOVNO(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, !EFLAGS.OF);
public void CMOVNO(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, !EFLAGS.OF);
public void CMOVNO(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, !EFLAGS.OF);

// aliased as CMOVC and CMOVNAE
public void CMOVB(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, EFLAGS.CF);
public void CMOVB(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, EFLAGS.CF);
public void CMOVB(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, EFLAGS.CF);

// aliased as CMOVNB aand CMOVNC
public void CMOVAE(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, !EFLAGS.CF);
public void CMOVAE(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, !EFLAGS.CF);
public void CMOVAE(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, !EFLAGS.CF);

// aliased as CMOVZ
public void CMOVE(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, EFLAGS.ZF);
public void CMOVE(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, EFLAGS.ZF);
public void CMOVE(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, EFLAGS.ZF);

// aliased as CMOVNZ
public void CMOVNE(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, !EFLAGS.ZF);
public void CMOVNE(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, !EFLAGS.ZF);
public void CMOVNE(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, !EFLAGS.ZF);

// aliased as CMOVNA
public void CMOVBE(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, EFLAGS.CF && EFLAGS.ZF);
public void CMOVBE(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, EFLAGS.CF && EFLAGS.ZF);
public void CMOVBE(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, EFLAGS.CF && EFLAGS.ZF);

// aliased as CMOVNBE
public void CMOVA(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, !EFLAGS.CF && !EFLAGS.ZF);
public void CMOVA(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, !EFLAGS.CF && !EFLAGS.ZF);
public void CMOVA(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, !EFLAGS.CF && !EFLAGS.ZF);

public void CMOVS(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, EFLAGS.SF);
public void CMOVS(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, EFLAGS.SF);
public void CMOVS(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, EFLAGS.SF);

public void CMOVNS(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, !EFLAGS.SF);
public void CMOVNS(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, !EFLAGS.SF);
public void CMOVNS(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, !EFLAGS.SF);

// aliased as CMOVPE
public void CMOVP(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, EFLAGS.PF);
public void CMOVP(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, EFLAGS.PF);
public void CMOVP(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, EFLAGS.PF);

// aliased as CMOVPO
public void CMOVNP(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, !EFLAGS.PF);
public void CMOVNP(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, !EFLAGS.PF);
public void CMOVNP(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, !EFLAGS.PF);

// aliased as CMOVNGE
public void CMOVL(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, EFLAGS.SF != EFLAGS.OF);
public void CMOVL(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, EFLAGS.SF != EFLAGS.OF);
public void CMOVL(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, EFLAGS.SF != EFLAGS.OF);

// aliased as CMOVNL
public void CMOVGE(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, EFLAGS.SF == EFLAGS.OF);
public void CMOVGE(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, EFLAGS.SF == EFLAGS.OF);
public void CMOVGE(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, EFLAGS.SF == EFLAGS.OF);

// aliased as CMOVNG
public void CMOVLE(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, !EFLAGS.ZF && EFLAGS.SF != EFLAGS.OF);
public void CMOVLE(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, !EFLAGS.ZF && EFLAGS.SF != EFLAGS.OF);
public void CMOVLE(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, !EFLAGS.ZF && EFLAGS.SF != EFLAGS.OF);

// aliased as CMOVNLE
public void CMOVG(ref U16 dest, U16 src) =>
    CMOVcc(dest, src, EFLAGS.ZF && EFLAGS.SF == EFLAGS.OF);
public void CMOVG(ref U32 dest, U32 src) =>
    CMOVcc(dest, src, EFLAGS.ZF && EFLAGS.SF == EFLAGS.OF);
public void CMOVG(ref U64 dest, U64 src) =>
    CMOVcc(dest, src, EFLAGS.ZF && EFLAGS.SF == EFLAGS.OF);

Flags Affected

None.

Intrinsics

None. Auto-generated by compiler.

Exceptions

Real-Address Mode

#UD
  • If the LOCK prefix is used.
#SS(0)
  • If a memory operand using the SS segment has an effective address that is outside the SS segment's limit.
#GP(0)
  • If a memory operand (using a segment other than SS) has an effective address that is outside the segment's limit.

Virtual-8086 Mode

#UD
  • If the LOCK prefix is used.
#SS(0)
  • If a memory operand using the SS segment has an effective address that is outside the SS segment's limit.
#GP(0)
  • If a memory operand (using a segment other than SS) has an effective address that is outside the segment's limit.
#PF(fc)
  • If a page fault occurs.
#AC(0)
  • If alignment checking is enabled while the current privilege level is 3 and an unaligned memory access is made.

Protected Mode

#UD
  • If the LOCK prefix is used.
#SS(0)
  • If a memory operand using the SS segment has an effective address that is outside the SS segment's limit.
#GP(0)
  • If the destination is located in a non-writable segment.
  • If a memory operand uses a segment containing a NULL selector.
  • If a memory operand (using a segment other than SS) has an effective address that is outside the segment's limit.
#PF(fc)
  • If a page fault occurs.
#AC(0)
  • If alignment checking is enabled while the current privilege level is 3 and an unaligned memory access is made.

Compatibility Mode

#UD
  • If the LOCK prefix is used.
#SS(0)
  • If a memory operand using the SS segment has an effective address that is outside the SS segment's limit.
#GP(0)
  • If the destination is located in a non-writable segment.
  • If a memory operand uses a segment containing a NULL selector.
  • If a memory operand (using a segment other than SS) has an effective address that is outside the segment's limit.
#PF(fc)
  • If a page fault occurs.
#AC(0)
  • If alignment checking is enabled while the current privilege level is 3 and an unaligned memory access is made.

Long Mode

#UD
  • If the LOCK prefix is used.
#SS(0)
  • If a memory operand using the SS segment is in non-canonical form.
  • If a memory operand using the SS segment has an effective address that is outside the SS segment's limit.
#GP(0)
  • If a memory operand (using a segment other than SS) is in non-canonical form.
  • If the destination is located in a non-writable segment.
  • If a memory operand uses a segment containing a NULL selector.
  • If a memory operand (using a segment other than SS) has an effective address that is outside the segment's limit.
#PF(fc)
  • If a page fault occurs.
#AC(0)
  • If alignment checking is enabled while the current privilege level is 3 and an unaligned memory access is made.