Compare Packed Double-Precision Floating-Point Values

Encoding

EncodingOperand 1Operand 2Operand 3Operand 4Operand 5
rmin/aModRM.reg[rw]ModRM.r/m[r]imm8
rvmin/aModRM.reg[rw]VEX.vvvv[r]ModRM.r/m[r]imm8
ervmifullModRM.reg[rw]EVEX.vvvvv[r]ModRM.r/m[r]imm8

Description

The (V)CMPPD instruction compares two, four, or eight double-precision floating-point values from the two source operands. The eight bit immediate determines the operation. The result is stored in the destination operand.

All forms except the legacy SSE one will zero the upper (untouched) bits.

For the legacy SSE and VEX versions, the results will all be a 64 bit integer (not a double-precision floating-point) of either all zeros or ones. For the EVEX versions, the destination is a mask register where each bit contains an individual comparison result.

For the legacy SSE version, bits 0..2 are used to determine the operation. For the VEX and EVEX encoded versions, bits 0..4 are used. The other bits are reserved. The operation is determined from the table below (an empty row indicates the division between allowed predicates from legacy SSE and VEX/EVEX encoded forms):

imm8 ValuePredicateDescriptionResult1QNaN Signals #IA
A < BA = BA > BUnordered2
00hEQ_OQ (EQ)Equal (ordered, non-signaling)falsetruefalsefalseno
01hLT_OS (LT)Less-than (ordered, signaling)truefalsefalsefalseyes
02hLE_OS (LE)Less-than-or-equal (ordered, signaling)truetruefalsefalseyes
03hUNORD_Q (UNORD)Unordered (non-signaling)falsefalsefalsetrueno
04hNEQ_UQ (NEQ)Not-equal (unordered, non-signaling)truefalsetruetrueno
05hNLT_US (NLT)Not-less-than (unordered, signaling)falsetruetruetrueyes
06hNLE_US (NLE)Not-less-than-or-equal (unordered, signaling)falsefalsetruetrueyes
07hORD_Q (ORD)Ordered (non-signaling)truetruetruefalseno
08hEQ_UQEqual (unordered, non-signaling)falsetruefalsetrueno
09hNGE_US (NGE)Not-greater-than-or-equal (unordered, signaling)truefalsefalsetrueyes
0AhNGT_US (NGT)Not-greater-than (unordered, signaling)truetruefalsetrueyes
0BhFALSE_OQ (FALSE)False (ordered, non-signaling)falsefalsefalsefalseno
0ChNEQ_OQNot-equal (ordered, non-signaling)truefalsetruefalseno
0DhGE_OS (GE)Greater-than-or-equal (ordered, signaling)falsetruetruefalseyes
0EhGT_OS (GT)Greater-than (ordered, signaling)falsefalsetruefalseyes
0FhTRUE_UQ (TRUE)True (unordered, non-signaling)truetruetruetrueno
10hEQ_OSEqual (ordered, signaling)falsetruefalsefalseyes
11hLT_OQLess-than (ordered, non-signaling)truefalsefalsefalseno
12hLE_OQLess-than-or-equal (ordered, non-signaling)truetruefalsefalseno
13hUNORD_SUnordered (signaling)falsefalsefalsetrueyes
14hNEQ_USNot-equal (unordered, signaling)truefalsetruetrueyes
15hNLT_UQNot-less-than (unordered, non-signaling)falsetruetruetrueno
16hNLE_UQNot-less-than-or-equal (unordered, non-signaling)falsefalsetruetrueno
17hORD_SOrdered (signaling)truetruetruefalseyes
18hEQ_USEqual (unordered, signaling)falsetruefalsetrueyes
19hNGE_UQNot-greater-than-or-equal (unordered, non-signaling)truefalsefalsetrueno
1AhNGT_UQNot-greater-than (unordered, non-signaling)truetruefalsetrueno
1BhFALSE_OSFalse (ordered, signaling)falsefalsefalsefalseyes
1ChNEQ_OSNot-equal (ordered, signaling)truefalsetruefalseyes
1DhGE_OQGreater-than-or-equal (ordered, non-signaling)falsetruetruefalseno
1EhGT_OQGreater-than (ordered, non-signaling)falsefalsetruefalseno
1FhTRUE_USTrue (unordered, signaling)truetruetruetrueyes
  1. A is 1st operand; B is 2nd operand
  2. If either A or B is NaN.

Assemblers may implement the following pseudo-mnemonics for the various predicate values:

Pseudo-Mnemonic FormEncoded Form
CMPEQPD src1, src2CMPPD src1, src2, 00h
CMPLTPD src1, src2CMPPD src1, src2, 01h
CMPLEPD src1, src2CMPPD src1, src2, 02h
CMPUNORDPD src1, src2CMPPD src1, src2, 03h
CMPNEQPD src1, src2CMPPD src1, src2, 04h
CMPNLTPD src1, src2CMPPD src1, src2, 05h
CMPNLEPD src1, src2CMPPD src1, src2, 06h
CMPORDPD src1, src2CMPPD src1, src2, 07h
VCMPEQPD dest, src1, src2VCMPPD dest, src1, src2, 00h
VCMPLTPD dest, src1, src2VCMPPD dest, src1, src2, 01h
VCMPLEPD dest, src1, src2VCMPPD dest, src1, src2, 02h
VCMPUNORDPD dest, src1, src2VCMPPD dest, src1, src2, 03h
VCMPNEQPD dest, src1, src2VCMPPD dest, src1, src2, 04h
VCMPNLTPD dest, src1, src2VCMPPD dest, src1, src2, 05h
VCMPNLEPD dest, src1, src2VCMPPD dest, src1, src2, 06h
VCMPORDPD dest, src1, src2VCMPPD dest, src1, src2, 07h
VCMPEQ_UQPD dest, src1, src2VCMPPD dest, src1, src2, 08h
VCMPNGEPD dest, src1, src2VCMPPD dest, src1, src2, 09h
VCMPNGTPD dest, src1, src2VCMPPD dest, src1, src2, 0Ah
VCMPFALSEPD dest, src1, src2VCMPPD dest, src1, src2, 0Bh
VCMPNEQ_OQPD dest, src1, src2VCMPPD dest, src1, src2, 0Ch
VCMPGEPD dest, src1, src2VCMPPD dest, src1, src2, 0Dh
VCMPGTPD dest, src1, src2VCMPPD dest, src1, src2, 0Eh
VCMPTRUEPD dest, src1, src2VCMPPD dest, src1, src2, 0Fh
VCMPEQ_OSPD dest, src1, src2VCMPPD dest, src1, src2, 10h
VCMPLT_OQPD dest, src1, src2VCMPPD dest, src1, src2, 11h
VCMPLE_OQPD dest, src1, src2VCMPPD dest, src1, src2, 12h
VCMPUNORD_SPD dest, src1, src2VCMPPD dest, src1, src2, 13h
VCMPNEQ_USPD dest, src1, src2VCMPPD dest, src1, src2, 14h
VCMPNLT_UQPD dest, src1, src2VCMPPD dest, src1, src2, 15h
VCMPNLE_UQPD dest, src1, src2VCMPPD dest, src1, src2, 16h
VCMPORD_SPDPD dest, src1, src2VCMPPD dest, src1, src2, 17h
VCMPEQ_USPD dest, src1, src2VCMPPD dest, src1, src2, 18h
VCMPNGE_UQPD dest, src1, src2VCMPPD dest, src1, src2, 19h
VCMPNGT_UQPD dest, src1, src2VCMPPD dest, src1, src2, 1Ah
VCMPFALSE_OSPD dest, src1, src2VCMPPD dest, src1, src2, 1Bh
VCMPNEQ_OSPD dest, src1, src2VCMPPD dest, src1, src2, 1Ch
VCMPGE_OQPD dest, src1, src2VCMPPD dest, src1, src2, 1Dh
VCMPGT_OQPD dest, src1, src2VCMPPD dest, src1, src2, 1Eh
VCMPTRUE_USPD dest, src1, src2VCMPPD dest, src1, src2, 1Fh

Operation

ComparisonFunc[] PredicateMapping8 = new[]
{
    EQ_OQ, //   0 - equal                  (ordered, non-signaling)
    LT_OS, //   1 - less-than              (ordered, signaling)
    LE_OS, //   2 - less-than-or-equal     (ordered, signaling)
    UNORD_Q, // 3 - unordered              (non-signaling)
    NEQ_UQ, //  4 - not-equal              (unordered, non-signaling)
    NLT_US, //  5 - not-less-than          (unordered, signaling)
    NLE_US, //  6 - not-less-than-or-equal (unordered, signaling)
    ORD_Q, //   7 - ordered                (non-signaling)
};
ComparisonFunc[] PredicateMapping32 = new[]
{
    EQ_OQ, //     0 - equal                     (ordered, non-signaling)
    LT_OS, //     1 - less-than                 (ordered, signaling)
    LE_OS, //     2 - less-than-or-equal        (ordered, signaling)
    UNORD_Q, //   3 - unordered                 (non-signaling)
    NEQ_UQ, //    4 - not-equal                 (unordered, non-signaling)
    NLT_US, //    5 - not-less-than             (unordered, signaling)
    NLE_US, //    6 - not-less-than-or-equal    (unordered, signaling)
    ORD_Q, //     7 - ordered                   (non-signaling)
    EQ_UQ, //     8 - equal                     (unordered, non-signaling)
    NGE_US, //    9 - not-greater-than-or-equal (unordered, signaling)
    NGT_US, //   10 - not-greater-than          (unordered, signaling)
    FALSE_OQ, // 11 - false                     (ordered, non-signaling)
    NEQ_OQ, //   12 - not-equal                 (ordered, non-signaling)
    GE_OS, //    13 - greater-than-or-equal     (ordered, signaling)
    GT_OS, //    14 - greater-than              (ordered, signaling)
    TRUE_UQ, //  15 - true                      (unordered, non-signaling)
    EQ_OS, //    16 - equal                     (ordered, signaling)
    LT_OQ, //    17 - less-than                 (ordered, non-signaling)
    LE_OQ, //    18 - less-than-or-equal        (ordered, non-signaling)
    UNORD_S, //  19 - unordered                 (signaling)
    NEQ_US, //   20 - not-equal                 (unordered, signaling)
    NLT_UQ, //   21 - not-less-than             (unordered, non-signaling)
    NLE_UQ, //   22 - not-less-than-or-equal    (unordered, non-signaling)
    ORD_S, //    23 - ordered                   (signaling)
    EQ_US, //    24 - equal                     (unordered, signaling)
    NGE_UQ, //   25 - not-greater-than-or-equal (unordered, non-signaling)
    NGT_UQ, //   26 - not-greater-than          (unordered, non-signaling)
    FALSE_OS, // 27 - false                     (ordered, signaling)
    NEQ_OS, //   28 - not-equal                 (ordered, signaling)
    GE_OQ, //    29 - greater-than-or-equal     (ordered, non-signaling)
    GT_OQ, //    30 - greater-than              (ordered, non-signaling)
    TRUE_US, //  31 - true                      (unordered, signaling)
};

public void CMPPD(SimdU64 dest, SimdF64 src, U8 predicate)
{
    ComparisonFunc func = PredicateMapping8[predicate];
    dest[0] = func(dest[0], src[0]) ? 0xFFFF_FFFF_FFFF_FFFFul : 0;
    dest[1] = func(dest[1], src[1]) ? 0xFFFF_FFFF_FFFF_FFFFul : 0;
    // dest[2..] is unmodified
}

void VCMPPD_Vex(SimdU64 dest, SimdF64 src1, SimdF64 src2, U8 predicate, int kl)
{
    ComparisonFunc func = PredicateMapping32[predicate];
    for (int n = 0; n < kl; n++)
        dest[n] = func(src1[n], src2[n]) ? 0xFFFF_FFFF_FFFF_FFFFul : 0;
    dest[kl..] = 0;
}
public void VCMPPD_Vex128(SimdU64 dest, SimdF64 src1, SimdF64 src2, U8 predicate) =>
    VCMPPD_Vex(dest, src1, src2, predicate, 2);
public void VCMPPD_Vex256(SimdU64 dest, SimdF64 src1, SimdF64 src2, U8 predicate) =>
    VCMPPD_Vex(dest, src1, src2, predicate, 4);

void VCMPPD_EvexMemory(KMask dest, SimdF64 src1, SimdF64 src2, U8 predicate, KMask k, int kl)
{
    ComparisonFunc func = PredicateMapping32[predicate];
    for (int n = 0; n < kl; n++)
    {
        if (k[n])
            dest[n] = func(src1[n], EVEX.b ? src2[0] : src2[n])) ? 1 : 0;
        else
            dest[n] = 0;
        // no merge masking - EVEX.z is implicit (zero masking)
    }
    dest[kl..] = 0;
}
public void VCMPPD_Evex128Memory(KMask dest, SimdF64 src1, SimdF64 src2, U8 predicate, KMask k) =>
    VCMPPD_EvexMemory(dest, src1, src2, predicate, 2);
public void VCMPPD_Evex256Memory(KMask dest, SimdF64 src1, SimdF64 src2, U8 predicate, KMask k) =>
    VCMPPD_EvexMemory(dest, src1, src2, predicate, 4);
public void VCMPPD_Evex512Memory(KMask dest, SimdF64 src1, SimdF64 src2, U8 predicate, KMask k) =>
    VCMPPD_EvexMemory(dest, src1, src2, predicate, 8);


void VCMPPD_EvexRegister(KMask dest, SimdF64 src1, SimdF64 src2, U8 predicate, KMask k, int kl)
{
    ComparisonFunc func = PredicateMapping32[predicate];
    for (int n = 0; n < kl; n++)
    {
        if (k[n])
            dest[n] = func(src1[n], EVEX.b ? src2[0] : src2[n])) ? 1 : 0;
        else
            dest[n] = 0;
        // no merge masking - EVEX.z is implicit (zero masking)
    }
    dest[kl..] = 0;
}
public void VCMPPD_Evex128Register(KMask dest, SimdF64 src1, SimdF64 src2, U8 predicate, KMask k) =>
    VCMPPD_EvexRegister(dest, src1, src2, predicate, 2);
public void VCMPPD_Evex256Register(KMask dest, SimdF64 src1, SimdF64 src2, U8 predicate, KMask k) =>
    VCMPPD_EvexRegister(dest, src1, src2, predicate, 4);
public void VCMPPD_Evex512Register(KMask dest, SimdF64 src1, SimdF64 src2, U8 predicate, KMask k) =>
    VCMPPD_EvexRegister(dest, src1, src2, predicate, 8);

Intrinsics

Exceptions

SIMD Floating-Point

#XM
  • #D - Denormal operand.
  • #I - Invalid operation.

Other Exceptions

VEX Encoded Form: See Type 2 Exception Conditions.
EVEX Encoded Form: See Type E2 Exception Conditions.