Compare Scalar 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
ervmituple1-scalarModRM.reg[rw]EVEX.vvvvv[r]ModRM.r/m[r]imm8

Description

The (V)CMPSD instruction compares a single 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.

The VEX form will copy bits 64..127 from the first source operand into the destination. 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
CMPEQSD src1, src2CMPSD src1, src2, 00h
CMPLTSD src1, src2CMPSD src1, src2, 01h
CMPLESD src1, src2CMPSD src1, src2, 02h
CMPUNORDSD src1, src2CMPSD src1, src2, 03h
CMPNEQSD src1, src2CMPSD src1, src2, 04h
CMPNLTSD src1, src2CMPSD src1, src2, 05h
CMPNLESD src1, src2CMPSD src1, src2, 06h
CMPORDSD src1, src2CMPSD src1, src2, 07h
VCMPEQSD dest, src1, src2VCMPSD dest, src1, src2, 00h
VCMPLTSD dest, src1, src2VCMPSD dest, src1, src2, 01h
VCMPLESD dest, src1, src2VCMPSD dest, src1, src2, 02h
VCMPUNORDSD dest, src1, src2VCMPSD dest, src1, src2, 03h
VCMPNEQSD dest, src1, src2VCMPSD dest, src1, src2, 04h
VCMPNLTSD dest, src1, src2VCMPSD dest, src1, src2, 05h
VCMPNLESD dest, src1, src2VCMPSD dest, src1, src2, 06h
VCMPORDSD dest, src1, src2VCMPSD dest, src1, src2, 07h
VCMPEQ_UQSD dest, src1, src2VCMPSD dest, src1, src2, 08h
VCMPNGESD dest, src1, src2VCMPSD dest, src1, src2, 09h
VCMPNGTSD dest, src1, src2VCMPSD dest, src1, src2, 0Ah
VCMPFALSESD dest, src1, src2VCMPSD dest, src1, src2, 0Bh
VCMPNEQ_OQSD dest, src1, src2VCMPSD dest, src1, src2, 0Ch
VCMPGESD dest, src1, src2VCMPSD dest, src1, src2, 0Dh
VCMPGTSD dest, src1, src2VCMPSD dest, src1, src2, 0Eh
VCMPTRUESD dest, src1, src2VCMPSD dest, src1, src2, 0Fh
VCMPEQ_OSSD dest, src1, src2VCMPSD dest, src1, src2, 10h
VCMPLT_OQSD dest, src1, src2VCMPSD dest, src1, src2, 11h
VCMPLE_OQSD dest, src1, src2VCMPSD dest, src1, src2, 12h
VCMPUNORD_SSD dest, src1, src2VCMPSD dest, src1, src2, 13h
VCMPNEQ_USSD dest, src1, src2VCMPSD dest, src1, src2, 14h
VCMPNLT_UQSD dest, src1, src2VCMPSD dest, src1, src2, 15h
VCMPNLE_UQSD dest, src1, src2VCMPSD dest, src1, src2, 16h
VCMPORD_SPDSD dest, src1, src2VCMPSD dest, src1, src2, 17h
VCMPEQ_USSD dest, src1, src2VCMPSD dest, src1, src2, 18h
VCMPNGE_UQSD dest, src1, src2VCMPSD dest, src1, src2, 19h
VCMPNGT_UQSD dest, src1, src2VCMPSD dest, src1, src2, 1Ah
VCMPFALSE_OSSD dest, src1, src2VCMPSD dest, src1, src2, 1Bh
VCMPNEQ_OSSD dest, src1, src2VCMPSD dest, src1, src2, 1Ch
VCMPGE_OQSD dest, src1, src2VCMPSD dest, src1, src2, 1Dh
VCMPGT_OQSD dest, src1, src2VCMPSD dest, src1, src2, 1Eh
VCMPTRUE_USSD dest, src1, src2VCMPSD 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 CMPSD(SimdU64 dest, SimdF64 src, U8 predicate)
{
    ComparisonFunc func = PredicateMapping8[predicate];
    dest[0] = func(dest[0], src[0]) ? 0xFFFF_FFFF_FFFF_FFFFul : 0;
    // dest[1..] is unmodified
}

public void VCMPSD_Vex(SimdU64 dest, SimdF64 src1, SimdF64 src2, U8 predicate, int kl)
{
    ComparisonFunc func = PredicateMapping32[predicate];
    dest[0] = func(dest[0], src[0]) ? 0xFFFF_FFFF_FFFF_FFFFul : 0;
    dest[1] = src1[1];
    dest[2..] = 0;
}

public void VCMPSD_Evex(KMask dest, SimdF64 src1, SimdF64 src2, U8 predicate, KMask k, int kl)
{
    ComparisonFunc func = PredicateMapping32[predicate];
    if (k[0])
        dest[0] = func(dest[0], src[0]) ? 0xFFFF_FFFF_FFFF_FFFFul : 0;
    else
        dest[0] = 0;
    // no merge masking - EVEX.z is implicit (zero masking)
    dest[1..] = 0;
}

Intrinsics

Exceptions

SIMD Floating-Point

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

Other Exceptions

VEX Encoded Form: See Type 3 Exception Conditions.
EVEX Encoded Form: See Type E3 Exception Conditions.