Skip to content

TCMMIMFP16PS_TCMMRLFP16PS

Henk-Jan Lebbink edited this page Jun 4, 2026 · 1 revision

TCMMIMFP16PS / TCMMRLFP16PS — Matrix Multiplication of Complex Tiles Accumulated into Packed Single Precision Tile

Opcode/ Instruction Op/ En 64/32 bit Mode Support CPUID Feature Flag Description
VEX.128.66.0F38.W0 6C 11:rrr:bbb TCMMIMFP16PS tmm1, tmm2, tmm3 A V/N.E. AMX_COMPLEX Matrix multiply complex elements from tmm2 and tmm3, and accumulate the imaginary part into single precision elements in tmm1.
VEX.128.NP.0F38.W0 6C 11:rrr:bbb TCMMRLFP16PS tmm1, tmm2, tmm3 A V/N.E. AMX_COMPLEX Matrix multiply complex elements from tmm2 and tmm3, and accumulate the real part into single precision elements in tmm1.

Instruction Operand Encoding

Op/En Tuple Operand 1 Operand 2 Operand 3 Operand 4
A N/A ModRM:reg (r, w) ModRM:r/m (r) VEX.vvvv (r) N/A

Description

These instructions perform matrix multiplication of two tiles containing complex elements and accumulate the results into a packed single precision tile. Each dword element in input tiles tmm2 and tmm3 is interpreted as a complex number with FP16 real part and FP16 imaginary part.

TCMMRLFP16PS calculates the real part of the result. For each possible combination of (row of tmm2, column of tmm3), the instruction performs a set of multiplication and accumulations on all corresponding complex numbers (one from tmm2 and one from tmm3). The real part of the tmm2 element is multiplied with the real part of the corresponding tmm3 element, and the negated imaginary part of the tmm2 element is multiplied with the imagi-nary part of the corresponding tmm3 elements. The two accumulated results are added, and then accumulated into the corresponding row and column of tmm1.

TCMMIMFP16PS calculates the imaginary part of the result. For each possible combination of (row of tmm2, column of tmm3), the instruction performs a set of multiplication and accumulations on all corresponding complex numbers (one from tmm2 and one from tmm3). The imaginary part of the tmm2 element is multiplied with the real part of the corresponding tmm3 element, and the real part of the tmm2 element is multiplied with the imaginary part of the corresponding tmm3 elements. The two accumulated results are added, and then accumulated into the corresponding row and column of tmm1.

“Round to nearest even” rounding mode is used when doing each accumulation of the FMA. Output denormals are always flushed to zero but FP16 input denormals are not treated as zero.

MXCSR is not consulted nor updated.

Any attempt to execute these instructions inside an Intel TSX transaction will result in a transaction abort.

Operation

TCMMIMFP16PS tsrcdest, tsrc1, tsrc2

// C = m x n (tsrcdest), A = m x k (tsrc1), B = k x n (tsrc2)
# src1 and src2 elements are pairs of fp16
elements_src1tsrc1.colsb / 4
elements_desttsrcdest.colsb / 4
elements_temptsrcdest.colsb / 2  // Count is in fp16 prior to horizontal
for m in 0 ... tsrcdest.rows-1:
    temp1[ 0 ... elements_temp-1] ← 0
    for k in 0 ... elements_src1-1:
        for n in 0 ... elements_dest-1:
            s1e = cvt_fp16_to_fp32(tsrc1.row[m].fp16[2*k+0])
                            // real
            s2e = cvt_fp16_to_fp32(tsrc2.row[k].fp16[2*n+0])
                            // real
            s1o = cvt_fp16_to_fp32(tsrc1.row[m].fp16[2*k+1])
                            // imaginary
            s2o = cvt_fp16_to_fp32(tsrc2.row[k].fp16[2*n+1])
                            // imaginary
            // FP32 FMA with DAZ=FTZ=1, RNE rounding.
            // MXCSR is neither consulted nor updated.
            // No exceptions raised or denoted.
            temp1.fp32[2*n+0] = fma32(temp1.fp32[2*n+0], s1o, s2e, daz=1, ftz=1, sae=1, rc=RNE)
            temp1.fp32[2*n+1] = fma32(temp1.fp32[2*n+1], s1e, s2o, daz=1, ftz=1, sae=1, rc=RNE)
    for n in 0 ... elements_dest-1:
        // DAZ=FTZ=1, RNE rounding.
        // MXCSR is neither consulted nor updated.
        // No exceptions raised or denoted.
        tmpf32temp1.fp32[2*n] + temp1.fp32[2*n+1]
        srcdest.row[m].fp32[n] ← srcdest.row[m].fp32[n] + tmpf32
    write_row_and_zero(tsrcdest, m, tmp, tsrcdest.colsb)
zero_upper_rows(tsrcdest, tsrcdest.rows)
zero_tileconfig_start()

TCMMRLFP16PS tsrcdest, tsrc1, tsrc2

// C = m x n (tsrcdest), A = m x k (tsrc1), B = k x n (tsrc2)
# src1 and src2 elements are pairs of fp16
elements_src1tsrc1.colsb / 4
elements_desttsrcdest.colsb / 4
elements_temptsrcdest.colsb / 2 // Count is in fp16 prior to horizontal
for m in 0 ... tsrcdest.rows-1:
    temp1[ 0 ... elements_temp-1 ] ← 0
    for k in 0 ... elements_src1-1:
        for n in 0 ... elements_dest-1:
            s1e = cvt_fp16_to_fp32(tsrc1.row[m].fp16[2*k+0])
                            // real
            s2e = cvt_fp16_to_fp32(tsrc2.row[k].fp16[2*n+0])
                            // real
            s1o = cvt_fp16_to_fp32(-tsrc1.row[m].fp16[2*k+1]) // imaginary: “-” is for imaginary*imaginary
            s2o = cvt_fp16_to_fp32(tsrc2.row[k].fp16[2*n+1])
                            // imaginary
            //   FP32 FMA with DAZ=FTZ=1, RNE rounding.
            //   MXCSR is neither consulted nor updated.
            //   No exceptions raised or denoted.
            temp1.fp32[2*n+0] = fma32(temp1.fp32[2*n+0], s1e, s2e, daz=1, ftz=1, sae=1, rc=RNE)
                            // real
            temp1.fp32[2*n+1] = fma32(temp1.fp32[2*n+1], s1o, s2o, daz=1, ftz=1, sae=1, rc=RNE)
                            // imaginary
    for n in 0 ... elements_dest-1:
        // DAZ=FTZ=1, RNE rounding.
        // MXCSR is neither consulted nor updated.
        // No exceptions raised or denoted.
        tmpf32temp1.fp32[2*n] + temp1.fp32[2*n+1]
        srcdest.row[m].fp32[n] ← srcdest.row[m].fp32[n] + tmpf32
    write_row_and_zero(tsrcdest, m, tmp, tsrcdest.colsb)
zero_upper_rows(tsrcdest, tsrcdest.rows)
zero_tileconfig_start()

Flags Affected

None.

Exceptions


Source: Intel® 64 and IA-32 Architectures Software Developer's Manual, Combined Volumes (Order Number 325462-091US, March 2026)
Generated: 7-6-2026

Clone this wiki locally