x86doc › Opcode

Opcode/Instruction | Op /En | 64/32 bit Mode Support | CPUID Feature Flag | Description |
---|---|---|---|---|

EVEX.LLIG.66.0F3A.W1 51 /r VRANGESD xmm1 {k1}{z}, xmm2, xmm3/m64{sae}, imm8 | A | V/V | AVX512DQ | Calculate a RANGE operation output value from 2 double-precision floating-point values in xmm2 and xmm3/m64, store the output to xmm1 under writemask. Imm8 specifies the comparison and sign of the range operation. |

Op/En | Tuple Type | Operand 1 | Operand 2 | Operand 3 | Operand 4 |
---|---|---|---|---|---|

A | Tuple1 Scalar | ModRM:reg (w) | EVEX.vvvv (r) | ModRM:r/m (r) | Imm8 |

**Description**

This instruction calculates a range operation output from two input double-precision FP values in the low qword element of the first source operand (the second operand) and second source operand (the third operand). The range output is written to the low qword element of the destination operand (the first operand) under the writemask k1.

Bits7:4 of imm8 byte must be zero. The range operation output is performed in two parts, each configured by a two-bit control field within imm8[3:0]:

The encodings of Imm8[1:0] and Imm8[3:2] are shown in Figure 5-27.

Bits 128:63 of the destination operand are copied from the respective element of the first source operand.

When one or more of the input value is a NAN, the comparison operation may signal invalid exception (IE). Details with one of more input value is NAN is listed in Table 5-10. If the comparison raises an IE, the sign select control (Imm8[3:2] has no effect to the range operation output, this is indicated also in Table 5-10.

When both input values are zeros of opposite signs, the comparison operation of MIN/MAX in the range compare operation is slightly different from the conceptually similar FP MIN/MAX operation that are found in the instructions VMAXPD/VMINPD. The details of MIN/MAX/MIN_ABS/MAX_ABS operation for VRANGEPD/PS/SD/SS for magni-tude-0, opposite-signed input cases are listed in Table 5-11.

Additionally, non-zero, equal-magnitude with opposite-sign input values perform MIN_ABS or MAX_ABS compar-ison operation with result listed in Table 5-12.

**Operation**

RangeDP(SRC1[63:0], SRC2[63:0], CmpOpCtl[1:0], SignSelCtl[1:0])

{

// Check if SNAN and report IE, see also Table 5-10

IF (SRC1 = SNAN) THEN RETURN (QNAN(SRC1), set IE);

IF (SRC2 = SNAN) THEN RETURN (QNAN(SRC2), set IE);

Src1.exp := SRC1[62:52];

Src1.fraction := SRC1[51:0];

IF ((Src1.exp = 0 ) and (Src1.fraction != 0)) THEN// Src1 is a denormal number

IF DAZ THEN Src1.fraction := 0;

ELSE IF (SRC2 <> QNAN) Set DE; FI;

FI;

Src2.exp := SRC2[62:52];

Src2.fraction := SRC2[51:0];

IF ((Src2.exp = 0) and (Src2.fraction !=0 )) THEN// Src2 is a denormal number

IF DAZ THEN Src2.fraction := 0;

ELSE IF (SRC1 <> QNAN) Set DE; FI;

FI;

IF

(SRC2 = QNAN) THEN{TMP[63:0] := SRC1[63:0]}

ELSE IF(SRC1 = QNAN) THEN{TMP[63:0] := SRC2[63:0]}

ELSE IF (Both SRC1, SRC2 are magnitude-0 and opposite-signed) TMP[63:0] := from Table 5-11

ELSE IF (Both SRC1, SRC2 are magnitude-equal and opposite-signed and CmpOpCtl[1:0] > 01) TMP[63:0] := from Table 5-12

ELSE

Case(CmpOpCtl[1:0])

00: TMP[63:0] := (SRC1[63:0] ≤ SRC2[63:0]) ? SRC1[63:0] : SRC2[63:0];

01: TMP[63:0] := (SRC1[63:0] ≤ SRC2[63:0]) ? SRC2[63:0] : SRC1[63:0];

10: TMP[63:0] := (ABS(SRC1[63:0]) ≤ ABS(SRC2[63:0])) ? SRC1[63:0] : SRC2[63:0];

11: TMP[63:0] := (ABS(SRC1[63:0]) ≤ ABS(SRC2[63:0])) ? SRC2[63:0] : SRC1[63:0];

ESAC;

FI;

Case(SignSelCtl[1:0])

00: dest := (SRC1[63] << 63) OR (TMP[62:0]);// Preserve Src1 sign bit

01: dest := TMP[63:0];// Preserve sign of compare result

10: dest := (0 << 63) OR (TMP[62:0]);// Zero out sign bit

11: dest := (1 << 63) OR (TMP[62:0]);// Set the sign bit

ESAC;

RETURN dest[63:0];

}

CmpOpCtl[1:0]= imm8[1:0]; SignSelCtl[1:0]=imm8[3:2];

**VRANGESD**

IF k1[0] OR *no writemask*

THEN DEST[63:0] := RangeDP (SRC1[63:0], SRC2[63:0], CmpOpCtl[1:0], SignSelCtl[1:0]);

ELSE

IF *merging-masking*

; merging-masking

THEN *DEST[63:0] remains unchanged*

ELSE

; zeroing-masking

DEST[63:0] = 0

FI;

FI;

DEST[127:64] := SRC1[127:64]

DEST[MAXVL-1:128] := 0

The following example describes a common usage of this instruction for checking that the input operand is bound-ed between ±1023.

VRANGESD xmm_dst, xmm_src, xmm_1023, 02h;

Where: xmm_dst is the destination operand. xmm_src is the input operand to compare against ±1023. xmm_1023 is the reference operand, contains the value of 1023. IMM=02(imm8[1:0]=’10) selects the Min Absolute value operation with selection of src1.sign.

In case |xmm_src| < 1023, then its value will be written into xmm_dst. Otherwise, the value stored in xmm_dst will get the value of 1023 (received on xmm_1023). However, the sign control (imm8[3:2]=’00) instructs to select the sign of SRC1 received from xmm_src. So, even in the case of |xmm_src| ≥ 1023, the selected sign of SRC1 is kept. Thus, if xmm_src < -1023, the result of VRANGEPD will be the minimal value of -1023while if xmm_src > +1023, the result of VRANGE will be the maximal value of +1023.

**Intel C/C++ Compiler Intrinsic Equivalent**

VRANGESD __m128d _mm_range_sd ( __m128d a, __m128d b, int imm); VRANGESD __m128d _mm_range_round_sd ( __m128d a, __m128d b, int imm, int sae); VRANGESD __m128d _mm_mask_range_sd (__m128d s, __mmask8 k, __m128d a, __m128d b, int imm); VRANGESD __m128d _mm_mask_range_round_sd (__m128d s, __mmask8 k, __m128d a, __m128d b, int imm, int sae); VRANGESD __m128d _mm_maskz_range_sd ( __mmask8 k, __m128d a, __m128d b, int imm); VRANGESD __m128d _mm_maskz_range_round_sd ( __mmask8 k, __m128d a, __m128d b, int imm, int sae);

**SIMD Floating-Point Exceptions**

Invalid, Denormal

**Other Exceptions**

See Table 2-47, “Type E3 Class Exception Conditions”.