Compare Packed Single-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)CMPPS instruction compares four, eight, or 16 single-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 32-bit integer (not a single-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
CMPEQPS src1, src2CMPPS src1, src2, 00h
CMPLTPS src1, src2CMPPS src1, src2, 01h
CMPLEPS src1, src2CMPPS src1, src2, 02h
CMPUNORDPS src1, src2CMPPS src1, src2, 03h
CMPNEQPS src1, src2CMPPS src1, src2, 04h
CMPNLTPS src1, src2CMPPS src1, src2, 05h
CMPNLEPS src1, src2CMPPS src1, src2, 06h
CMPORDPS src1, src2CMPPS src1, src2, 07h
VCMPEQPS dest, src1, src2VCMPPS dest, src1, src2, 00h
VCMPLTPS dest, src1, src2VCMPPS dest, src1, src2, 01h
VCMPLEPS dest, src1, src2VCMPPS dest, src1, src2, 02h
VCMPUNORDPS dest, src1, src2VCMPPS dest, src1, src2, 03h
VCMPNEQPS dest, src1, src2VCMPPS dest, src1, src2, 04h
VCMPNLTPS dest, src1, src2VCMPPS dest, src1, src2, 05h
VCMPNLEPS dest, src1, src2VCMPPS dest, src1, src2, 06h
VCMPORDPS dest, src1, src2VCMPPS dest, src1, src2, 07h
VCMPEQ_UQPS dest, src1, src2VCMPPS dest, src1, src2, 08h
VCMPNGEPS dest, src1, src2VCMPPS dest, src1, src2, 09h
VCMPNGTPS dest, src1, src2VCMPPS dest, src1, src2, 0Ah
VCMPFALSEPS dest, src1, src2VCMPPS dest, src1, src2, 0Bh
VCMPNEQ_OQPS dest, src1, src2VCMPPS dest, src1, src2, 0Ch
VCMPGEPS dest, src1, src2VCMPPS dest, src1, src2, 0Dh
VCMPGTPS dest, src1, src2VCMPPS dest, src1, src2, 0Eh
VCMPTRUEPS dest, src1, src2VCMPPS dest, src1, src2, 0Fh
VCMPEQ_OSPS dest, src1, src2VCMPPS dest, src1, src2, 10h
VCMPLT_OQPS dest, src1, src2VCMPPS dest, src1, src2, 11h
VCMPLE_OQPS dest, src1, src2VCMPPS dest, src1, src2, 12h
VCMPUNORD_SPS dest, src1, src2VCMPPS dest, src1, src2, 13h
VCMPNEQ_USPS dest, src1, src2VCMPPS dest, src1, src2, 14h
VCMPNLT_UQPS dest, src1, src2VCMPPS dest, src1, src2, 15h
VCMPNLE_UQPS dest, src1, src2VCMPPS dest, src1, src2, 16h
VCMPORD_SPDPS dest, src1, src2VCMPPS dest, src1, src2, 17h
VCMPEQ_USPS dest, src1, src2VCMPPS dest, src1, src2, 18h
VCMPNGE_UQPS dest, src1, src2VCMPPS dest, src1, src2, 19h
VCMPNGT_UQPS dest, src1, src2VCMPPS dest, src1, src2, 1Ah
VCMPFALSE_OSPS dest, src1, src2VCMPPS dest, src1, src2, 1Bh
VCMPNEQ_OSPS dest, src1, src2VCMPPS dest, src1, src2, 1Ch
VCMPGE_OQPS dest, src1, src2VCMPPS dest, src1, src2, 1Dh
VCMPGT_OQPS dest, src1, src2VCMPPS dest, src1, src2, 1Eh
VCMPTRUE_USPS dest, src1, src2VCMPPS 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 CMPPS(SimdU32 dest, SimdF32 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] = func(dest[2], src[2]) ? 0xFFFF_FFFF_FFFF_FFFFul : 0;
    dest[3] = func(dest[3], src[3]) ? 0xFFFF_FFFF_FFFF_FFFFul : 0;
    // dest[4..] is unmodified
}

void VCMPPS_Vex(SimdU32 dest, SimdF32 src1, SimdF32 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 VCMPPS_Vex128(SimdU32 dest, SimdF32 src1, SimdF32 src2, U8 predicate) =>
    VCMPPS_Vex(dest, src1, src2, predicate, 4);
public void VCMPPS_Vex256(SimdU32 dest, SimdF32 src1, SimdF32 src2, U8 predicate) =>
    VCMPPS_Vex(dest, src1, src2, predicate, 8);

void VCMPPS_EvexMemory(KMask dest, SimdF32 src1, SimdF32 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], src2[n]) ? 1 : 0;
        else
            dest[n] = 0;
        // no merge masking - EVEX.z is implicit (zero masking)
    }
    dest[kl..] = 0;
}
public void VCMPPS_Evex128Memory(KMask dest, SimdF32 src1, SimdF32 src2, U8 predicate, KMask k) =>
    VCMPPS_EvexMemory(dest, src1, src2, predicate, 4);
public void VCMPPS_Evex256Memory(KMask dest, SimdF32 src1, SimdF32 src2, U8 predicate, KMask k) =>
    VCMPPS_EvexMemory(dest, src1, src2, predicate, 8);
public void VCMPPS_Evex512Memory(KMask dest, SimdF32 src1, SimdF32 src2, U8 predicate, KMask k) =>
    VCMPPS_EvexMemory(dest, src1, src2, predicate, 16);

void VCMPPS_EvexRegister(KMask dest, SimdF32 src1, SimdF32 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 VCMPPS_Evex128Register(KMask dest, SimdF32 src1, SimdF32 src2, U8 predicate, KMask k) =>
    VCMPPS_EvexRegister(dest, src1, src2, predicate, 4);
public void VCMPPS_Evex256Register(KMask dest, SimdF32 src1, SimdF32 src2, U8 predicate, KMask k) =>
    VCMPPS_EvexRegister(dest, src1, src2, predicate, 8);
public void VCMPPS_Evex512Register(KMask dest, SimdF32 src1, SimdF32 src2, U8 predicate, KMask k) =>
    VCMPPS_EvexRegister(dest, src1, src2, predicate, 16);

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.