Skip to main content

core/stdarch/crates/core_arch/src/x86_64/
amx.rs

1use crate::core_arch::x86_64::{__tile1024i, Tile};
2use crate::core_arch::{simd::*, x86::*};
3
4#[cfg(test)]
5use stdarch_test::assert_instr;
6
7/// Load tile configuration from a 64-byte memory location specified by `mem_addr`.
8/// The tile configuration format is specified below, and includes the tile type pallette,
9/// the number of bytes per row, and the number of rows. If the specified pallette_id is zero,
10/// that signifies the init state for both the tile config and the tile data, and the tiles are zeroed.
11/// Any invalid configurations will result in #GP fault.
12///
13/// ```intel
14/// //	format of memory payload. each field is a byte.
15///		 0: palette
16///		 1: start_row
17///	  2-15: reserved, must be zero
18///	 16-17: tile0.colsb
19///	 18-19: tile1.colsb
20///	 20-21: tile2.colsb
21///			...
22///	 30-31: tile7.colsb
23///	 32-47: reserved, must be zero
24///		48: tile0.rows
25///		49: tile1.rows
26///		50: tile2.rows
27///			 ...
28///		55: tile7.rows
29///	 56-63: reserved, must be zero
30/// ```
31///
32/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_loadconfig&ig_expand=6875)
33#[inline]
34#[target_feature(enable = "amx-tile")]
35#[cfg_attr(test, assert_instr(ldtilecfg))]
36#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
37pub unsafe fn _tile_loadconfig(mem_addr: *const u8) {
38    ldtilecfg(mem_addr);
39}
40
41/// Stores the current tile configuration to a 64-byte memory location specified by `mem_addr`.
42/// The tile configuration format is as specified in [`_tile_loadconfig`], and includes the tile type pallette,
43/// the number of bytes per row, and the number of rows. If tiles are not configured, all zeroes will be stored to memory.
44///
45/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_storeconfig&ig_expand=6879)
46#[inline]
47#[target_feature(enable = "amx-tile")]
48#[cfg_attr(test, assert_instr(sttilecfg))]
49#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
50pub unsafe fn _tile_storeconfig(mem_addr: *mut u8) {
51    sttilecfg(mem_addr);
52}
53
54/// Load tile rows from memory specified by base address and stride into destination tile dst using the tile configuration previously configured via [`_tile_loadconfig`].
55///
56/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_loadd&ig_expand=6877)
57#[inline]
58#[rustc_legacy_const_generics(0)]
59#[target_feature(enable = "amx-tile")]
60#[cfg_attr(test, assert_instr(tileloadd, DST = 0))]
61#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
62pub unsafe fn _tile_loadd<const DST: i32>(base: *const u8, stride: usize) {
63    static_assert_uimm_bits!(DST, 3);
64    tileloadd64(DST as i8, base, stride as u64);
65}
66
67/// Load tile rows from memory specified by base address and stride into destination tile dst. The shape
68/// of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
69///
70/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_loadd&ig_expand=6877)
71#[inline]
72#[target_feature(enable = "amx-tile")]
73#[cfg_attr(test, assert_instr(tileloadd))]
74#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
75pub unsafe fn __tile_loadd(dst: *mut __tile1024i, base: *const u8, stride: usize) {
76    (*dst).tile = tileloadd64_internal((*dst).rows, (*dst).colsb, base, stride as u64);
77}
78
79/// Release the tile configuration to return to the init state, which releases all storage it currently holds.
80///
81/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_release&ig_expand=6878)
82#[inline]
83#[target_feature(enable = "amx-tile")]
84#[cfg_attr(test, assert_instr(tilerelease))]
85#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
86pub unsafe fn _tile_release() {
87    tilerelease();
88}
89
90/// Store the tile specified by src to memory specified by base address and stride using the tile configuration previously configured via [`_tile_loadconfig`].
91///
92/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_stored&ig_expand=6881)
93#[inline]
94#[rustc_legacy_const_generics(0)]
95#[target_feature(enable = "amx-tile")]
96#[cfg_attr(test, assert_instr(tilestored, DST = 0))]
97#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
98pub unsafe fn _tile_stored<const DST: i32>(base: *mut u8, stride: usize) {
99    static_assert_uimm_bits!(DST, 3);
100    tilestored64(DST as i8, base, stride as u64);
101}
102
103/// Store the tile specified by src to memory specified by base address and stride. The shape of the tile
104/// is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
105///
106/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_stored&ig_expand=6881)
107#[inline]
108#[target_feature(enable = "amx-tile")]
109#[cfg_attr(test, assert_instr(tilestored))]
110#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
111pub unsafe fn __tile_stored(base: *mut u8, stride: usize, src: __tile1024i) {
112    tilestored64_internal(src.rows, src.colsb, base, stride as u64, src.tile);
113}
114
115/// Load tile rows from memory specified by base address and stride into destination tile dst using the tile configuration
116/// previously configured via [`_tile_loadconfig`]. This intrinsic provides a hint to the implementation that the data will
117/// likely not be reused in the near future and the data caching can be optimized accordingly.
118///
119/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_stream_loadd&ig_expand=6883)
120#[inline]
121#[rustc_legacy_const_generics(0)]
122#[target_feature(enable = "amx-tile")]
123#[cfg_attr(test, assert_instr(tileloaddt1, DST = 0))]
124#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
125pub unsafe fn _tile_stream_loadd<const DST: i32>(base: *const u8, stride: usize) {
126    static_assert_uimm_bits!(DST, 3);
127    tileloaddt164(DST as i8, base, stride as u64);
128}
129
130/// Load tile rows from memory specified by base address and stride into destination tile dst. The shape
131/// of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
132/// This intrinsic provides a hint to the implementation that the data will likely not be reused in the
133/// near future and the data caching can be optimized accordingly.
134///
135/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_stream_loadd&ig_expand=6883)
136#[inline]
137#[target_feature(enable = "amx-tile")]
138#[cfg_attr(test, assert_instr(tileloaddt1))]
139#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
140pub unsafe fn __tile_stream_loadd(dst: *mut __tile1024i, base: *const u8, stride: usize) {
141    (*dst).tile = tileloaddt164_internal((*dst).rows, (*dst).colsb, base, stride as u64);
142}
143
144/// Zero the tile specified by `tdest`.
145///
146/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_zero&ig_expand=6885)
147#[inline]
148#[rustc_legacy_const_generics(0)]
149#[target_feature(enable = "amx-tile")]
150#[cfg_attr(test, assert_instr(tilezero, DST = 0))]
151#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
152pub unsafe fn _tile_zero<const DST: i32>() {
153    static_assert_uimm_bits!(DST, 3);
154    tilezero(DST as i8);
155}
156
157/// Zero the tile specified by `dst`. The shape of the tile is specified in the struct of [`__tile1024i`].
158/// The register of the tile is allocated by the compiler.
159///
160/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_zero&ig_expand=6885)
161#[inline]
162#[target_feature(enable = "amx-tile")]
163#[cfg_attr(test, assert_instr(tilezero))]
164#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
165pub unsafe fn __tile_zero(dst: *mut __tile1024i) {
166    (*dst).tile = tilezero_internal((*dst).rows, (*dst).colsb);
167}
168
169/// Compute dot-product of BF16 (16-bit) floating-point pairs in tiles a and b,
170/// accumulating the intermediate single-precision (32-bit) floating-point elements
171/// with elements in dst, and store the 32-bit result back to tile dst.
172///
173/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_dpbf16ps&ig_expand=6864)
174#[inline]
175#[rustc_legacy_const_generics(0, 1, 2)]
176#[target_feature(enable = "amx-bf16")]
177#[cfg_attr(test, assert_instr(tdpbf16ps, DST = 0, A = 1, B = 2))]
178#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
179pub unsafe fn _tile_dpbf16ps<const DST: i32, const A: i32, const B: i32>() {
180    static_assert_uimm_bits!(DST, 3);
181    static_assert_uimm_bits!(A, 3);
182    static_assert_uimm_bits!(B, 3);
183    tdpbf16ps(DST as i8, A as i8, B as i8);
184}
185
186/// Compute dot-product of FP16 (16-bit) floating-point pairs in tiles a and b,
187/// accumulating the intermediate single-precision (32-bit) floating-point elements
188/// with elements in dst, and store the 32-bit result back to tile dst. The shape of the tile
189/// is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
190///
191/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_dpbf16ps&ig_expand=6864)
192#[inline]
193#[target_feature(enable = "amx-bf16")]
194#[cfg_attr(test, assert_instr(tdpbf16ps))]
195#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
196pub unsafe fn __tile_dpbf16ps(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
197    (*dst).tile = tdpbf16ps_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
198}
199
200/// Compute dot-product of bytes in tiles with a source/destination accumulator.
201/// Multiply groups of 4 adjacent pairs of signed 8-bit integers in a with corresponding
202/// signed 8-bit integers in b, producing 4 intermediate 32-bit results.
203/// Sum these 4 results with the corresponding 32-bit integer in dst, and store the 32-bit result back to tile dst.
204///
205/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_dpbssd&ig_expand=6866)
206#[inline]
207#[rustc_legacy_const_generics(0, 1, 2)]
208#[target_feature(enable = "amx-int8")]
209#[cfg_attr(test, assert_instr(tdpbssd, DST = 0, A = 1, B = 2))]
210#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
211pub unsafe fn _tile_dpbssd<const DST: i32, const A: i32, const B: i32>() {
212    static_assert_uimm_bits!(DST, 3);
213    static_assert_uimm_bits!(A, 3);
214    static_assert_uimm_bits!(B, 3);
215    tdpbssd(DST as i8, A as i8, B as i8);
216}
217
218/// Compute dot-product of bytes in tiles with a source/destination accumulator.
219/// Multiply groups of 4 adjacent pairs of signed 8-bit integers in a with corresponding
220/// signed 8-bit integers in b, producing 4 intermediate 32-bit results.
221/// Sum these 4 results with the corresponding 32-bit integer in dst, and store the 32-bit result back to tile dst.
222/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
223///
224/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_dpbssd&ig_expand=6866)
225#[inline]
226#[target_feature(enable = "amx-int8")]
227#[cfg_attr(test, assert_instr(tdpbssd))]
228#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
229pub unsafe fn __tile_dpbssd(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
230    (*dst).tile = tdpbssd_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
231}
232
233/// Compute dot-product of bytes in tiles with a source/destination accumulator.
234/// Multiply groups of 4 adjacent pairs of signed 8-bit integers in a with corresponding
235/// unsigned 8-bit integers in b, producing 4 intermediate 32-bit results.
236/// Sum these 4 results with the corresponding 32-bit integer in dst, and store the 32-bit result back to tile dst.
237///
238/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_dpbsud&ig_expand=6868)
239#[inline]
240#[rustc_legacy_const_generics(0, 1, 2)]
241#[target_feature(enable = "amx-int8")]
242#[cfg_attr(test, assert_instr(tdpbsud, DST = 0, A = 1, B = 2))]
243#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
244pub unsafe fn _tile_dpbsud<const DST: i32, const A: i32, const B: i32>() {
245    static_assert_uimm_bits!(DST, 3);
246    static_assert_uimm_bits!(A, 3);
247    static_assert_uimm_bits!(B, 3);
248    tdpbsud(DST as i8, A as i8, B as i8);
249}
250
251/// Compute dot-product of bytes in tiles with a source/destination accumulator.
252/// Multiply groups of 4 adjacent pairs of signed 8-bit integers in a with corresponding
253/// unsigned 8-bit integers in b, producing 4 intermediate 32-bit results.
254/// Sum these 4 results with the corresponding 32-bit integer in dst, and store the 32-bit result back to tile dst.
255/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
256///
257/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_dpbsud&ig_expand=6868)
258#[inline]
259#[target_feature(enable = "amx-int8")]
260#[cfg_attr(test, assert_instr(tdpbsud))]
261#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
262pub unsafe fn __tile_dpbsud(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
263    (*dst).tile = tdpbsud_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
264}
265
266/// Compute dot-product of bytes in tiles with a source/destination accumulator.
267/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding
268/// signed 8-bit integers in b, producing 4 intermediate 32-bit results.
269/// Sum these 4 results with the corresponding 32-bit integer in dst, and store the 32-bit result back to tile dst.
270///
271/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_dpbusd&ig_expand=6870)
272#[inline]
273#[rustc_legacy_const_generics(0, 1, 2)]
274#[target_feature(enable = "amx-int8")]
275#[cfg_attr(test, assert_instr(tdpbusd, DST = 0, A = 1, B = 2))]
276#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
277pub unsafe fn _tile_dpbusd<const DST: i32, const A: i32, const B: i32>() {
278    static_assert_uimm_bits!(DST, 3);
279    static_assert_uimm_bits!(A, 3);
280    static_assert_uimm_bits!(B, 3);
281    tdpbusd(DST as i8, A as i8, B as i8);
282}
283
284/// Compute dot-product of bytes in tiles with a source/destination accumulator.
285/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding
286/// signed 8-bit integers in b, producing 4 intermediate 32-bit results.
287/// Sum these 4 results with the corresponding 32-bit integer in dst, and store the 32-bit result back to tile dst.
288/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
289///
290/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_dpbusd&ig_expand=6870)
291#[inline]
292#[target_feature(enable = "amx-int8")]
293#[cfg_attr(test, assert_instr(tdpbusd))]
294#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
295pub unsafe fn __tile_dpbusd(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
296    (*dst).tile = tdpbusd_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
297}
298
299/// Compute dot-product of bytes in tiles with a source/destination accumulator.
300/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding
301/// unsigned 8-bit integers in b, producing 4 intermediate 32-bit results.
302/// Sum these 4 results with the corresponding 32-bit integer in dst, and store the 32-bit result back to tile dst.
303///
304/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_dpbuud&ig_expand=6872)
305#[inline]
306#[rustc_legacy_const_generics(0, 1, 2)]
307#[target_feature(enable = "amx-int8")]
308#[cfg_attr(test, assert_instr(tdpbuud, DST = 0, A = 1, B = 2))]
309#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
310pub unsafe fn _tile_dpbuud<const DST: i32, const A: i32, const B: i32>() {
311    static_assert_uimm_bits!(DST, 3);
312    static_assert_uimm_bits!(A, 3);
313    static_assert_uimm_bits!(B, 3);
314    tdpbuud(DST as i8, A as i8, B as i8);
315}
316
317/// Compute dot-product of bytes in tiles with a source/destination accumulator.
318/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in a with corresponding
319/// unsigned 8-bit integers in b, producing 4 intermediate 32-bit results.
320/// Sum these 4 results with the corresponding 32-bit integer in dst, and store the 32-bit result back to tile dst.
321/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
322///
323/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_dpbuud&ig_expand=6872)
324#[inline]
325#[target_feature(enable = "amx-int8")]
326#[cfg_attr(test, assert_instr(tdpbuud))]
327#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
328pub unsafe fn __tile_dpbuud(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
329    (*dst).tile = tdpbuud_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
330}
331
332/// Compute dot-product of FP16 (16-bit) floating-point pairs in tiles a and b,
333/// accumulating the intermediate single-precision (32-bit) floating-point elements
334///  with elements in dst, and store the 32-bit result back to tile dst.
335///
336/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_dpfp16ps&ig_expand=6874)
337#[inline]
338#[rustc_legacy_const_generics(0, 1, 2)]
339#[target_feature(enable = "amx-fp16")]
340#[cfg_attr(test, assert_instr(tdpfp16ps, DST = 0, A = 1, B = 2))]
341#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
342pub unsafe fn _tile_dpfp16ps<const DST: i32, const A: i32, const B: i32>() {
343    static_assert_uimm_bits!(DST, 3);
344    static_assert_uimm_bits!(A, 3);
345    static_assert_uimm_bits!(B, 3);
346    tdpfp16ps(DST as i8, A as i8, B as i8);
347}
348
349/// Compute dot-product of FP16 (16-bit) floating-point pairs in tiles a and b,
350/// accumulating the intermediate single-precision (32-bit) floating-point elements
351///  with elements in dst, and store the 32-bit result back to tile dst.
352/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
353///
354/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_dpfp16ps&ig_expand=6874)
355#[inline]
356#[target_feature(enable = "amx-fp16")]
357#[cfg_attr(test, assert_instr(tdpfp16ps))]
358#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
359pub unsafe fn __tile_dpfp16ps(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
360    (*dst).tile = tdpfp16ps_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
361}
362
363/// Perform matrix multiplication of two tiles containing complex elements and accumulate the results into a packed single precision tile.
364/// Each dword element in input tiles a and b is interpreted as a complex number with FP16 real part and FP16 imaginary part.
365/// Calculates the imaginary part of the result. For each possible combination of (row of a, column of b),
366/// it performs a set of multiplication and accumulations on all corresponding complex numbers (one from a and one from b).
367/// The imaginary part of the a element is multiplied with the real part of the corresponding b element, and the real part of
368/// the a element is multiplied with the imaginary part of the corresponding b elements. The two accumulated results are added,
369/// and then accumulated into the corresponding row and column of dst.
370///
371/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_cmmimfp16ps&ig_expand=6860)
372#[inline]
373#[rustc_legacy_const_generics(0, 1, 2)]
374#[target_feature(enable = "amx-complex")]
375#[cfg_attr(test, assert_instr(tcmmimfp16ps, DST = 0, A = 1, B = 2))]
376#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
377pub unsafe fn _tile_cmmimfp16ps<const DST: i32, const A: i32, const B: i32>() {
378    static_assert_uimm_bits!(DST, 3);
379    static_assert_uimm_bits!(A, 3);
380    static_assert_uimm_bits!(B, 3);
381    tcmmimfp16ps(DST as i8, A as i8, B as i8);
382}
383
384/// Perform matrix multiplication of two tiles containing complex elements and accumulate the results into a packed single precision tile.
385/// Each dword element in input tiles a and b is interpreted as a complex number with FP16 real part and FP16 imaginary part.
386/// Calculates the imaginary part of the result. For each possible combination of (row of a, column of b),
387/// it performs a set of multiplication and accumulations on all corresponding complex numbers (one from a and one from b).
388/// The imaginary part of the a element is multiplied with the real part of the corresponding b element, and the real part of
389/// the a element is multiplied with the imaginary part of the corresponding b elements. The two accumulated results are added,
390/// and then accumulated into the corresponding row and column of dst.
391/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
392///
393/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_cmmimfp16ps&ig_expand=6860)
394#[inline]
395#[target_feature(enable = "amx-complex")]
396#[cfg_attr(test, assert_instr(tcmmimfp16ps))]
397#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
398pub unsafe fn __tile_cmmimfp16ps(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
399    (*dst).tile = tcmmimfp16ps_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
400}
401
402/// Perform matrix multiplication of two tiles containing complex elements and accumulate the results into a packed single precision tile.
403/// Each dword element in input tiles a and b is interpreted as a complex number with FP16 real part and FP16 imaginary part.
404/// Calculates the real part of the result. For each possible combination of (row of a, column of b),
405/// it performs a set of multiplication and accumulations on all corresponding complex numbers (one from a and one from b).
406/// The real part of the a element is multiplied with the real part of the corresponding b element, and the negated imaginary part of
407/// the a element is multiplied with the imaginary part of the corresponding b elements.
408/// The two accumulated results are added, and then accumulated into the corresponding row and column of dst.
409///
410/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_tile_cmmrlfp16ps&ig_expand=6862)
411#[inline]
412#[rustc_legacy_const_generics(0, 1, 2)]
413#[target_feature(enable = "amx-complex")]
414#[cfg_attr(test, assert_instr(tcmmrlfp16ps, DST = 0, A = 1, B = 2))]
415#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
416pub unsafe fn _tile_cmmrlfp16ps<const DST: i32, const A: i32, const B: i32>() {
417    static_assert_uimm_bits!(DST, 3);
418    static_assert_uimm_bits!(A, 3);
419    static_assert_uimm_bits!(B, 3);
420    tcmmrlfp16ps(DST as i8, A as i8, B as i8);
421}
422
423/// Perform matrix multiplication of two tiles containing complex elements and accumulate the results into a packed single precision tile.
424/// Each dword element in input tiles a and b is interpreted as a complex number with FP16 real part and FP16 imaginary part.
425/// Calculates the real part of the result. For each possible combination of (row of a, column of b),
426/// it performs a set of multiplication and accumulations on all corresponding complex numbers (one from a and one from b).
427/// The real part of the a element is multiplied with the real part of the corresponding b element, and the negated imaginary part of
428/// the a element is multiplied with the imaginary part of the corresponding b elements.
429/// The two accumulated results are added, and then accumulated into the corresponding row and column of dst.
430/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
431///
432/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=__tile_cmmrlfp16ps&ig_expand=6862)
433#[inline]
434#[target_feature(enable = "amx-complex")]
435#[cfg_attr(test, assert_instr(tcmmrlfp16ps))]
436#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
437pub unsafe fn __tile_cmmrlfp16ps(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
438    (*dst).tile = tcmmrlfp16ps_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
439}
440
441/// Compute dot-product of BF8 (8-bit E5M2) floating-point elements in tile a and BF8 (8-bit E5M2)
442/// floating-point elements in tile b, accumulating the intermediate single-precision
443/// (32-bit) floating-point elements with elements in dst, and store the 32-bit result
444/// back to tile dst.
445#[inline]
446#[rustc_legacy_const_generics(0, 1, 2)]
447#[target_feature(enable = "amx-fp8")]
448#[cfg_attr(
449    all(test, not(target_vendor = "apple")),
450    assert_instr(tdpbf8ps, DST = 0, A = 1, B = 2)
451)]
452#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
453pub unsafe fn _tile_dpbf8ps<const DST: i32, const A: i32, const B: i32>() {
454    static_assert_uimm_bits!(DST, 3);
455    static_assert_uimm_bits!(A, 3);
456    static_assert_uimm_bits!(B, 3);
457    tdpbf8ps(DST as i8, A as i8, B as i8);
458}
459
460/// Compute dot-product of BF8 (8-bit E5M2) floating-point elements in tile a and BF8 (8-bit E5M2)
461/// floating-point elements in tile b, accumulating the intermediate single-precision
462/// (32-bit) floating-point elements with elements in dst, and store the 32-bit result
463/// back to tile dst.
464/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
465#[inline]
466#[target_feature(enable = "amx-fp8")]
467#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tdpbf8ps))]
468#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
469pub unsafe fn __tile_dpbf8ps(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
470    (*dst).tile = tdpbf8ps_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
471}
472
473/// Compute dot-product of BF8 (8-bit E5M2) floating-point elements in tile a and HF8
474/// (8-bit E4M3) floating-point elements in tile b, accumulating the intermediate single-precision
475/// (32-bit) floating-point elements with elements in dst, and store the 32-bit result
476/// back to tile dst.
477#[inline]
478#[rustc_legacy_const_generics(0, 1, 2)]
479#[target_feature(enable = "amx-fp8")]
480#[cfg_attr(
481    all(test, not(target_vendor = "apple")),
482    assert_instr(tdpbhf8ps, DST = 0, A = 1, B = 2)
483)]
484#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
485pub unsafe fn _tile_dpbhf8ps<const DST: i32, const A: i32, const B: i32>() {
486    static_assert_uimm_bits!(DST, 3);
487    static_assert_uimm_bits!(A, 3);
488    static_assert_uimm_bits!(B, 3);
489    tdpbhf8ps(DST as i8, A as i8, B as i8);
490}
491
492/// Compute dot-product of BF8 (8-bit E5M2) floating-point elements in tile a and HF8
493/// (8-bit E4M3) floating-point elements in tile b, accumulating the intermediate single-precision
494/// (32-bit) floating-point elements with elements in dst, and store the 32-bit result
495/// back to tile dst.
496/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
497#[inline]
498#[target_feature(enable = "amx-fp8")]
499#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tdpbhf8ps))]
500#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
501pub unsafe fn __tile_dpbhf8ps(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
502    (*dst).tile = tdpbhf8ps_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
503}
504
505/// Compute dot-product of HF8 (8-bit E4M3) floating-point elements in tile a and BF8
506/// (8-bit E5M2) floating-point elements in tile b, accumulating the intermediate single-precision
507/// (32-bit) floating-point elements with elements in dst, and store the 32-bit result
508/// back to tile dst.
509#[inline]
510#[rustc_legacy_const_generics(0, 1, 2)]
511#[target_feature(enable = "amx-fp8")]
512#[cfg_attr(
513    all(test, not(target_vendor = "apple")),
514    assert_instr(tdphbf8ps, DST = 0, A = 1, B = 2)
515)]
516#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
517pub unsafe fn _tile_dphbf8ps<const DST: i32, const A: i32, const B: i32>() {
518    static_assert_uimm_bits!(DST, 3);
519    static_assert_uimm_bits!(A, 3);
520    static_assert_uimm_bits!(B, 3);
521    tdphbf8ps(DST as i8, A as i8, B as i8);
522}
523
524/// Compute dot-product of HF8 (8-bit E4M3) floating-point elements in tile a and BF8
525/// (8-bit E5M2) floating-point elements in tile b, accumulating the intermediate single-precision
526/// (32-bit) floating-point elements with elements in dst, and store the 32-bit result
527/// back to tile dst.
528/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
529#[inline]
530#[target_feature(enable = "amx-fp8")]
531#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tdphbf8ps))]
532#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
533pub unsafe fn __tile_dphbf8ps(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
534    (*dst).tile = tdphbf8ps_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
535}
536
537/// Compute dot-product of HF8 (8-bit E4M3) floating-point elements in tile a and HF8 (8-bit E4M3)
538/// floating-point elements in tile b, accumulating the intermediate single-precision
539/// (32-bit) floating-point elements with elements in dst, and store the 32-bit result
540/// back to tile dst.
541#[inline]
542#[rustc_legacy_const_generics(0, 1, 2)]
543#[target_feature(enable = "amx-fp8")]
544#[cfg_attr(
545    all(test, not(target_vendor = "apple")),
546    assert_instr(tdphf8ps, DST = 0, A = 1, B = 2)
547)]
548#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
549pub unsafe fn _tile_dphf8ps<const DST: i32, const A: i32, const B: i32>() {
550    static_assert_uimm_bits!(DST, 3);
551    static_assert_uimm_bits!(A, 3);
552    static_assert_uimm_bits!(B, 3);
553    tdphf8ps(DST as i8, A as i8, B as i8);
554}
555
556/// Compute dot-product of HF8 (8-bit E4M3) floating-point elements in tile a and HF8 (8-bit E4M3)
557/// floating-point elements in tile b, accumulating the intermediate single-precision
558/// (32-bit) floating-point elements with elements in dst, and store the 32-bit result
559/// back to tile dst.
560/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
561#[inline]
562#[target_feature(enable = "amx-fp8")]
563#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tdphf8ps))]
564#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
565pub unsafe fn __tile_dphf8ps(dst: *mut __tile1024i, a: __tile1024i, b: __tile1024i) {
566    (*dst).tile = tdphf8ps_internal(a.rows, b.colsb, a.colsb, (*dst).tile, a.tile, b.tile);
567}
568
569/// Load tile rows from memory specified by base address and stride into destination tile dst
570/// using the tile configuration previously configured via [`_tile_loadconfig`].
571/// Additionally, this intrinsic indicates the source memory location is likely to become
572/// read-shared by multiple processors, i.e., read in the future by at least one other processor
573/// before it is written, assuming it is ever written in the future.
574#[inline]
575#[rustc_legacy_const_generics(0)]
576#[target_feature(enable = "amx-movrs")]
577#[cfg_attr(
578    all(test, not(target_vendor = "apple")),
579    assert_instr(tileloaddrs, DST = 0)
580)]
581#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
582pub unsafe fn _tile_loaddrs<const DST: i32>(base: *const u8, stride: usize) {
583    static_assert_uimm_bits!(DST, 3);
584    tileloaddrs64(DST as i8, base, stride as u64);
585}
586
587/// Load tile rows from memory specified by base address and stride into destination tile dst.
588/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
589/// Additionally, this intrinsic indicates the source memory location is likely to become
590/// read-shared by multiple processors, i.e., read in the future by at least one other processor
591/// before it is written, assuming it is ever written in the future.
592#[inline]
593#[target_feature(enable = "amx-movrs")]
594#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tileloaddrs))]
595#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
596pub unsafe fn __tile_loaddrs(dst: *mut __tile1024i, base: *const u8, stride: usize) {
597    (*dst).tile = tileloaddrs64_internal((*dst).rows, (*dst).colsb, base, stride as u64);
598}
599
600/// Load tile rows from memory specified by base address and stride into destination tile dst
601/// using the tile configuration previously configured via [`_tile_loadconfig`].
602/// Provides a hint to the implementation that the data would be reused but does not need
603/// to be resident in the nearest cache levels.
604/// Additionally, this intrinsic indicates the source memory location is likely to become
605/// read-shared by multiple processors, i.e., read in the future by at least one other processor
606/// before it is written, assuming it is ever written in the future.
607#[inline]
608#[rustc_legacy_const_generics(0)]
609#[target_feature(enable = "amx-movrs")]
610#[cfg_attr(
611    all(test, not(target_vendor = "apple")),
612    assert_instr(tileloaddrst1, DST = 0)
613)]
614#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
615pub unsafe fn _tile_stream_loaddrs<const DST: i32>(base: *const u8, stride: usize) {
616    static_assert_uimm_bits!(DST, 3);
617    tileloaddrst164(DST as i8, base, stride as u64);
618}
619
620/// Load tile rows from memory specified by base address and stride into destination tile dst.
621/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
622/// Provides a hint to the implementation that the data would be reused but does not need
623/// to be resident in the nearest cache levels.
624/// Additionally, this intrinsic indicates the source memory location is likely to become
625/// read-shared by multiple processors, i.e., read in the future by at least one other processor
626/// before it is written, assuming it is ever written in the future.
627#[inline]
628#[target_feature(enable = "amx-movrs")]
629#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tileloaddrst1))]
630#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
631pub unsafe fn __tile_stream_loaddrs(dst: *mut __tile1024i, base: *const u8, stride: usize) {
632    (*dst).tile = tileloaddrst164_internal((*dst).rows, (*dst).colsb, base, stride as u64);
633}
634
635/// Moves a row from a tile register to a zmm register, converting the packed 32-bit signed integer
636/// elements to packed single-precision (32-bit) floating-point elements.
637#[inline]
638#[rustc_legacy_const_generics(0)]
639#[target_feature(enable = "amx-avx512,avx10.2")]
640#[cfg_attr(
641    all(test, not(target_vendor = "apple")),
642    assert_instr(tcvtrowd2ps, TILE = 0)
643)]
644#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
645pub unsafe fn _tile_cvtrowd2ps<const TILE: i32>(row: u32) -> __m512 {
646    static_assert_uimm_bits!(TILE, 3);
647    tcvtrowd2ps(TILE as i8, row).as_m512()
648}
649
650/// Moves a row from a tile register to a zmm register, converting the packed 32-bit signed integer
651/// elements to packed single-precision (32-bit) floating-point elements.
652#[inline]
653#[rustc_legacy_const_generics(0, 1)]
654#[target_feature(enable = "amx-avx512,avx10.2")]
655#[cfg_attr(
656    all(test, not(target_vendor = "apple")),
657    assert_instr(tcvtrowd2ps, TILE = 0, ROW = 0)
658)]
659#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
660pub unsafe fn _tile_cvtrowd2psi<const TILE: i32, const ROW: i32>() -> __m512 {
661    static_assert_uimm_bits!(TILE, 3);
662    static_assert_uimm_bits!(ROW, 6);
663    tcvtrowd2psi(TILE as i8, ROW as u32).as_m512()
664}
665
666/// Moves a row from a tile register to a zmm register, converting the packed 32-bit signed integer
667/// elements to packed single-precision (32-bit) floating-point elements.
668/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
669#[inline]
670#[target_feature(enable = "amx-avx512,avx10.2")]
671#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tcvtrowd2ps))]
672#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
673pub unsafe fn __tile_cvtrowd2ps(src: __tile1024i, row: u32) -> __m512 {
674    tcvtrowd2ps_internal(src.rows, src.colsb, src.tile, row).as_m512()
675}
676
677/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
678/// floating-point elements to packed half-precision (16-bit) floating-point elements. The resulting
679/// 16-bit elements are placed in the high 16-bits within each 32-bit element of the returned vector.
680#[inline]
681#[rustc_legacy_const_generics(0)]
682#[target_feature(enable = "amx-avx512,avx10.2")]
683#[cfg_attr(
684    all(test, not(target_vendor = "apple")),
685    assert_instr(tcvtrowps2phh, TILE = 0)
686)]
687#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
688pub unsafe fn _tile_cvtrowps2phh<const TILE: i32>(row: u32) -> __m512h {
689    static_assert_uimm_bits!(TILE, 3);
690    tcvtrowps2phh(TILE as i8, row).as_m512h()
691}
692
693/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
694/// floating-point elements to packed half-precision (16-bit) floating-point elements. The resulting
695/// 16-bit elements are placed in the high 16-bits within each 32-bit element of the returned vector.
696#[inline]
697#[rustc_legacy_const_generics(0, 1)]
698#[target_feature(enable = "amx-avx512,avx10.2")]
699#[cfg_attr(
700    all(test, not(target_vendor = "apple")),
701    assert_instr(tcvtrowps2phh, TILE = 0, ROW = 0)
702)]
703#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
704pub unsafe fn _tile_cvtrowps2phhi<const TILE: i32, const ROW: i32>() -> __m512h {
705    static_assert_uimm_bits!(TILE, 3);
706    static_assert_uimm_bits!(ROW, 6);
707    tcvtrowps2phhi(TILE as i8, ROW as u32).as_m512h()
708}
709
710/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
711/// floating-point elements to packed half-precision (16-bit) floating-point elements. The resulting
712/// 16-bit elements are placed in the high 16-bits within each 32-bit element of the returned vector.
713/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
714#[inline]
715#[target_feature(enable = "amx-avx512,avx10.2")]
716#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tcvtrowps2phh))]
717#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
718pub unsafe fn __tile_cvtrowps2phh(src: __tile1024i, row: u32) -> __m512h {
719    tcvtrowps2phh_internal(src.rows, src.colsb, src.tile, row).as_m512h()
720}
721
722/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
723/// floating-point elements to packed half-precision (16-bit) floating-point elements. The resulting
724/// 16-bit elements are placed in the low 16-bits within each 32-bit element of the returned vector.
725#[inline]
726#[rustc_legacy_const_generics(0)]
727#[target_feature(enable = "amx-avx512,avx10.2")]
728#[cfg_attr(
729    all(test, not(target_vendor = "apple")),
730    assert_instr(tcvtrowps2phl, TILE = 0)
731)]
732#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
733pub unsafe fn _tile_cvtrowps2phl<const TILE: i32>(row: u32) -> __m512h {
734    static_assert_uimm_bits!(TILE, 3);
735    tcvtrowps2phl(TILE as i8, row).as_m512h()
736}
737
738/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
739/// floating-point elements to packed half-precision (16-bit) floating-point elements. The resulting
740/// 16-bit elements are placed in the low 16-bits within each 32-bit element of the returned vector.
741#[inline]
742#[rustc_legacy_const_generics(0, 1)]
743#[target_feature(enable = "amx-avx512,avx10.2")]
744#[cfg_attr(
745    all(test, not(target_vendor = "apple")),
746    assert_instr(tcvtrowps2phl, TILE = 0, ROW = 0)
747)]
748#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
749pub unsafe fn _tile_cvtrowps2phli<const TILE: i32, const ROW: i32>() -> __m512h {
750    static_assert_uimm_bits!(TILE, 3);
751    static_assert_uimm_bits!(ROW, 6);
752    tcvtrowps2phli(TILE as i8, ROW as u32).as_m512h()
753}
754
755/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
756/// floating-point elements to packed half-precision (16-bit) floating-point elements. The resulting
757/// 16-bit elements are placed in the low 16-bits within each 32-bit element of the returned vector.
758/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
759#[inline]
760#[target_feature(enable = "amx-avx512,avx10.2")]
761#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tcvtrowps2phl))]
762#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
763pub unsafe fn __tile_cvtrowps2phl(src: __tile1024i, row: u32) -> __m512h {
764    tcvtrowps2phl_internal(src.rows, src.colsb, src.tile, row).as_m512h()
765}
766
767/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
768/// floating-point elements to packed BF16 (16-bit) floating-point elements. The resulting
769/// 16-bit elements are placed in the high 16-bits within each 32-bit element of the returned vector.
770#[inline]
771#[rustc_legacy_const_generics(0)]
772#[target_feature(enable = "amx-avx512,avx10.2")]
773#[cfg_attr(
774    all(test, not(target_vendor = "apple")),
775    assert_instr(tcvtrowps2bf16h, TILE = 0)
776)]
777#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
778pub unsafe fn _tile_cvtrowps2bf16h<const TILE: i32>(row: u32) -> __m512bh {
779    static_assert_uimm_bits!(TILE, 3);
780    tcvtrowps2bf16h(TILE as i8, row).as_m512bh()
781}
782
783/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
784/// floating-point elements to packed BF16 (16-bit) floating-point elements. The resulting
785/// 16-bit elements are placed in the high 16-bits within each 32-bit element of the returned vector.
786#[inline]
787#[rustc_legacy_const_generics(0, 1)]
788#[target_feature(enable = "amx-avx512,avx10.2")]
789#[cfg_attr(
790    all(test, not(target_vendor = "apple")),
791    assert_instr(tcvtrowps2bf16h, TILE = 0, ROW = 0)
792)]
793#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
794pub unsafe fn _tile_cvtrowps2bf16hi<const TILE: i32, const ROW: i32>() -> __m512bh {
795    static_assert_uimm_bits!(TILE, 3);
796    static_assert_uimm_bits!(ROW, 6);
797    tcvtrowps2bf16hi(TILE as i8, ROW as u32).as_m512bh()
798}
799
800/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
801/// floating-point elements to packed BF16 (16-bit) floating-point elements. The resulting
802/// 16-bit elements are placed in the high 16-bits within each 32-bit element of the returned vector.
803/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
804#[inline]
805#[target_feature(enable = "amx-avx512,avx10.2")]
806#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tcvtrowps2bf16h))]
807#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
808pub unsafe fn __tile_cvtrowps2bf16h(src: __tile1024i, row: u32) -> __m512bh {
809    tcvtrowps2bf16h_internal(src.rows, src.colsb, src.tile, row).as_m512bh()
810}
811
812/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
813/// floating-point elements to packed BF16 (16-bit) floating-point elements. The resulting
814/// 16-bit elements are placed in the low 16-bits within each 32-bit element of the returned vector.
815#[inline]
816#[rustc_legacy_const_generics(0)]
817#[target_feature(enable = "amx-avx512,avx10.2")]
818#[cfg_attr(
819    all(test, not(target_vendor = "apple")),
820    assert_instr(tcvtrowps2bf16l, TILE = 0)
821)]
822#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
823pub unsafe fn _tile_cvtrowps2bf16l<const TILE: i32>(row: u32) -> __m512bh {
824    static_assert_uimm_bits!(TILE, 3);
825    tcvtrowps2bf16l(TILE as i8, row).as_m512bh()
826}
827
828/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
829/// floating-point elements to packed BF16 (16-bit) floating-point elements. The resulting
830/// 16-bit elements are placed in the low 16-bits within each 32-bit element of the returned vector.
831#[inline]
832#[rustc_legacy_const_generics(0, 1)]
833#[target_feature(enable = "amx-avx512,avx10.2")]
834#[cfg_attr(
835    all(test, not(target_vendor = "apple")),
836    assert_instr(tcvtrowps2bf16l, TILE = 0, ROW = 0)
837)]
838#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
839pub unsafe fn _tile_cvtrowps2bf16li<const TILE: i32, const ROW: i32>() -> __m512bh {
840    static_assert_uimm_bits!(TILE, 3);
841    static_assert_uimm_bits!(ROW, 6);
842    tcvtrowps2bf16li(TILE as i8, ROW as u32).as_m512bh()
843}
844
845/// Moves a row from a tile register to a zmm register, converting the packed single-precision (32-bit)
846/// floating-point elements to packed BF16 (16-bit) floating-point elements. The resulting
847/// 16-bit elements are placed in the low 16-bits within each 32-bit element of the returned vector.
848/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
849#[inline]
850#[target_feature(enable = "amx-avx512,avx10.2")]
851#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tcvtrowps2bf16l))]
852#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
853pub unsafe fn __tile_cvtrowps2bf16l(src: __tile1024i, row: u32) -> __m512bh {
854    tcvtrowps2bf16l_internal(src.rows, src.colsb, src.tile, row).as_m512bh()
855}
856
857/// Moves one row of tile data into a zmm vector register
858#[inline]
859#[rustc_legacy_const_generics(0)]
860#[target_feature(enable = "amx-avx512,avx10.2")]
861#[cfg_attr(
862    all(test, not(target_vendor = "apple")),
863    assert_instr(tilemovrow, TILE = 0)
864)]
865#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
866pub unsafe fn _tile_movrow<const TILE: i32>(row: u32) -> __m512i {
867    static_assert_uimm_bits!(TILE, 3);
868    tilemovrow(TILE as i8, row).as_m512i()
869}
870
871/// Moves one row of tile data into a zmm vector register
872#[inline]
873#[rustc_legacy_const_generics(0, 1)]
874#[target_feature(enable = "amx-avx512,avx10.2")]
875#[cfg_attr(
876    all(test, not(target_vendor = "apple")),
877    assert_instr(tilemovrow, TILE = 0, ROW = 0)
878)]
879#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
880pub unsafe fn _tile_movrowi<const TILE: i32, const ROW: i32>() -> __m512i {
881    static_assert_uimm_bits!(TILE, 3);
882    static_assert_uimm_bits!(ROW, 6);
883    tilemovrowi(TILE as i8, ROW as u32).as_m512i()
884}
885
886/// Moves one row of tile data into a zmm vector register
887/// The shape of the tile is specified in the struct of [`__tile1024i`]. The register of the tile is allocated by the compiler.
888#[inline]
889#[target_feature(enable = "amx-avx512,avx10.2")]
890#[cfg_attr(all(test, not(target_vendor = "apple")), assert_instr(tilemovrow))]
891#[unstable(feature = "x86_amx_intrinsics", issue = "126622")]
892pub unsafe fn __tile_movrow(src: __tile1024i, row: u32) -> __m512i {
893    tilemovrow_internal(src.rows, src.colsb, src.tile, row).as_m512i()
894}
895
896#[allow(improper_ctypes)]
897unsafe extern "unadjusted" {
898    #[link_name = "llvm.x86.ldtilecfg"]
899    fn ldtilecfg(mem_addr: *const u8);
900    #[link_name = "llvm.x86.sttilecfg"]
901    fn sttilecfg(mem_addr: *mut u8);
902
903    #[link_name = "llvm.x86.tileloadd64"]
904    fn tileloadd64(dst: i8, base: *const u8, stride: u64);
905    #[link_name = "llvm.x86.tileloadd64.internal"]
906    fn tileloadd64_internal(rows: u16, colsb: u16, base: *const u8, stride: u64) -> Tile;
907
908    #[link_name = "llvm.x86.tileloaddt164"]
909    fn tileloaddt164(dst: i8, base: *const u8, stride: u64);
910    #[link_name = "llvm.x86.tileloaddt164.internal"]
911    fn tileloaddt164_internal(rows: u16, colsb: u16, base: *const u8, stride: u64) -> Tile;
912
913    #[link_name = "llvm.x86.tilerelease"]
914    fn tilerelease();
915
916    #[link_name = "llvm.x86.tilestored64"]
917    fn tilestored64(dst: i8, base: *mut u8, stride: u64);
918    #[link_name = "llvm.x86.tilestored64.internal"]
919    fn tilestored64_internal(rows: u16, colsb: u16, base: *mut u8, stride: u64, src: Tile);
920
921    #[link_name = "llvm.x86.tilezero"]
922    fn tilezero(dst: i8);
923    #[link_name = "llvm.x86.tilezero.internal"]
924    fn tilezero_internal(rows: u16, colsb: u16) -> Tile;
925
926    #[link_name = "llvm.x86.tdpbf16ps"]
927    fn tdpbf16ps(dst: i8, a: i8, b: i8);
928    #[link_name = "llvm.x86.tdpbf16ps.internal"]
929    fn tdpbf16ps_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
930
931    #[link_name = "llvm.x86.tdpbuud"]
932    fn tdpbuud(dst: i8, a: i8, b: i8);
933    #[link_name = "llvm.x86.tdpbuud.internal"]
934    fn tdpbuud_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
935
936    #[link_name = "llvm.x86.tdpbusd"]
937    fn tdpbusd(dst: i8, a: i8, b: i8);
938    #[link_name = "llvm.x86.tdpbusd.internal"]
939    fn tdpbusd_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
940
941    #[link_name = "llvm.x86.tdpbsud"]
942    fn tdpbsud(dst: i8, a: i8, b: i8);
943    #[link_name = "llvm.x86.tdpbsud.internal"]
944    fn tdpbsud_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
945
946    #[link_name = "llvm.x86.tdpbssd"]
947    fn tdpbssd(dst: i8, a: i8, b: i8);
948    #[link_name = "llvm.x86.tdpbssd.internal"]
949    fn tdpbssd_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
950
951    #[link_name = "llvm.x86.tdpfp16ps"]
952    fn tdpfp16ps(dst: i8, a: i8, b: i8);
953    #[link_name = "llvm.x86.tdpfp16ps.internal"]
954    fn tdpfp16ps_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
955
956    #[link_name = "llvm.x86.tcmmimfp16ps"]
957    fn tcmmimfp16ps(dst: i8, a: i8, b: i8);
958    #[link_name = "llvm.x86.tcmmimfp16ps.internal"]
959    fn tcmmimfp16ps_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
960
961    #[link_name = "llvm.x86.tcmmrlfp16ps"]
962    fn tcmmrlfp16ps(dst: i8, a: i8, b: i8);
963    #[link_name = "llvm.x86.tcmmrlfp16ps.internal"]
964    fn tcmmrlfp16ps_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
965
966    #[link_name = "llvm.x86.tdpbf8ps"]
967    fn tdpbf8ps(dst: i8, a: i8, b: i8);
968    #[link_name = "llvm.x86.tdpbf8ps.internal"]
969    fn tdpbf8ps_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
970
971    #[link_name = "llvm.x86.tdpbhf8ps"]
972    fn tdpbhf8ps(dst: i8, a: i8, b: i8);
973    #[link_name = "llvm.x86.tdpbhf8ps.internal"]
974    fn tdpbhf8ps_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
975
976    #[link_name = "llvm.x86.tdphbf8ps"]
977    fn tdphbf8ps(dst: i8, a: i8, b: i8);
978    #[link_name = "llvm.x86.tdphbf8ps.internal"]
979    fn tdphbf8ps_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
980
981    #[link_name = "llvm.x86.tdphf8ps"]
982    fn tdphf8ps(dst: i8, a: i8, b: i8);
983    #[link_name = "llvm.x86.tdphf8ps.internal"]
984    fn tdphf8ps_internal(m: u16, n: u16, k: u16, dst: Tile, a: Tile, b: Tile) -> Tile;
985
986    #[link_name = "llvm.x86.tileloaddrs64"]
987    fn tileloaddrs64(dst: i8, base: *const u8, stride: u64);
988    #[link_name = "llvm.x86.tileloaddrs64.internal"]
989    fn tileloaddrs64_internal(rows: u16, colsb: u16, base: *const u8, stride: u64) -> Tile;
990
991    #[link_name = "llvm.x86.tileloaddrst164"]
992    fn tileloaddrst164(dst: i8, base: *const u8, stride: u64);
993    #[link_name = "llvm.x86.tileloaddrst164.internal"]
994    fn tileloaddrst164_internal(rows: u16, colsb: u16, base: *const u8, stride: u64) -> Tile;
995
996    #[link_name = "llvm.x86.tcvtrowd2ps"]
997    fn tcvtrowd2ps(tile: i8, row: u32) -> f32x16;
998    #[link_name = "llvm.x86.tcvtrowd2psi"]
999    fn tcvtrowd2psi(tile: i8, row: u32) -> f32x16;
1000    #[link_name = "llvm.x86.tcvtrowd2ps.internal"]
1001    fn tcvtrowd2ps_internal(rows: u16, colsb: u16, src: Tile, row: u32) -> f32x16;
1002
1003    #[link_name = "llvm.x86.tcvtrowps2phh"]
1004    fn tcvtrowps2phh(tile: i8, row: u32) -> f16x32;
1005    #[link_name = "llvm.x86.tcvtrowps2phhi"]
1006    fn tcvtrowps2phhi(tile: i8, row: u32) -> f16x32;
1007    #[link_name = "llvm.x86.tcvtrowps2phh.internal"]
1008    fn tcvtrowps2phh_internal(rows: u16, colsb: u16, src: Tile, row: u32) -> f16x32;
1009
1010    #[link_name = "llvm.x86.tcvtrowps2phl"]
1011    fn tcvtrowps2phl(tile: i8, row: u32) -> f16x32;
1012    #[link_name = "llvm.x86.tcvtrowps2phli"]
1013    fn tcvtrowps2phli(tile: i8, row: u32) -> f16x32;
1014    #[link_name = "llvm.x86.tcvtrowps2phl.internal"]
1015    fn tcvtrowps2phl_internal(rows: u16, colsb: u16, src: Tile, row: u32) -> f16x32;
1016
1017    #[link_name = "llvm.x86.tcvtrowps2bf16h"]
1018    fn tcvtrowps2bf16h(tile: i8, row: u32) -> u16x32;
1019    #[link_name = "llvm.x86.tcvtrowps2bf16hi"]
1020    fn tcvtrowps2bf16hi(tile: i8, row: u32) -> u16x32;
1021    #[link_name = "llvm.x86.tcvtrowps2bf16h.internal"]
1022    fn tcvtrowps2bf16h_internal(rows: u16, colsb: u16, src: Tile, row: u32) -> u16x32;
1023
1024    #[link_name = "llvm.x86.tcvtrowps2bf16l"]
1025    fn tcvtrowps2bf16l(tile: i8, row: u32) -> u16x32;
1026    #[link_name = "llvm.x86.tcvtrowps2bf16li"]
1027    fn tcvtrowps2bf16li(tile: i8, row: u32) -> u16x32;
1028    #[link_name = "llvm.x86.tcvtrowps2bf16l.internal"]
1029    fn tcvtrowps2bf16l_internal(rows: u16, colsb: u16, src: Tile, row: u32) -> u16x32;
1030
1031    #[link_name = "llvm.x86.tilemovrow"]
1032    fn tilemovrow(tile: i8, row: u32) -> i32x16;
1033    #[link_name = "llvm.x86.tilemovrowi"]
1034    fn tilemovrowi(tile: i8, row: u32) -> i32x16;
1035    #[link_name = "llvm.x86.tilemovrow.internal"]
1036    fn tilemovrow_internal(rows: u16, colsb: u16, src: Tile, row: u32) -> i32x16;
1037}
1038
1039#[cfg(test)]
1040mod tests {
1041    use crate::core_arch::x86::_mm_cvtness_sbh;
1042    use crate::core_arch::x86_64::*;
1043    use core::array;
1044    use stdarch_test::simd_test;
1045    #[cfg(target_os = "linux")]
1046    use syscalls::{Sysno, syscall};
1047
1048    #[allow(non_camel_case_types)]
1049    #[repr(C, packed)]
1050    #[derive(Copy, Clone, Default, Debug, PartialEq)]
1051    struct __tilecfg {
1052        /// 0 `or` 1
1053        palette: u8,
1054        start_row: u8,
1055        /// reserved, must be zero
1056        reserved_a0: [u8; 14],
1057        /// number of bytes of one row in each tile
1058        colsb: [u16; 8],
1059        /// reserved, must be zero
1060        reserved_b0: [u16; 8],
1061        /// number of rows in each tile
1062        rows: [u8; 8],
1063        /// reserved, must be zero
1064        reserved_c0: [u8; 8],
1065    }
1066
1067    impl __tilecfg {
1068        fn new(palette: u8, start_row: u8, colsb: [u16; 8], rows: [u8; 8]) -> Self {
1069            Self {
1070                palette,
1071                start_row,
1072                reserved_a0: [0u8; 14],
1073                colsb,
1074                reserved_b0: [0u16; 8],
1075                rows,
1076                reserved_c0: [0u8; 8],
1077            }
1078        }
1079
1080        const fn as_ptr(&self) -> *const u8 {
1081            self as *const Self as *const u8
1082        }
1083
1084        fn as_mut_ptr(&mut self) -> *mut u8 {
1085            self as *mut Self as *mut u8
1086        }
1087    }
1088
1089    #[cfg(not(target_os = "linux"))]
1090    #[target_feature(enable = "amx-tile")]
1091    fn _init_amx() {}
1092
1093    #[cfg(target_os = "linux")]
1094    #[target_feature(enable = "amx-tile")]
1095    #[inline]
1096    fn _init_amx() {
1097        let mut ret: usize;
1098        let mut xfeatures: usize = 0;
1099        ret = unsafe {
1100            syscall!(Sysno::arch_prctl, 0x1022, &raw mut xfeatures)
1101                .expect("arch_prctl ARCH_GET_XCOMP_PERM syscall failed")
1102        };
1103        if ret != 0 {
1104            panic!("Failed to get XFEATURES");
1105        } else {
1106            match 0b11 & (xfeatures >> 17) {
1107                0 => panic!("AMX is not available"),
1108                1 => {
1109                    ret = unsafe {
1110                        syscall!(Sysno::arch_prctl, 0x1023, 18)
1111                            .expect("arch_prctl ARCH_REQ_XCOMP_PERM syscall failed")
1112                    };
1113                    if ret != 0 {
1114                        panic!("Failed to enable AMX");
1115                    }
1116                }
1117                3 => {}
1118                _ => unreachable!(),
1119            }
1120        }
1121    }
1122
1123    impl __tile1024i {
1124        #[inline]
1125        #[target_feature(enable = "amx-tile")]
1126        fn zeroed(rows: u16, colsb: u16) -> Self {
1127            Self {
1128                rows,
1129                colsb,
1130                tile: unsafe { super::tilezero_internal(rows, colsb) },
1131            }
1132        }
1133    }
1134
1135    #[simd_test(enable = "amx-tile")]
1136    fn test_tile_loadconfig() {
1137        unsafe {
1138            let config = __tilecfg::default();
1139            _tile_loadconfig(config.as_ptr());
1140            _tile_release();
1141        }
1142    }
1143
1144    #[simd_test(enable = "amx-tile")]
1145    fn test_tile_storeconfig() {
1146        unsafe {
1147            let config = __tilecfg::new(1, 0, [32; 8], [8; 8]);
1148            _tile_loadconfig(config.as_ptr());
1149            let mut _config = __tilecfg::default();
1150            _tile_storeconfig(_config.as_mut_ptr());
1151            _tile_release();
1152            assert_eq!(config, _config);
1153        }
1154    }
1155
1156    #[simd_test(enable = "amx-tile")]
1157    fn test_tile_zero() {
1158        unsafe {
1159            _init_amx();
1160            let mut config = __tilecfg::default();
1161            config.palette = 1;
1162            config.colsb[0] = 64;
1163            config.rows[0] = 16;
1164            _tile_loadconfig(config.as_ptr());
1165            _tile_zero::<0>();
1166            let mut out = [[1_i8; 64]; 16];
1167            _tile_stored::<0>(out.as_mut_ptr().cast(), 64);
1168            _tile_release();
1169            assert_eq!(out, [[0; 64]; 16]);
1170        }
1171    }
1172
1173    #[simd_test(enable = "amx-tile")]
1174    fn test__tile_zero() {
1175        unsafe {
1176            _init_amx();
1177
1178            let tile = __tile1024i::zeroed(16, 64);
1179
1180            let mut out = [[1_i8; 64]; 16];
1181            __tile_stored(out.as_mut_ptr().cast(), 64, tile);
1182
1183            assert_eq!(out, [[0; 64]; 16]);
1184        }
1185    }
1186
1187    #[simd_test(enable = "amx-tile")]
1188    fn test_tile_stored() {
1189        unsafe {
1190            _init_amx();
1191            let mut config = __tilecfg::default();
1192            config.palette = 1;
1193            config.colsb[0] = 64;
1194            config.rows[0] = 16;
1195            _tile_loadconfig(config.as_ptr());
1196            _tile_zero::<0>();
1197            let mut out = [[1_i8; 64]; 16];
1198            _tile_stored::<0>(out.as_mut_ptr().cast(), 64);
1199            _tile_release();
1200            assert_eq!(out, [[0; 64]; 16]);
1201        }
1202    }
1203
1204    #[simd_test(enable = "amx-tile")]
1205    fn test__tile_stored() {
1206        unsafe {
1207            _init_amx();
1208
1209            let tile = __tile1024i::zeroed(16, 64);
1210
1211            let mut out = [[1_i8; 64]; 16];
1212            __tile_stored(out.as_mut_ptr().cast(), 64, tile);
1213
1214            assert_eq!(out, [[0; 64]; 16]);
1215        }
1216    }
1217
1218    #[simd_test(enable = "amx-tile")]
1219    fn test_tile_loadd() {
1220        unsafe {
1221            _init_amx();
1222            let mut config = __tilecfg::default();
1223            config.palette = 1;
1224            config.colsb[0] = 64;
1225            config.rows[0] = 16;
1226            _tile_loadconfig(config.as_ptr());
1227            _tile_zero::<0>();
1228            let mat = [1_i8; 1024];
1229            _tile_loadd::<0>(mat.as_ptr().cast(), 64);
1230            let mut out = [[0_i8; 64]; 16];
1231            _tile_stored::<0>(out.as_mut_ptr().cast(), 64);
1232            _tile_release();
1233            assert_eq!(out, [[1; 64]; 16]);
1234        }
1235    }
1236
1237    #[simd_test(enable = "amx-tile")]
1238    fn test__tile_loadd() {
1239        unsafe {
1240            _init_amx();
1241
1242            let mut tile = __tile1024i::zeroed(16, 64);
1243
1244            let mat = [1_i8; 1024];
1245            __tile_loadd(&mut tile, mat.as_ptr().cast(), 64);
1246            let mut out = [[0_i8; 64]; 16];
1247            __tile_stored(out.as_mut_ptr().cast(), 64, tile);
1248
1249            assert_eq!(out, [[1; 64]; 16]);
1250        }
1251    }
1252
1253    #[simd_test(enable = "amx-tile")]
1254    fn test_tile_stream_loadd() {
1255        unsafe {
1256            _init_amx();
1257            let mut config = __tilecfg::default();
1258            config.palette = 1;
1259            config.colsb[0] = 64;
1260            config.rows[0] = 16;
1261            _tile_loadconfig(config.as_ptr());
1262            _tile_zero::<0>();
1263            let mat = [1_i8; 1024];
1264            _tile_stream_loadd::<0>(mat.as_ptr().cast(), 64);
1265            let mut out = [[0_i8; 64]; 16];
1266            _tile_stored::<0>(out.as_mut_ptr().cast(), 64);
1267            _tile_release();
1268            assert_eq!(out, [[1; 64]; 16]);
1269        }
1270    }
1271
1272    #[simd_test(enable = "amx-tile")]
1273    fn test__tile_stream_loadd() {
1274        unsafe {
1275            _init_amx();
1276
1277            let mut tile = __tile1024i::zeroed(16, 64);
1278
1279            let mat = [1_i8; 1024];
1280            __tile_stream_loadd(&mut tile, mat.as_ptr().cast(), 64);
1281            let mut out = [[0_i8; 64]; 16];
1282            __tile_stored(out.as_mut_ptr().cast(), 64, tile);
1283
1284            assert_eq!(out, [[1; 64]; 16]);
1285        }
1286    }
1287
1288    #[simd_test(enable = "amx-tile")]
1289    fn test_tile_release() {
1290        unsafe {
1291            _tile_release();
1292        }
1293    }
1294
1295    const BF16_1: u16 = 0x3f80;
1296    const BF16_2: u16 = 0x4000;
1297
1298    #[simd_test(enable = "amx-bf16")]
1299    fn test_tile_dpbf16ps() {
1300        unsafe {
1301            _init_amx();
1302            let ones = [BF16_1; 512];
1303            let twos = [BF16_2; 512];
1304            let mut res = [[0f32; 16]; 16];
1305            let mut config = __tilecfg::default();
1306            config.palette = 1;
1307            (0..=2).for_each(|i| {
1308                config.colsb[i] = 64;
1309                config.rows[i] = 16;
1310            });
1311            _tile_loadconfig(config.as_ptr());
1312            _tile_zero::<0>();
1313            _tile_loadd::<1>(ones.as_ptr().cast(), 64);
1314            _tile_loadd::<2>(twos.as_ptr().cast(), 64);
1315            _tile_dpbf16ps::<0, 1, 2>();
1316            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1317            _tile_release();
1318            assert_eq!(res, [[64f32; 16]; 16]);
1319        }
1320    }
1321
1322    #[simd_test(enable = "amx-bf16")]
1323    fn test__tile_dpbf16ps() {
1324        unsafe {
1325            _init_amx();
1326            let ones = [BF16_1; 512];
1327            let twos = [BF16_2; 512];
1328            let mut res = [[0f32; 16]; 16];
1329
1330            let mut a = __tile1024i::zeroed(16, 64);
1331            let mut b = __tile1024i::zeroed(16, 64);
1332            let mut c = __tile1024i::zeroed(16, 64);
1333
1334            __tile_loadd(&mut a, ones.as_ptr().cast(), 64);
1335            __tile_loadd(&mut b, twos.as_ptr().cast(), 64);
1336            __tile_dpbf16ps(&mut c, a, b);
1337            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1338
1339            assert_eq!(res, [[64f32; 16]; 16]);
1340        }
1341    }
1342
1343    #[simd_test(enable = "amx-int8")]
1344    fn test_tile_dpbssd() {
1345        unsafe {
1346            _init_amx();
1347            let ones = [-1_i8; 1024];
1348            let twos = [-2_i8; 1024];
1349            let mut res = [[0_i32; 16]; 16];
1350            let mut config = __tilecfg::default();
1351            config.palette = 1;
1352            (0..=2).for_each(|i| {
1353                config.colsb[i] = 64;
1354                config.rows[i] = 16;
1355            });
1356            _tile_loadconfig(config.as_ptr());
1357            _tile_zero::<0>();
1358            _tile_loadd::<1>(ones.as_ptr().cast(), 64);
1359            _tile_loadd::<2>(twos.as_ptr().cast(), 64);
1360            _tile_dpbssd::<0, 1, 2>();
1361            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1362            _tile_release();
1363            assert_eq!(res, [[128_i32; 16]; 16]);
1364        }
1365    }
1366
1367    #[simd_test(enable = "amx-int8")]
1368    fn test__tile_dpbssd() {
1369        unsafe {
1370            _init_amx();
1371            let ones = [-1_i8; 1024];
1372            let twos = [-2_i8; 1024];
1373            let mut res = [[0_i32; 16]; 16];
1374
1375            let mut a = __tile1024i::zeroed(16, 64);
1376            let mut b = __tile1024i::zeroed(16, 64);
1377            let mut c = __tile1024i::zeroed(16, 64);
1378
1379            __tile_loadd(&mut a, ones.as_ptr().cast(), 64);
1380            __tile_loadd(&mut b, twos.as_ptr().cast(), 64);
1381            __tile_dpbssd(&mut c, a, b);
1382            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1383
1384            assert_eq!(res, [[128_i32; 16]; 16]);
1385        }
1386    }
1387
1388    #[simd_test(enable = "amx-int8")]
1389    fn test_tile_dpbsud() {
1390        unsafe {
1391            _init_amx();
1392            let ones = [-1_i8; 1024];
1393            let twos = [2_u8; 1024];
1394            let mut res = [[0_i32; 16]; 16];
1395            let mut config = __tilecfg::default();
1396            config.palette = 1;
1397            (0..=2).for_each(|i| {
1398                config.colsb[i] = 64;
1399                config.rows[i] = 16;
1400            });
1401            _tile_loadconfig(config.as_ptr());
1402            _tile_zero::<0>();
1403            _tile_loadd::<1>(ones.as_ptr().cast(), 64);
1404            _tile_loadd::<2>(twos.as_ptr(), 64);
1405            _tile_dpbsud::<0, 1, 2>();
1406            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1407            _tile_release();
1408            assert_eq!(res, [[-128_i32; 16]; 16]);
1409        }
1410    }
1411
1412    #[simd_test(enable = "amx-int8")]
1413    fn test__tile_dpbsud() {
1414        unsafe {
1415            _init_amx();
1416            let ones = [-1_i8; 1024];
1417            let twos = [2_u8; 1024];
1418            let mut res = [[0_i32; 16]; 16];
1419
1420            let mut a = __tile1024i::zeroed(16, 64);
1421            let mut b = __tile1024i::zeroed(16, 64);
1422            let mut c = __tile1024i::zeroed(16, 64);
1423
1424            __tile_loadd(&mut a, ones.as_ptr().cast(), 64);
1425            __tile_loadd(&mut b, twos.as_ptr(), 64);
1426            __tile_dpbsud(&mut c, a, b);
1427            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1428
1429            assert_eq!(res, [[-128_i32; 16]; 16]);
1430        }
1431    }
1432
1433    #[simd_test(enable = "amx-int8")]
1434    fn test_tile_dpbusd() {
1435        unsafe {
1436            _init_amx();
1437            let ones = [1_u8; 1024];
1438            let twos = [-2_i8; 1024];
1439            let mut res = [[0_i32; 16]; 16];
1440            let mut config = __tilecfg::default();
1441            config.palette = 1;
1442            (0..=2).for_each(|i| {
1443                config.colsb[i] = 64;
1444                config.rows[i] = 16;
1445            });
1446            _tile_loadconfig(config.as_ptr());
1447            _tile_zero::<0>();
1448            _tile_loadd::<1>(ones.as_ptr(), 64);
1449            _tile_loadd::<2>(twos.as_ptr().cast(), 64);
1450            _tile_dpbusd::<0, 1, 2>();
1451            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1452            _tile_release();
1453            assert_eq!(res, [[-128_i32; 16]; 16]);
1454        }
1455    }
1456
1457    #[simd_test(enable = "amx-int8")]
1458    fn test__tile_dpbusd() {
1459        unsafe {
1460            _init_amx();
1461            let ones = [1_u8; 1024];
1462            let twos = [-2_i8; 1024];
1463            let mut res = [[0_i32; 16]; 16];
1464
1465            let mut a = __tile1024i::zeroed(16, 64);
1466            let mut b = __tile1024i::zeroed(16, 64);
1467            let mut c = __tile1024i::zeroed(16, 64);
1468
1469            __tile_loadd(&mut a, ones.as_ptr(), 64);
1470            __tile_loadd(&mut b, twos.as_ptr().cast(), 64);
1471            __tile_dpbusd(&mut c, a, b);
1472            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1473
1474            assert_eq!(res, [[-128_i32; 16]; 16]);
1475        }
1476    }
1477
1478    #[simd_test(enable = "amx-int8")]
1479    fn test_tile_dpbuud() {
1480        unsafe {
1481            _init_amx();
1482            let ones = [1_u8; 1024];
1483            let twos = [2_u8; 1024];
1484            let mut res = [[0_i32; 16]; 16];
1485            let mut config = __tilecfg::default();
1486            config.palette = 1;
1487            (0..=2).for_each(|i| {
1488                config.colsb[i] = 64;
1489                config.rows[i] = 16;
1490            });
1491            _tile_loadconfig(config.as_ptr());
1492            _tile_zero::<0>();
1493            _tile_loadd::<1>(ones.as_ptr(), 64);
1494            _tile_loadd::<2>(twos.as_ptr(), 64);
1495            _tile_dpbuud::<0, 1, 2>();
1496            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1497            _tile_release();
1498            assert_eq!(res, [[128_i32; 16]; 16]);
1499        }
1500    }
1501
1502    #[simd_test(enable = "amx-int8")]
1503    fn test__tile_dpbuud() {
1504        unsafe {
1505            _init_amx();
1506            let ones = [1_u8; 1024];
1507            let twos = [2_u8; 1024];
1508            let mut res = [[0_i32; 16]; 16];
1509
1510            let mut a = __tile1024i::zeroed(16, 64);
1511            let mut b = __tile1024i::zeroed(16, 64);
1512            let mut c = __tile1024i::zeroed(16, 64);
1513
1514            __tile_loadd(&mut a, ones.as_ptr(), 64);
1515            __tile_loadd(&mut b, twos.as_ptr(), 64);
1516            __tile_dpbuud(&mut c, a, b);
1517            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1518
1519            assert_eq!(res, [[128_i32; 16]; 16]);
1520        }
1521    }
1522
1523    #[simd_test(enable = "amx-fp16")]
1524    fn test_tile_dpfp16ps() {
1525        unsafe {
1526            _init_amx();
1527            let ones = [1f16; 512];
1528            let twos = [2f16; 512];
1529            let mut res = [[0f32; 16]; 16];
1530            let mut config = __tilecfg::default();
1531            config.palette = 1;
1532            (0..=2).for_each(|i| {
1533                config.colsb[i] = 64;
1534                config.rows[i] = 16;
1535            });
1536            _tile_loadconfig(config.as_ptr());
1537            _tile_zero::<0>();
1538            _tile_loadd::<1>(ones.as_ptr().cast(), 64);
1539            _tile_loadd::<2>(twos.as_ptr().cast(), 64);
1540            _tile_dpfp16ps::<0, 1, 2>();
1541            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1542            _tile_release();
1543            assert_eq!(res, [[64f32; 16]; 16]);
1544        }
1545    }
1546
1547    #[simd_test(enable = "amx-fp16")]
1548    fn test__tile_dpfp16ps() {
1549        unsafe {
1550            _init_amx();
1551            let ones = [1f16; 512];
1552            let twos = [2f16; 512];
1553            let mut res = [[0f32; 16]; 16];
1554
1555            let mut a = __tile1024i::zeroed(16, 64);
1556            let mut b = __tile1024i::zeroed(16, 64);
1557            let mut c = __tile1024i::zeroed(16, 64);
1558
1559            __tile_loadd(&mut a, ones.as_ptr().cast(), 64);
1560            __tile_loadd(&mut b, twos.as_ptr().cast(), 64);
1561            __tile_dpfp16ps(&mut c, a, b);
1562            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1563
1564            assert_eq!(res, [[64f32; 16]; 16]);
1565        }
1566    }
1567
1568    #[simd_test(enable = "amx-complex")]
1569    fn test_tile_cmmimfp16ps() {
1570        unsafe {
1571            _init_amx();
1572            let ones = [1f16; 512];
1573            let twos = [2f16; 512];
1574            let mut res = [[0f32; 16]; 16];
1575            let mut config = __tilecfg::default();
1576            config.palette = 1;
1577            (0..=2).for_each(|i| {
1578                config.colsb[i] = 64;
1579                config.rows[i] = 16;
1580            });
1581            _tile_loadconfig(config.as_ptr());
1582            _tile_zero::<0>();
1583            _tile_loadd::<1>(ones.as_ptr().cast(), 64);
1584            _tile_loadd::<2>(twos.as_ptr().cast(), 64);
1585            _tile_cmmimfp16ps::<0, 1, 2>();
1586            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1587            _tile_release();
1588            assert_eq!(res, [[64f32; 16]; 16]);
1589        }
1590    }
1591
1592    #[simd_test(enable = "amx-complex")]
1593    fn test__tile_cmmimfp16ps() {
1594        unsafe {
1595            _init_amx();
1596            let ones = [1f16; 512];
1597            let twos = [2f16; 512];
1598            let mut res = [[0f32; 16]; 16];
1599
1600            let mut a = __tile1024i::zeroed(16, 64);
1601            let mut b = __tile1024i::zeroed(16, 64);
1602            let mut c = __tile1024i::zeroed(16, 64);
1603
1604            __tile_loadd(&mut a, ones.as_ptr().cast(), 64);
1605            __tile_loadd(&mut b, twos.as_ptr().cast(), 64);
1606            __tile_cmmimfp16ps(&mut c, a, b);
1607            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1608
1609            assert_eq!(res, [[64f32; 16]; 16]);
1610        }
1611    }
1612
1613    #[simd_test(enable = "amx-complex")]
1614    fn test_tile_cmmrlfp16ps() {
1615        unsafe {
1616            _init_amx();
1617            let ones = [1f16; 512];
1618            let twos = [2f16; 512];
1619            let mut res = [[0f32; 16]; 16];
1620            let mut config = __tilecfg::default();
1621            config.palette = 1;
1622            (0..=2).for_each(|i| {
1623                config.colsb[i] = 64;
1624                config.rows[i] = 16;
1625            });
1626            _tile_loadconfig(config.as_ptr());
1627            _tile_zero::<0>();
1628            _tile_loadd::<1>(ones.as_ptr().cast(), 64);
1629            _tile_loadd::<2>(twos.as_ptr().cast(), 64);
1630            _tile_cmmrlfp16ps::<0, 1, 2>();
1631            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1632            _tile_release();
1633            assert_eq!(res, [[0f32; 16]; 16]);
1634        }
1635    }
1636
1637    #[simd_test(enable = "amx-complex")]
1638    fn test__tile_cmmrlfp16ps() {
1639        unsafe {
1640            _init_amx();
1641            let ones = [1f16; 512];
1642            let twos = [2f16; 512];
1643            let mut res = [[0f32; 16]; 16];
1644
1645            let mut a = __tile1024i::zeroed(16, 64);
1646            let mut b = __tile1024i::zeroed(16, 64);
1647            let mut c = __tile1024i::zeroed(16, 64);
1648
1649            __tile_loadd(&mut a, ones.as_ptr().cast(), 64);
1650            __tile_loadd(&mut b, twos.as_ptr().cast(), 64);
1651            __tile_cmmrlfp16ps(&mut c, a, b);
1652            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1653
1654            assert_eq!(res, [[0f32; 16]; 16]);
1655        }
1656    }
1657
1658    const BF8_ONE: u8 = 0x3c;
1659    const BF8_TWO: u8 = 0x40;
1660    const HF8_ONE: u8 = 0x38;
1661    const HF8_TWO: u8 = 0x40;
1662
1663    #[simd_test(enable = "amx-fp8")]
1664    fn test_tile_dpbf8ps() {
1665        unsafe {
1666            _init_amx();
1667            let ones = [BF8_ONE; 1024];
1668            let twos = [BF8_TWO; 1024];
1669            let mut res = [[0.0_f32; 16]; 16];
1670            let mut config = __tilecfg::default();
1671            config.palette = 1;
1672            (0..=2).for_each(|i| {
1673                config.colsb[i] = 64;
1674                config.rows[i] = 16;
1675            });
1676            _tile_loadconfig(config.as_ptr());
1677            _tile_zero::<0>();
1678            _tile_loadd::<1>(ones.as_ptr(), 64);
1679            _tile_loadd::<2>(twos.as_ptr(), 64);
1680            _tile_dpbf8ps::<0, 1, 2>();
1681            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1682            _tile_release();
1683            assert_eq!(res, [[128.0_f32; 16]; 16]);
1684        }
1685    }
1686
1687    #[simd_test(enable = "amx-fp8")]
1688    fn test__tile_dpbf8ps() {
1689        unsafe {
1690            _init_amx();
1691            let ones = [BF8_ONE; 1024];
1692            let twos = [BF8_TWO; 1024];
1693            let mut res = [[0.0_f32; 16]; 16];
1694
1695            let mut a = __tile1024i::zeroed(16, 64);
1696            let mut b = __tile1024i::zeroed(16, 64);
1697            let mut c = __tile1024i::zeroed(16, 64);
1698
1699            __tile_loadd(&mut a, ones.as_ptr(), 64);
1700            __tile_loadd(&mut b, twos.as_ptr(), 64);
1701            __tile_dpbf8ps(&mut c, a, b);
1702            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1703
1704            assert_eq!(res, [[128.0_f32; 16]; 16]);
1705        }
1706    }
1707
1708    #[simd_test(enable = "amx-fp8")]
1709    fn test_tile_dpbhf8ps() {
1710        unsafe {
1711            _init_amx();
1712            let ones = [BF8_ONE; 1024];
1713            let twos = [HF8_TWO; 1024];
1714            let mut res = [[0.0_f32; 16]; 16];
1715            let mut config = __tilecfg::default();
1716            config.palette = 1;
1717            (0..=2).for_each(|i| {
1718                config.colsb[i] = 64;
1719                config.rows[i] = 16;
1720            });
1721            _tile_loadconfig(config.as_ptr());
1722            _tile_zero::<0>();
1723            _tile_loadd::<1>(ones.as_ptr(), 64);
1724            _tile_loadd::<2>(twos.as_ptr(), 64);
1725            _tile_dpbhf8ps::<0, 1, 2>();
1726            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1727            _tile_release();
1728            assert_eq!(res, [[128.0_f32; 16]; 16]);
1729        }
1730    }
1731
1732    #[simd_test(enable = "amx-fp8")]
1733    fn test__tile_dpbhf8ps() {
1734        unsafe {
1735            _init_amx();
1736            let ones = [BF8_ONE; 1024];
1737            let twos = [HF8_TWO; 1024];
1738            let mut res = [[0.0_f32; 16]; 16];
1739
1740            let mut a = __tile1024i::zeroed(16, 64);
1741            let mut b = __tile1024i::zeroed(16, 64);
1742            let mut c = __tile1024i::zeroed(16, 64);
1743
1744            __tile_loadd(&mut a, ones.as_ptr(), 64);
1745            __tile_loadd(&mut b, twos.as_ptr(), 64);
1746            __tile_dpbhf8ps(&mut c, a, b);
1747            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1748
1749            assert_eq!(res, [[128.0_f32; 16]; 16]);
1750        }
1751    }
1752
1753    #[simd_test(enable = "amx-fp8")]
1754    fn test_tile_dphbf8ps() {
1755        unsafe {
1756            _init_amx();
1757            let ones = [HF8_ONE; 1024];
1758            let twos = [BF8_TWO; 1024];
1759            let mut res = [[0.0_f32; 16]; 16];
1760            let mut config = __tilecfg::default();
1761            config.palette = 1;
1762            (0..=2).for_each(|i| {
1763                config.colsb[i] = 64;
1764                config.rows[i] = 16;
1765            });
1766            _tile_loadconfig(config.as_ptr());
1767            _tile_zero::<0>();
1768            _tile_loadd::<1>(ones.as_ptr(), 64);
1769            _tile_loadd::<2>(twos.as_ptr(), 64);
1770            _tile_dphbf8ps::<0, 1, 2>();
1771            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1772            _tile_release();
1773            assert_eq!(res, [[128.0_f32; 16]; 16]);
1774        }
1775    }
1776
1777    #[simd_test(enable = "amx-fp8")]
1778    fn test__tile_dphbf8ps() {
1779        unsafe {
1780            _init_amx();
1781            let ones = [HF8_ONE; 1024];
1782            let twos = [BF8_TWO; 1024];
1783            let mut res = [[0.0_f32; 16]; 16];
1784
1785            let mut a = __tile1024i::zeroed(16, 64);
1786            let mut b = __tile1024i::zeroed(16, 64);
1787            let mut c = __tile1024i::zeroed(16, 64);
1788
1789            __tile_loadd(&mut a, ones.as_ptr(), 64);
1790            __tile_loadd(&mut b, twos.as_ptr(), 64);
1791            __tile_dphbf8ps(&mut c, a, b);
1792            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1793
1794            assert_eq!(res, [[128.0_f32; 16]; 16]);
1795        }
1796    }
1797
1798    #[simd_test(enable = "amx-fp8")]
1799    fn test_tile_dphf8ps() {
1800        unsafe {
1801            _init_amx();
1802            let ones = [HF8_ONE; 1024];
1803            let twos = [HF8_TWO; 1024];
1804            let mut res = [[0.0_f32; 16]; 16];
1805            let mut config = __tilecfg::default();
1806            config.palette = 1;
1807            (0..=2).for_each(|i| {
1808                config.colsb[i] = 64;
1809                config.rows[i] = 16;
1810            });
1811            _tile_loadconfig(config.as_ptr());
1812            _tile_zero::<0>();
1813            _tile_loadd::<1>(ones.as_ptr(), 64);
1814            _tile_loadd::<2>(twos.as_ptr(), 64);
1815            _tile_dphf8ps::<0, 1, 2>();
1816            _tile_stored::<0>(res.as_mut_ptr().cast(), 64);
1817            _tile_release();
1818            assert_eq!(res, [[128.0_f32; 16]; 16]);
1819        }
1820    }
1821
1822    #[simd_test(enable = "amx-fp8")]
1823    fn test__tile_dphf8ps() {
1824        unsafe {
1825            _init_amx();
1826            let ones = [HF8_ONE; 1024];
1827            let twos = [HF8_TWO; 1024];
1828            let mut res = [[0.0_f32; 16]; 16];
1829
1830            let mut a = __tile1024i::zeroed(16, 64);
1831            let mut b = __tile1024i::zeroed(16, 64);
1832            let mut c = __tile1024i::zeroed(16, 64);
1833
1834            __tile_loadd(&mut a, ones.as_ptr(), 64);
1835            __tile_loadd(&mut b, twos.as_ptr(), 64);
1836            __tile_dphf8ps(&mut c, a, b);
1837            __tile_stored(res.as_mut_ptr().cast(), 64, c);
1838
1839            assert_eq!(res, [[128.0_f32; 16]; 16]);
1840        }
1841    }
1842
1843    #[simd_test(enable = "amx-movrs")]
1844    fn test_tile_loaddrs() {
1845        unsafe {
1846            _init_amx();
1847            let mut config = __tilecfg::default();
1848            config.palette = 1;
1849            config.colsb[0] = 64;
1850            config.rows[0] = 16;
1851            _tile_loadconfig(config.as_ptr());
1852            _tile_zero::<0>();
1853            let mat = [1_i8; 1024];
1854            _tile_loaddrs::<0>(mat.as_ptr().cast(), 64);
1855            let mut out = [[0_i8; 64]; 16];
1856            _tile_stored::<0>(out.as_mut_ptr().cast(), 64);
1857            _tile_release();
1858            assert_eq!(out, [[1; 64]; 16]);
1859        }
1860    }
1861
1862    #[simd_test(enable = "amx-movrs")]
1863    fn test__tile_loaddrs() {
1864        unsafe {
1865            _init_amx();
1866
1867            let mut tile = __tile1024i::zeroed(16, 64);
1868
1869            let mat = [1_i8; 1024];
1870            __tile_loaddrs(&mut tile, mat.as_ptr().cast(), 64);
1871            let mut out = [[0_i8; 64]; 16];
1872            __tile_stored(out.as_mut_ptr().cast(), 64, tile);
1873
1874            assert_eq!(out, [[1; 64]; 16]);
1875        }
1876    }
1877
1878    #[simd_test(enable = "amx-movrs")]
1879    fn test_tile_stream_loaddrs() {
1880        unsafe {
1881            _init_amx();
1882            let mut config = __tilecfg::default();
1883            config.palette = 1;
1884            config.colsb[0] = 64;
1885            config.rows[0] = 16;
1886            _tile_loadconfig(config.as_ptr());
1887            _tile_zero::<0>();
1888            let mat = [1_i8; 1024];
1889            _tile_stream_loaddrs::<0>(mat.as_ptr().cast(), 64);
1890            let mut out = [[0_i8; 64]; 16];
1891            _tile_stored::<0>(out.as_mut_ptr().cast(), 64);
1892            _tile_release();
1893            assert_eq!(out, [[1; 64]; 16]);
1894        }
1895    }
1896
1897    #[simd_test(enable = "amx-movrs")]
1898    fn test__tile_stream_loaddrs() {
1899        unsafe {
1900            _init_amx();
1901
1902            let mut tile = __tile1024i::zeroed(16, 64);
1903
1904            let mat = [1_i8; 1024];
1905            __tile_stream_loaddrs(&mut tile, mat.as_ptr().cast(), 64);
1906            let mut out = [[0_i8; 64]; 16];
1907            __tile_stored(out.as_mut_ptr().cast(), 64, tile);
1908
1909            assert_eq!(out, [[1; 64]; 16]);
1910        }
1911    }
1912
1913    #[simd_test(enable = "amx-avx512,avx10.2")]
1914    fn test_tile_movrow() {
1915        unsafe {
1916            _init_amx();
1917            let array: [[u8; 64]; 16] = array::from_fn(|i| [i as _; _]);
1918
1919            let mut config = __tilecfg::default();
1920            config.palette = 1;
1921            config.colsb[0] = 64;
1922            config.rows[0] = 16;
1923            _tile_loadconfig(config.as_ptr());
1924            _tile_loadd::<0>(array.as_ptr().cast(), 64);
1925            for i in 0..16 {
1926                let row = _tile_movrow::<0>(i);
1927                assert_eq!(*row.as_u8x64().as_array(), [i as _; _]);
1928            }
1929        }
1930    }
1931
1932    macro_rules! wrap_imm4 {
1933        ($name:ident :: <$TILE:literal>, $row:expr) => {
1934            match $row {
1935                0 => $name::<$TILE, 0>(),
1936                1 => $name::<$TILE, 1>(),
1937                2 => $name::<$TILE, 2>(),
1938                3 => $name::<$TILE, 3>(),
1939                4 => $name::<$TILE, 4>(),
1940                5 => $name::<$TILE, 5>(),
1941                6 => $name::<$TILE, 6>(),
1942                7 => $name::<$TILE, 7>(),
1943                8 => $name::<$TILE, 8>(),
1944                9 => $name::<$TILE, 9>(),
1945                10 => $name::<$TILE, 10>(),
1946                11 => $name::<$TILE, 11>(),
1947                12 => $name::<$TILE, 12>(),
1948                13 => $name::<$TILE, 13>(),
1949                14 => $name::<$TILE, 14>(),
1950                15 => $name::<$TILE, 15>(),
1951                _ => panic!("row index out of range"),
1952            }
1953        };
1954    }
1955
1956    #[simd_test(enable = "amx-avx512,avx10.2")]
1957    fn test_tile_movrowi() {
1958        unsafe {
1959            _init_amx();
1960            let array: [[u8; 64]; 16] = array::from_fn(|i| [i as _; _]);
1961
1962            let mut config = __tilecfg::default();
1963            config.palette = 1;
1964            config.colsb[0] = 64;
1965            config.rows[0] = 16;
1966            _tile_loadconfig(config.as_ptr());
1967            _tile_loadd::<0>(array.as_ptr().cast(), 64);
1968
1969            for i in 0..16 {
1970                let row = wrap_imm4!(_tile_movrowi::<0>, i);
1971                assert_eq!(*row.as_u8x64().as_array(), [i as _; _]);
1972            }
1973        }
1974    }
1975
1976    #[simd_test(enable = "amx-avx512,avx10.2")]
1977    fn test__tile_movrow() {
1978        unsafe {
1979            _init_amx();
1980            let array: [[u8; 64]; 16] = array::from_fn(|i| [i as _; _]);
1981
1982            let mut tile = __tile1024i::zeroed(16, 64);
1983            __tile_loadd(&mut tile, array.as_ptr().cast(), 64);
1984
1985            for i in 0..16 {
1986                let row = __tile_movrow(tile, i);
1987                assert_eq!(*row.as_u8x64().as_array(), [i as _; _]);
1988            }
1989        }
1990    }
1991
1992    #[simd_test(enable = "amx-avx512,avx10.2")]
1993    fn test_tile_cvtrowd2ps() {
1994        unsafe {
1995            _init_amx();
1996            let array: [[u32; 16]; 16] = array::from_fn(|i| [i as _; _]);
1997
1998            let mut config = __tilecfg::default();
1999            config.palette = 1;
2000            config.colsb[0] = 64;
2001            config.rows[0] = 16;
2002            _tile_loadconfig(config.as_ptr());
2003            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2004            for i in 0..16 {
2005                let row = _tile_cvtrowd2ps::<0>(i);
2006                assert_eq!(*row.as_f32x16().as_array(), [i as _; _]);
2007            }
2008        }
2009    }
2010
2011    #[simd_test(enable = "amx-avx512,avx10.2")]
2012    fn test_tile_cvtrowd2psi() {
2013        unsafe {
2014            _init_amx();
2015            let array: [[u32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2016
2017            let mut config = __tilecfg::default();
2018            config.palette = 1;
2019            config.colsb[0] = 64;
2020            config.rows[0] = 16;
2021            _tile_loadconfig(config.as_ptr());
2022            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2023
2024            for i in 0..16 {
2025                let row = wrap_imm4!(_tile_cvtrowd2psi::<0>, i);
2026                assert_eq!(*row.as_f32x16().as_array(), [i as _; _]);
2027            }
2028        }
2029    }
2030
2031    #[simd_test(enable = "amx-avx512,avx10.2")]
2032    fn test__tile_cvtrowd2ps() {
2033        unsafe {
2034            _init_amx();
2035            let array: [[u32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2036
2037            let mut tile = __tile1024i::zeroed(16, 64);
2038            __tile_loadd(&mut tile, array.as_ptr().cast(), 64);
2039
2040            for i in 0..16 {
2041                let row = __tile_cvtrowd2ps(tile, i);
2042                assert_eq!(*row.as_f32x16().as_array(), [i as _; _]);
2043            }
2044        }
2045    }
2046
2047    #[simd_test(enable = "amx-avx512,avx10.2")]
2048    fn test_tile_cvtrowps2phh() {
2049        unsafe {
2050            _init_amx();
2051            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2052
2053            let mut config = __tilecfg::default();
2054            config.palette = 1;
2055            config.colsb[0] = 64;
2056            config.rows[0] = 16;
2057            _tile_loadconfig(config.as_ptr());
2058            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2059            for i in 0..16 {
2060                let row = _tile_cvtrowps2phh::<0>(i);
2061                assert_eq!(
2062                    *row.as_f16x32().as_array(),
2063                    array::from_fn(|j| if j & 1 == 0 { 0.0 } else { i as _ })
2064                );
2065            }
2066        }
2067    }
2068
2069    #[simd_test(enable = "amx-avx512,avx10.2")]
2070    fn test_tile_cvtrowps2phhi() {
2071        unsafe {
2072            _init_amx();
2073            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2074
2075            let mut config = __tilecfg::default();
2076            config.palette = 1;
2077            config.colsb[0] = 64;
2078            config.rows[0] = 16;
2079            _tile_loadconfig(config.as_ptr());
2080            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2081            for i in 0..16 {
2082                let row = wrap_imm4!(_tile_cvtrowps2phhi::<0>, i);
2083                assert_eq!(
2084                    *row.as_f16x32().as_array(),
2085                    array::from_fn(|j| if j & 1 == 0 { 0.0 } else { i as _ })
2086                );
2087            }
2088        }
2089    }
2090
2091    #[simd_test(enable = "amx-avx512,avx10.2")]
2092    fn test__tile_cvtrowps2phh() {
2093        unsafe {
2094            _init_amx();
2095            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2096
2097            let mut tile = __tile1024i::zeroed(16, 64);
2098            __tile_loadd(&mut tile, array.as_ptr().cast(), 64);
2099
2100            for i in 0..16 {
2101                let row = __tile_cvtrowps2phh(tile, i);
2102                assert_eq!(
2103                    *row.as_f16x32().as_array(),
2104                    array::from_fn(|j| if j & 1 == 0 { 0.0 } else { i as _ })
2105                );
2106            }
2107        }
2108    }
2109
2110    #[simd_test(enable = "amx-avx512,avx10.2")]
2111    fn test_tile_cvtrowps2phl() {
2112        unsafe {
2113            _init_amx();
2114            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2115
2116            let mut config = __tilecfg::default();
2117            config.palette = 1;
2118            config.colsb[0] = 64;
2119            config.rows[0] = 16;
2120            _tile_loadconfig(config.as_ptr());
2121            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2122            for i in 0..16 {
2123                let row = _tile_cvtrowps2phl::<0>(i);
2124                assert_eq!(
2125                    *row.as_f16x32().as_array(),
2126                    array::from_fn(|j| if j & 1 == 0 { i as _ } else { 0.0 })
2127                );
2128            }
2129        }
2130    }
2131
2132    #[simd_test(enable = "amx-avx512,avx10.2")]
2133    fn test_tile_cvtrowps2phli() {
2134        unsafe {
2135            _init_amx();
2136            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2137
2138            let mut config = __tilecfg::default();
2139            config.palette = 1;
2140            config.colsb[0] = 64;
2141            config.rows[0] = 16;
2142            _tile_loadconfig(config.as_ptr());
2143            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2144            for i in 0..16 {
2145                let row = wrap_imm4!(_tile_cvtrowps2phli::<0>, i);
2146                assert_eq!(
2147                    *row.as_f16x32().as_array(),
2148                    array::from_fn(|j| if j & 1 == 0 { i as _ } else { 0.0 })
2149                );
2150            }
2151        }
2152    }
2153
2154    #[simd_test(enable = "amx-avx512,avx10.2")]
2155    fn test__tile_cvtrowps2phl() {
2156        unsafe {
2157            _init_amx();
2158            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2159
2160            let mut tile = __tile1024i::zeroed(16, 64);
2161            __tile_loadd(&mut tile, array.as_ptr().cast(), 64);
2162
2163            for i in 0..16 {
2164                let row = __tile_cvtrowps2phl(tile, i);
2165                assert_eq!(
2166                    *row.as_f16x32().as_array(),
2167                    array::from_fn(|j| if j & 1 == 0 { i as _ } else { 0.0 })
2168                );
2169            }
2170        }
2171    }
2172
2173    #[simd_test(enable = "amx-avx512,avx10.2")]
2174    fn test_tile_cvtrowps2bf16h() {
2175        unsafe {
2176            _init_amx();
2177            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2178
2179            let mut config = __tilecfg::default();
2180            config.palette = 1;
2181            config.colsb[0] = 64;
2182            config.rows[0] = 16;
2183            _tile_loadconfig(config.as_ptr());
2184            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2185            for i in 0..16 {
2186                let row = _tile_cvtrowps2bf16h::<0>(i);
2187                assert_eq!(
2188                    *row.as_u16x32().as_array(),
2189                    array::from_fn(|j| if j & 1 == 0 {
2190                        0
2191                    } else {
2192                        _mm_cvtness_sbh(i as _).to_bits()
2193                    })
2194                );
2195            }
2196        }
2197    }
2198
2199    #[simd_test(enable = "amx-avx512,avx10.2")]
2200    fn test_tile_cvtrowps2bf16hi() {
2201        unsafe {
2202            _init_amx();
2203            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2204
2205            let mut config = __tilecfg::default();
2206            config.palette = 1;
2207            config.colsb[0] = 64;
2208            config.rows[0] = 16;
2209            _tile_loadconfig(config.as_ptr());
2210            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2211            for i in 0..16 {
2212                let row = wrap_imm4!(_tile_cvtrowps2bf16hi::<0>, i);
2213                assert_eq!(
2214                    *row.as_u16x32().as_array(),
2215                    array::from_fn(|j| if j & 1 == 0 {
2216                        0
2217                    } else {
2218                        _mm_cvtness_sbh(i as _).to_bits()
2219                    })
2220                );
2221            }
2222        }
2223    }
2224
2225    #[simd_test(enable = "amx-avx512,avx10.2")]
2226    fn test__tile_cvtrowps2bf16h() {
2227        unsafe {
2228            _init_amx();
2229            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2230
2231            let mut tile = __tile1024i::zeroed(16, 64);
2232            __tile_loadd(&mut tile, array.as_ptr().cast(), 64);
2233
2234            for i in 0..16 {
2235                let row = __tile_cvtrowps2bf16h(tile, i);
2236                assert_eq!(
2237                    *row.as_u16x32().as_array(),
2238                    array::from_fn(|j| if j & 1 == 0 {
2239                        0
2240                    } else {
2241                        _mm_cvtness_sbh(i as _).to_bits()
2242                    })
2243                );
2244            }
2245        }
2246    }
2247
2248    #[simd_test(enable = "amx-avx512,avx10.2")]
2249    fn test_tile_cvtrowps2bf16l() {
2250        unsafe {
2251            _init_amx();
2252            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2253
2254            let mut config = __tilecfg::default();
2255            config.palette = 1;
2256            config.colsb[0] = 64;
2257            config.rows[0] = 16;
2258            _tile_loadconfig(config.as_ptr());
2259            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2260            for i in 0..16 {
2261                let row = _tile_cvtrowps2bf16l::<0>(i);
2262                assert_eq!(
2263                    *row.as_u16x32().as_array(),
2264                    array::from_fn(|j| if j & 1 == 0 {
2265                        _mm_cvtness_sbh(i as _).to_bits()
2266                    } else {
2267                        0
2268                    })
2269                );
2270            }
2271        }
2272    }
2273
2274    #[simd_test(enable = "amx-avx512,avx10.2")]
2275    fn test_tile_cvtrowps2bf16li() {
2276        unsafe {
2277            _init_amx();
2278            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2279
2280            let mut config = __tilecfg::default();
2281            config.palette = 1;
2282            config.colsb[0] = 64;
2283            config.rows[0] = 16;
2284            _tile_loadconfig(config.as_ptr());
2285            _tile_loadd::<0>(array.as_ptr().cast(), 64);
2286            for i in 0..16 {
2287                let row = wrap_imm4!(_tile_cvtrowps2bf16li::<0>, i);
2288                assert_eq!(
2289                    *row.as_u16x32().as_array(),
2290                    array::from_fn(|j| if j & 1 == 0 {
2291                        _mm_cvtness_sbh(i as _).to_bits()
2292                    } else {
2293                        0
2294                    })
2295                );
2296            }
2297        }
2298    }
2299
2300    #[simd_test(enable = "amx-avx512,avx10.2")]
2301    fn test__tile_cvtrowps2bf16l() {
2302        unsafe {
2303            _init_amx();
2304            let array: [[f32; 16]; 16] = array::from_fn(|i| [i as _; _]);
2305
2306            let mut tile = __tile1024i::zeroed(16, 64);
2307            __tile_loadd(&mut tile, array.as_ptr().cast(), 64);
2308
2309            for i in 0..16 {
2310                let row = __tile_cvtrowps2bf16l(tile, i);
2311                assert_eq!(
2312                    *row.as_u16x32().as_array(),
2313                    array::from_fn(|j| if j & 1 == 0 {
2314                        _mm_cvtness_sbh(i as _).to_bits()
2315                    } else {
2316                        0
2317                    })
2318                );
2319            }
2320        }
2321    }
2322}