1. Integer Arithmetic#

1.1. dp4a#

Compute the dot product of four pairs of bytes from two 32-bit operands, and add a 32-bit accumulator.

Semantics:

src2_signed = .signedness == .us || .signedness == .ss
src1_signed = .signedness == .su || .signedness == .ss

if (src1_signed) {
  src1_0 = sign_extend(src1[7:0], 32)
  src1_1 = sign_extend(src1[15:8], 32)
  src1_2 = sign_extend(src1[23:16], 32)
  src1_3 = sign_extend(src1[31:24], 32)
} else {
  src1_0 = zero_extend(src1[7:0], 32)
  src1_1 = zero_extend(src1[15:8], 32)
  src1_2 = zero_extend(src1[23:16], 32)
  src1_3 = zero_extend(src1[31:24], 32)
}
if (src2_signed) {
  src2_0 = sign_extend(src2[7:0], 32)
  src2_1 = sign_extend(src2[15:8], 32)
  src2_2 = sign_extend(src2[23:16], 32)
  src2_3 = sign_extend(src2[31:24], 32)
} else {
  src2_0 = zero_extend(src2[7:0], 32)
  src2_1 = zero_extend(src2[15:8], 32)
  src2_2 = zero_extend(src2[23:16], 32)
  src2_3 = zero_extend(src2[31:24], 32)
}
dst = src0 + src1_0*src2_0 + src1_1*src2_1 + src1_2*src2_2 + src1_3*src2_3

Notes:

Enabling saturation via .dsat qualifier clamps the final result to between the min/max values representable by signed 32-bit integer. The addition of the results of the multiplications cannot overflow, but the addition of src0 can cause overflow and therefore obeys the saturation control.

Examples:

.reg .32b %dst, %src0, %src1, %src2;

// src0, src1, and src2 are treated as unsigned
dp4a.uu.32b  %dst, %src0, %src1, %src2;
// src1 is treated as signed, src2 as unsigned
dp4a.su.32b  %dst, %src0, %src1, %src2;
// src0, src1, and src2 are treated as signed with saturation
dp4a.ss.dsat.32b  %dst, %src0, %src1, %src2;

1.2. iabs#

Compute the absolute value of an integer.

Semantics:

default#
dst = |src0|

Examples:

.reg .32b %dst, %src0;

// absolute value of a 32-bit element
iabs.32b  %dst, %src0;

1.3. iadd#

Add two integer values.

Semantics:

.type == .16bx2#
dst[15:0] = src0[15:0] + src1[15:0]
dst[31:16] = src0[31:16] + src1[31:16]
.type == .8bx4#
dst[7:0] = src0[7:0] + src1[7:0]
dst[15:8] = src0[15:8] + src1[15:8]
dst[23:16] = src0[23:16] + src1[23:16]
dst[31:24] = src0[31:24] + src1[31:24]
default#
dst = src0 + src1

Notes:

Enabling the .dsat qualifier clamps the final result to the minimum and maximum values representable by a signed integer of the element bitwidth of the specified .type.

Examples:

.reg .32b %dst, %src0, %src1;

// addition of 32-bit elements
iadd.32b  %dst, %src0, %src1;
// element-wise addition of 4x8-bit packed values
.reg .v4.8b %dst_4x8, %src0_4x8, %src1_4x8;
iadd.8bx4  %dst_4x8, %src0_4x8, %src1_4x8;
// element-wise addition of 2x16-bit packed values
.reg .v2.16b %dst_packed, %src0_packed, %src1_packed;
iadd.16bx2  %dst_packed, %src0_packed, %src1_packed;

1.4. ineg#

Negate an integer value.

Semantics:

dst = -src0

Examples:

.reg .32b %dst, %src0;

// negate 32-bit element
ineg.32b  %dst, %src0;

1.5. isub#

Subtract two integer values.

Semantics:

.type == .16bx2#
dst[15:0] = src0[15:0] - src1[15:0]
dst[31:16] = src0[31:16] - src1[31:16]
default#
dst = src0 - src1

Notes:

Enabling the .dsat qualifier clamps the final result to the minimum and maximum values representable by a signed integer of the element bitwidth of the specified .type.

Examples:

.reg .32b %dst, %src0, %src1;

// subtraction of 32-bit elements
isub.32b  %dst, %src0, %src1;
// element-wise subtraction of 2x16-bit packed values
.reg .v2.16b %dst_packed, %src0_packed, %src1_packed;
isub.16bx2  %dst_packed, %src0_packed, %src1_packed;

1.6. sdiv#

Divide two signed integers.

Semantics:

.output == .rem#
dst = src0 % src1
default#
dst = src0 / src1

Notes:

Division by zero is undefined behavior.

Examples:

.reg .32b %dst, %src0, %src1;

// compute quotent from 32-bit signed integer division
sdiv.quo.32b  %dst, %src0, %src1;
// compute remainder from 32-bit signed integer division
sdiv.rem.32b  %dst, %src0, %src1;

1.7. smad#

Multiply and add signed integers.

Semantics:

.precision == .full#
src0_extend = sign_extend(src0, bitwidth(.type)*2)
src1_extend = sign_extend(src1, bitwidth(.type)*2)
dst = src0_extend * src1_extend + src2
.type == .16bx2#
dst[15:0] = src0[15:0] * src1[15:0] + src2[15:0]
dst[31:16] = src0[31:16] * src1[31:16] + src2[31:16]
default#
dst = src0 * src1 + src2

Examples:

.reg .32b %dst, %src0, %src1, %src2;
.reg .64b %dst64, %src64;

// signed multiply and add 32-bit elements
smad.32b  %dst, %src0, %src1, %src2;
// signed multiply and add 32-bit elements with full precision
smad.full.32b  %dst64, %src0, %src1, %src64;
// element-wise signed multiply and add of 2x16-bit packed values
.reg .v2.16b %dst_packed, %src0_packed, %src1_packed, %src2_packed;
smad.16bx2  %dst_packed, %src0_packed, %src1_packed, %src2_packed;

1.8. smax#

Find the maximum of two signed integers.

Semantics:

.type == .16bx2#
dst[15:0] = src0[15:0] > src1[15:0] ? src0[15:0] : src1[15:0]
dst[31:16] = src0[31:16] > src1[31:16] ? src0[31:16] : src1[31:16]
.type == .8bx4#
dst[7:0] = src0[7:0] > src1[7:0] ? src0[7:0] : src1[7:0]
dst[15:8] = src0[15:8] > src1[15:8] ? src0[15:8] : src1[15:8]
dst[23:16] = src0[23:16] > src1[23:16] ? src0[23:16] : src1[23:16]
dst[31:24] = src0[31:24] > src1[31:24] ? src0[31:24] : src1[31:24]
default#
dst = src0 > src1 ? src0 : src1

Examples:

.reg .32b %dst, %src0, %src1;

// maximum element from 2 signed 32-bit elements
smax.32b  %dst, %src0, %src1;
// element-wise maximum of 2x16-bit packed values
.reg .v2.16b %dst_packed, %src0_packed, %src1_packed;
smax.16bx2  %dst_packed, %src0_packed, %src1_packed;
// element-wise maximum of 4x8-bit packed values
.reg .v4.8b %dst_4x8, %src0_4x8, %src1_4x8;
smax.8bx4  %dst_4x8, %src0_4x8, %src1_4x8;

1.9. smin#

Find the minimum of two signed integers.

Semantics:

.type == .16bx2#
dst[15:0] = src0[15:0] < src1[15:0] ? src0[15:0] : src1[15:0]
dst[31:16] = src0[31:16] < src1[31:16] ? src0[31:16] : src1[31:16]
.type == .8bx4#
dst[7:0] = src0[7:0] < src1[7:0] ? src0[7:0] : src1[7:0]
dst[15:8] = src0[15:8] < src1[15:8] ? src0[15:8] : src1[15:8]
dst[23:16] = src0[23:16] < src1[23:16] ? src0[23:16] : src1[23:16]
dst[31:24] = src0[31:24] < src1[31:24] ? src0[31:24] : src1[31:24]
default#
dst = src0 < src1 ? src0 : src1

Examples:

.reg .32b %dst, %src0, %src1;

// minimum element from 2 signed 32-bit elements
smin.32b  %dst, %src0, %src1;
// element-wise minimum of 2x16-bit packed values
.reg .v2.16b %dst_packed, %src0_packed, %src1_packed;
smin.16bx2  %dst_packed, %src0_packed, %src1_packed;
// element-wise minimum of 4x8-bit packed values
.reg .v4.8b %dst_4x8, %src0_4x8, %src1_4x8;
smin.8bx4  %dst_4x8, %src0_4x8, %src1_4x8;

1.10. smul#

Multiply two signed integers.

Semantics:

.precision == .full#
src0_extend = sign_extend(src0, bitwidth(.type)*2)
src1_extend = sign_extend(src1, bitwidth(.type)*2)
dst = src0_extend * src1_extend
.type == .16bx2#
dst[15:0] = src0[15:0] * src1[15:0]
dst[31:16] = src0[31:16] * src1[31:16]
default#
dst = src0 * src1

Examples:

.reg .32b %dst, %src0, %src1;
.reg .64b %dst64;

// signed multiply 32-bit elements
smul.32b  %dst, %src0, %src1;
// signed multiply 32-bit elements with full precision
smul.full.32b  %dst64, %src0, %src1;
// element-wise signed multiply of 2x16-bit packed values
.reg .v2.16b %dst_packed, %src0_packed, %src1_packed;
smul.16bx2  %dst_packed, %src0_packed, %src1_packed;

1.11. uaddc#

Add unsigned integers with carry.

Semantics:

if ('.ci' is set)
   dst = src0 + src1 + carry-in
else
   dst = src0 + src1

if ('.co' is set)
   carry-out = 1 if the result overflows uint32, 0 otherwise

Examples:

Add two 32-bit unsigned values with carry#
.reg .32b %dst, %src0, %src1;
.pred %pin, %pout;

// add two 32-bit unsigned values with carry-out
uaddc.co.32b  %dst, %pout, %src0, %src1;
// add two 32-bit unsigned values with carry-in
uaddc.ci.32b  %dst, %src0, %src1, %pin;
64-bit unsigned addition emulated with two 32-bit uaddc instructions#
.reg .64b %dst, %src0, %src1;
.reg .v2.32b %dst_vec, %src0_vec, %src1_vec;
.pred %p0;

// unpack 64-bit operands into 32-bit halves (.x = low, .y = high)
mov.64b  %src0_vec.xy, %src0;
mov.64b  %src1_vec.xy, %src1;
// add low 32-bit halves with carry-out
uaddc.co.32b  %dst_vec.x, %p0, %src0_vec.x, %src1_vec.x;
// add high 32-bit halves with carry-in
uaddc.ci.32b  %dst_vec.y, %src0_vec.y, %src1_vec.y, %p0;
// pack 32-bit halves back into 64-bit result
mov.64b  %dst, %dst_vec.xy;

1.12. udiv#

Divide two unsigned integers.

Semantics:

.output == .rem#
dst = src0 % src1
default#
dst = src0 / src1

Notes:

Division by zero is undefined behavior.

Examples:

.reg .32b %dst, %src0, %src1;

// compute quotent from 32-bit unsigned integer division
udiv.quo.32b  %dst, %src0, %src1;
// compute remainder from 32-bit unsigned integer division
udiv.rem.32b  %dst, %src0, %src1;

1.13. umad#

Multiply and add unsigned integers.

Semantics:

.precision == .full#
src0_extend = zero_extend(src0, bitwidth(.type)*2)
src1_extend = zero_extend(src1, bitwidth(.type)*2)
dst = src0_extend * src1_extend + src2
default#
dst = src0 * src1 + src2

Examples:

.reg .32b %dst, %src0, %src1, %src2;
.reg .64b %dst64, %src64;

// unsigned multiply and add 32-bit elements
umad.32b  %dst, %src0, %src1, %src2;
// unsigned multiply and add 32-bit elements with full precision
umad.full.32b  %dst64, %src0, %src1, %src64;

1.14. umax#

Find the maximum of two unsigned integers.

Semantics:

.type == .16bx2#
dst[15:0] = src0[15:0] > src1[15:0] ? src0[15:0] : src1[15:0]
dst[31:16] = src0[31:16] > src1[31:16] ? src0[31:16] : src1[31:16]
default#
dst = src0 > src1 ? src0 : src1

Examples:

.reg .32b %dst, %src0, %src1;

// maximum element from 2 unsigned 32-bit elements
umax.32b  %dst, %src0, %src1;
// element-wise maximum of 2x16-bit packed values
.reg .v2.16b %dst_packed, %src0_packed, %src1_packed;
umax.16bx2  %dst_packed, %src0_packed, %src1_packed;

1.15. umin#

Find the minimum of two unsigned integers.

Semantics:

.type == .16bx2#
dst[15:0] = src0[15:0] < src1[15:0] ? src0[15:0] : src1[15:0]
dst[31:16] = src0[31:16] < src1[31:16] ? src0[31:16] : src1[31:16]
default#
dst = src0 < src1 ? src0 : src1

Examples:

.reg .32b %dst, %src0, %src1;

// minimum element from 2 unsigned 32-bit elements
umin.32b  %dst, %src0, %src1;
// element-wise minimum of 2x16-bit packed values
.reg .v2.16b %dst_packed, %src0_packed, %src1_packed;
umin.16bx2  %dst_packed, %src0_packed, %src1_packed;

1.16. umul#

Multiply two unsigned integers.

Semantics:

.precision == .full#
src0_extend = zero_extend(src0, bitwidth(.type)*2)
src1_extend = zero_extend(src1, bitwidth(.type)*2)
dst = src0_extend * src1_extend
default#
dst = src0 * src1

Examples:

.reg .32b %dst, %src0, %src1;
.reg .64b %dst64;

// unsigned multiply 32-bit elements
umul.32b  %dst, %src0, %src1;
// unsigned multiply 32-bit elements with full precision
umul.full.32b  %dst64, %src0, %src1;