1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2020-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #include "MessageDecoder.hpp"
10
11 using namespace iga;
12
13 static const char *MDC_DS_MEANINGS[] {
14 "DE1 (1 data element per address)",
15 "DE2 (2 data elements per address)",
16 "DE4 (4 data elements per address)",
17 "DE8 (8 data elements per address)",
18 };
19
20
21 // https://gfxspecs.intel.com/Predator/Home/Index/44782
22 // https://gfxspecs.intel.com/Predator/Home/Index/44783
23 // https://gfxspecs.intel.com/Predator/Home/Index/44785
24 using HDCOpcode = uint32_t;
25 enum DC0 : uint32_t {
26 /////////////////////////////////////////
27 MSD0R_OWB = 0x00, // oword block read (unaligned)
28 MSD0R_OWAB = 0x01, // oword/hword block read (aligned)
29 MSD0W_OWB = 0x08, // oword block write
30 MSD0W_HWAB = 0x09, // hword block write (aligned)
31 MSD0R_OWDB = 0x02, // dual block read
32 MSD0W_OWDB = 0x0A, // dual block write
33 //
34 MSD0R_BS = 0x04, // byte gathered read
35 MSD0W_BS = 0x0C, // byte scattered write
36 //
37 MSD0R_DWS = 0x03, // dword gathered read
38 MSD0W_DWS = 0x0B, // dword scattered write
39 //
40 MSD0R_QWS = 0x05, // qword gathered write
41 MSD0W_QWS = 0x0D, // qword scattered write
42 //
43 MSD_MEMFENCE = 0x07,
44 //
45 };
46 enum DC1 : uint32_t {
47 /////////////////////////////////////////
48 MSD1R_US = 0x01, // untyped read
49 MSD1W_US = 0x09, // untyped write
50 //
51 MSD1R_A64_US = 0x11, // a64 untyped read
52 MSD1W_A64_US = 0x19, // a64 untyped write
53 //
54 MSD1R_A64_BS = 0x10, // byte gathered read
55 MSD1W_A64_BS = 0x1A, // byte scattered write
56 MSD1R_A64_DWS = (0x1 << 8) | MSD1R_A64_BS,
57 MSD1W_A64_DWS = (0x1 << 8) | MSD1W_A64_BS,
58 MSD1R_A64_QWS = (0x2 << 8) | MSD1R_A64_BS,
59 MSD1W_A64_QWS = (0x2 << 8) | MSD1W_A64_BS,
60 MSD1RS_A64_BS = (0x3 << 8) | MSD1R_A64_BS,
61 //
62 MSD1R_A64_HWB = 0x14,
63 MSD1W_A64_HWB = 0x15,
64 //
65 MSD1W_A64_DWAF = 0x1D,
66 MSD1W_DWAF = 0x1B,
67 // MSD1W_A64_QWAI = (1 << 12) | 0x12,
68 // MSD1W_A64_DWAI = (0 << 12) | 0x12,
69 MSD1W_A64_AI = 0x12,
70 //
71 MSD1W_DWAI = 0x02,
72 //
73 MSD1R_MB = 0x04,
74 MSD1W_MB = 0x0A,
75 //
76 MSD1R_TS = 0x05,
77 MSD1W_TS = 0x0D,
78 MSD1RS_TS = 0x0E,
79 //
80 MSD1A_DWAC = 0x0B,
81 MSD1A_DWTAI = 0x06,
82 //
83 // XE+
84 // e.g. MSD1R_WAC MSD1W_WAC => MSD1A_WAC (use "a" for atomic)
85 MSD1A_WAC = 0x0C, // typed atomic 16b int counter
86 MSD1A_WTAI = 0x07, // typed atomic 16b int op
87 MSD1A_A64_WAF = 0x1E, // typed atomic 16b float
88 MSD1A_WAF = 0x1C,
89 MSD1A_A64_WAI = 0x13,
90 MSD1A_WAI = 0x03,
91 };
92
93
94 struct MessageDecoderHDC : MessageDecoderLegacy {
MessageDecoderHDCMessageDecoderHDC95 MessageDecoderHDC(
96 Platform _platform, SFID _sfid, ExecSize execSize,
97 SendDesc _exDesc, SendDesc _desc,
98 DecodeResult &_result)
99 : MessageDecoderLegacy(
100 _platform, _sfid, execSize,
101 _exDesc, _desc, _result)
102 {
103 }
104
ensurePlatformLTMessageDecoderHDC105 void ensurePlatformLT(Platform removed) {
106 if (platform() >= removed) {
107 error(14, 5, "operation not supported on this platform");
108 }
109 }
ensurePlatformLEMessageDecoderHDC110 void ensurePlatformLE(Platform removed) {
111 if (platform() > removed) {
112 error(14, 5, "operation not supported on this platform");
113 }
114 }
ensurePlatformGEMessageDecoderHDC115 void ensurePlatformGE(Platform introduced) {
116 if (platform() < introduced) {
117 error(14, 5, "operation not supported on this platform");
118 }
119 }
ensurePlatformInMessageDecoderHDC120 void ensurePlatformIn(Platform first, Platform last) {
121 if (platform() < first || platform() > last) {
122 error(14, 5, "operation not supported on this platform");
123 }
124 }
125
126 ///////////////////////////////////////////////////////////////////////////
127 // decoder helpers
decodeXXX_HWMessageDecoderHDC128 int decodeXXX_HW(int off, int len, const char *fieldName) {
129 // scratch's use of DataElements:MDC_DB_HW uses 2 bits
130 // DataElements:MDC_DB_HW for A32 uses 3 bits (starting at bit 8)
131 // the A64 version is always [10:8]
132 auto bits = getDescBits(off,len);
133 // 0 -> 1 block, 1 -> 2 blocks, 2 -> 4 blocks, 3 -> 8 blocks
134 int val = (int)(1 << bits);
135 std::stringstream ss;
136 ss << val << " 256b blocks";
137 addField(fieldName, off, len, getDescBits(off,len), ss.str());
138 return val;
139 }
decodeMDC_A64_DB_HWMessageDecoderHDC140 int decodeMDC_A64_DB_HW(int off) {
141 return decodeXXX_HW(off, 3, "DataElements:MDC_A64_DB_HW");
142 }
decodeMDC_DB_HWMessageDecoderHDC143 int decodeMDC_DB_HW(int off, int len) {
144 return decodeXXX_HW(off, len, "DataElements:MDC_DB_HW");
145 }
146 //
decodeXXX_OWMessageDecoderHDC147 int decodeXXX_OW(int off, const char *fieldName) {
148 int bits = getDescBits(off,3);
149 int ows = 0;
150 const char *descs = "???";
151 // MDC_DB_OW and MDC_64_DB_OW
152 // 1L, 1H, 2, 4, 8, 16
153 switch (bits) {
154 case 0: ows = 1; descs = "1L (accesses low OWord of GRF)"; break;
155 case 1: ows = 1; descs = "1H (accesses second OWord of GRF)"; break;
156 case 2: ows = 2; descs = "2 OWords"; break;
157 case 3: ows = 4; descs = "4 OWords"; break;
158 case 4: ows = 8; descs = "8 OWords"; break;
159 case 5:
160 ensurePlatformGE(Platform::XE_HPG);
161 ows = 16; descs = "16 OWords";
162 break;
163 default: break;
164 }
165 addField(fieldName, off, 3, bits, descs);
166 return ows;
167 }
decodeMDC_A64_DB_OWMessageDecoderHDC168 int decodeMDC_A64_DB_OW(int off) {
169 return decodeXXX_OW(off, "DataElements:MDC_A64_DB_OW");
170 }
decodeMDC_DB_OWMessageDecoderHDC171 int decodeMDC_DB_OW(int off) {
172 return decodeXXX_OW(off, "DataElements:MDC_DB_OW");
173 }
174
decodeMDC_DSMessageDecoderHDC175 int decodeMDC_DS(int off) {
176 auto bits = getDescBits(off,2);
177 addField("DataElements:MDC_DS", off, 2, bits, MDC_DS_MEANINGS[bits]);
178 return (1 << (int)bits);
179 }
MDC_A64_DSMessageDecoderHDC180 int MDC_A64_DS(int off) {
181 auto bits = getDescBits(off,2);
182 addField("DataElements:MDC_A64_DS", off, 2, bits, MDC_DS_MEANINGS[bits]);
183 return (1 << (int)bits);
184 }
decodeMDC_DWS_DSMessageDecoderHDC185 int decodeMDC_DWS_DS(int off) {
186 auto bits = getDescBits(off,2);
187 static const char *meanings[] {
188 "Fill low 1 byte per DW",
189 "Fill low 2 bytes per DW",
190 "Fill all 4 bytes per DW",
191 "???"
192 };
193 addField("DataElements:MDC_DWS_DS", off, 2, bits, meanings[bits]);
194 return (1 << (int)bits);
195 }
196
decodeMDC_SM2XMessageDecoderHDC197 int decodeMDC_SM2X(int off, bool reversed) {
198
199 int simd = 0;
200 if (reversed) {
201 int bits =
202 decodeDescBitField("SimdMode:MDC_SM2R", off, "SIMD8", "SIMD16");
203 simd = bits ? 8 : 16;
204 } else {
205 int bits =
206 decodeDescBitField("SimdMode:MDC_SM2R", off, "SIMD16", "SIMD8");
207 simd = bits ? 16 : 8;
208 }
209
210 if (platform() >= Platform::XE_HPC) {
211 if (simd == 16) {
212 error(off, 1, "invalid value for this platform");
213 }
214 simd *= 2;
215 }
216 return simd;
217 }
decodeMDC_SM2RMessageDecoderHDC218 int decodeMDC_SM2R(int off) {return decodeMDC_SM2X(off, true);}
decodeMDC_SM2SMessageDecoderHDC219 int decodeMDC_SM2S(int off) {return decodeMDC_SM2X(off, false);}
decodeMDC_SM3MessageDecoderHDC220 int decodeMDC_SM3(int off) {
221 auto bits = getDescBits(off, 2);
222 int simd = 0;
223 const char *simdStr = "?";
224 switch (bits) {
225 case 1: simd = 16; simdStr = "SIMD16"; break;
226 case 2: simd = 8; simdStr = "SIMD8"; break;
227 default: error(off, 2, "invalid value"); break;
228 }
229 if (platform() >= Platform::XE_HPC) {
230 if (bits == 2) {
231 // illegal on XeHPC+
232 error(off, 1, "invalid value for this platform");
233 }
234 }
235 addField("SimdMode:MDC_SM3", off, 2, bits, simdStr);
236 return simd;
237 }
decodeMDC_CMASKMessageDecoderHDC238 int decodeMDC_CMASK() {
239 auto bits = getDescBits(8, 4);
240 std::stringstream ss;
241 int vecLen = 0;
242 if (bits == 0xF) {
243 error(8, 4, "channel mask must have one element not disabled");
244 }
245 for (int i = 0; i < 4; i++) {
246 if (((1 << i) & bits) == 0) {
247 if (vecLen > 0)
248 ss << ", ";
249 ss << "XYZW"[i];
250 vecLen++;
251 }
252 }
253 if (vecLen == 0)
254 ss << "no channels enabled";
255 else
256 ss << " enabled";
257 addField("ChannelDisableMask:MDC_CMASK", 8, 4, bits, ss.str());
258 return vecLen;
259 }
260
261
262
263 // returns true if high slot group
decodeMDC_SG3MessageDecoderHDC264 bool decodeMDC_SG3() {
265 auto bits = getDescBits(12, 2);
266 const char *sym = "??";
267 switch (bits) {
268 case 0: sym = "SG4x2"; break;
269 case 1:
270 sym = "SG8L";
271 // in XeHPC this becomes the default
272 if (platform() >= Platform::XE_HPC)
273 sym = "SIMD16";
274 break;
275 case 2: sym = "SG8U"; break;
276 default:
277 error(12,2,"invalid slot group value");
278 }
279 addField("SlotGroup:MDC_SG3", 12, 2, bits, sym);
280 return bits == 2;
281 }
282
decodeMDC_SG2MessageDecoderHDC283 bool decodeMDC_SG2() {
284 auto bits = getDescBits(12,1);
285 const char *sym = "??";
286 switch (bits) {
287 case 0:
288 sym = "SG8L";
289 // in XeHPC this becomes the default
290 if (platform() >= Platform::XE_HPC)
291 sym = "SIMD16";
292 break;
293 case 1: sym = "SG8U"; break;
294 default: break;
295 }
296 addField("SlotGroup:MDC_SG2", 12, 1, bits, sym);
297 return bits == 1;
298 }
299
decodeMDC_IARMessageDecoderHDC300 CacheOpt decodeMDC_IAR() {
301 int bits = decodeDescBitField("MDC_IAR", 13, "disabled", "enabled");
302 return bits ? CacheOpt::READINVALIDATE : CacheOpt::DEFAULT;
303 }
304
305 ///////////////////////////////////////////////////////////////////////////
306 //
307
308 // allows different data sizes in mem and reg
setHdcMessageXMessageDecoderHDC309 void setHdcMessageX(
310 std::string msgSym,
311 std::string msgDesc,
312 SendOp op,
313 int addrSizeBits,
314 int bitsPerElemReg,
315 int bitsPerElemMem,
316 int elemsPerAddr,
317 int execSize,
318 MessageInfo::Attr extraAttrs)
319 {
320 CacheOpt caching = CacheOpt::DEFAULT;
321 const SendOpDefinition &opInfo = lookupSendOp(op);
322 std::stringstream ss;
323 ss << "hdc_";
324 ss << msgSym; // e.g. "load"
325 if (execSize == 8 || execSize == 16)
326 ss << "_simd" << execSize;
327
328 if (instExecSize != ExecSize::INVALID) {
329 // e.g. a SIMD4 message will mask out the top bits
330 execSize = std::min(execSize, int(instExecSize));
331 }
332
333 ss << ".";
334 int bti = 0;
335 if (!(extraAttrs & MessageInfo::Attr::SCRATCH)) {
336 bti = decodeBTI(addrSizeBits);
337 }
338 AddrType addrType = AddrType::BTI;
339 uint32_t surfaceId = 0;
340 if (addrSizeBits == 32) {
341 if (extraAttrs & MessageInfo::Attr::SCRATCH) {
342 ss << "scratch";
343 ss << "+" << 32*getDescBits(0, 12);
344 } else if (bti == SLM_BTI) {
345 ss << "slm";
346 addrType = AddrType::FLAT;
347 surfaceId = 0;
348 extraAttrs |= MessageInfo::Attr::SLM;
349 } else if (bti == COHERENT_BTI || bti == NONCOHERENT_BTI) {
350 ss << "stateless";
351 if (bti != COHERENT_BTI) {
352 ss << "_incoherent";
353 caching = CacheOpt::CACHED;
354 } else {
355 caching = CacheOpt::UNCACHED;
356 }
357 addrType = AddrType::FLAT;
358 } else {
359 addrType = AddrType::BTI;
360 surfaceId = bti;
361 ss << "bti[" << bti << "]";
362 }
363 } else if (addrSizeBits == 64) {
364 ss << "stateless";
365 if (bti != COHERENT_BTI) {
366 ss << "_incoherent";
367 caching = CacheOpt::CACHED;
368 } else {
369 caching = CacheOpt::UNCACHED;
370 }
371 addrType = AddrType::FLAT;
372 if (bti != COHERENT_BTI && bti != NONCOHERENT_BTI)
373 error(0, 8, "must have 0xFF or 0xFD BTI");
374 }
375 ss << ".a" << addrSizeBits;
376 if (bitsPerElemReg == bitsPerElemMem) {
377 ss << ".d" << bitsPerElemReg;
378 } else {
379 ss << ".d" << bitsPerElemMem << "u" << bitsPerElemReg;
380 }
381 int chEnMask = 0;
382 if (opInfo.hasChMask()) {
383 ss << ".";
384 // in legacy HDC messages, this is a channel disable mask
385 auto chDisabled = getDescBits(8,4);
386 chEnMask = ~chDisabled & 0xF;
387 if ((chDisabled & 0x1) == 0) {
388 ss << 'x';
389 }
390 if ((chDisabled & 0x2) == 0) {
391 ss << 'y';
392 }
393 if ((chDisabled & 0x4) == 0) {
394 ss << 'z';
395 }
396 if ((chDisabled & 0x8) == 0) {
397 ss << 'w';
398 }
399 } else {
400 if (elemsPerAddr > 1 ||
401 (extraAttrs & MessageInfo::Attr::TRANSPOSED))
402 {
403 ss << "x" << elemsPerAddr;
404 }
405 }
406
407 // if DC2, ExDesc[31:16] is immediate offset
408 if (sfid == SFID::DC2 && exDesc.isImm())
409 result.info.immediateOffset = exDesc.imm >> 16;
410 setScatterGatherOpX(
411 ss.str(),
412 msgDesc,
413 op,
414 addrType,
415 SendDesc(surfaceId),
416 caching,
417 caching,
418 addrSizeBits,
419 bitsPerElemReg, bitsPerElemMem,
420 elemsPerAddr,
421 execSize,
422 extraAttrs);
423 result.info.channelsEnabled = chEnMask;
424 }
425 // data size is same in mem and reg (typical case)
setHdcMessageMessageDecoderHDC426 void setHdcMessage(
427 std::string msgSym,
428 std::string msgDesc,
429 SendOp op,
430 int addrSize,
431 int bitsPerElem,
432 int elemsPerAddr,
433 int execSize,
434 MessageInfo::Attr extraAttrs)
435 {
436 setHdcMessageX(
437 msgSym,
438 msgDesc,
439 op,
440 addrSize,
441 bitsPerElem, bitsPerElem,
442 elemsPerAddr,
443 execSize,
444 extraAttrs);
445 }
446
setHdcOwBlockMessageDecoderHDC447 void setHdcOwBlock(
448 std::string msgSym,
449 std::string msgDesc,
450 SendOp op,
451 int addrSize,
452 MessageInfo::Attr extraAttrs)
453 {
454 enum MDC_A64_DB_OW {
455 OW1L = 0x0,
456 OW1H = 0x1,
457 OW2 = 0x2,
458 OW4 = 0x3,
459 OW8 = 0x4,
460 };
461
462 auto owBits = getDescBits(8, 3);
463 if (owBits == OW1H) {
464 extraAttrs |= MessageInfo::Attr::EXPAND_HIGH;
465 }
466 extraAttrs |= MessageInfo::Attr::TRANSPOSED;
467
468 int elems = addrSize == 64 ?
469 decodeMDC_A64_DB_OW(8) :
470 decodeMDC_DB_OW(8);
471 std::stringstream ss;
472 ss << msgDesc << " x" << elems;
473 if (owBits == OW1H)
474 ss << "H";
475 msgDesc = ss.str();
476
477 setHdcMessageX(
478 msgSym,
479 msgDesc,
480 op,
481 addrSize,
482 128, 128,
483 elems,
484 1, // SIMD
485 extraAttrs);
486 }
487
setHdcHwBlockMessageDecoderHDC488 void setHdcHwBlock(
489 std::string msgSym,
490 std::string msgDesc,
491 SendOp op,
492 int addrSize,
493 int blockCountOffset,
494 int blockCountLen,
495 MessageInfo::Attr extraAttrs)
496 {
497 extraAttrs |= MessageInfo::Attr::TRANSPOSED;
498
499 int elems =
500 addrSize == 64 ?
501 decodeMDC_A64_DB_HW(blockCountOffset) :
502 decodeMDC_DB_HW(blockCountOffset, blockCountLen);
503 std::stringstream ss;
504 ss << msgDesc << " x" << elems;
505 msgDesc = ss.str();
506
507 setHdcMessageX(
508 msgSym,
509 msgDesc,
510 op,
511 addrSize,
512 256, 256,
513 elems,
514 1, // SIMD
515 extraAttrs);
516 }
517
setHdcUntypedSurfaceMessageMessageDecoderHDC518 void setHdcUntypedSurfaceMessage(
519 std::string msgDesc,
520 bool isRead,
521 int addrSizeBits,
522 MessageInfo::Attr extraAttrs)
523 {
524 std::string msgSym = isRead ? "untyped_load" : "untyped_store";
525 extraAttrs |= MessageInfo::Attr::HAS_CHMASK;
526 //
527 appendCMask(msgDesc);
528 //
529 setHdcMessage(
530 msgSym,
531 msgDesc,
532 isRead ? SendOp::LOAD_QUAD : SendOp::STORE_QUAD,
533 addrSizeBits,
534 32,
535 decodeMDC_CMASK(),
536 decodeMDC_SM3(12),
537 extraAttrs);
538 }
539
appendCMaskMessageDecoderHDC540 void appendCMask(std::string &msgDesc) {
541 auto cMaskBits = getDescBits(8, 4);
542 msgDesc += " with ";
543 for (int i = 0; i < 4; i++) {
544 if ((cMaskBits & (1 << i)) == 0) {
545 // NOTE: legacy untyped message channel masks are a
546 // disable bit
547 msgDesc += "xyzw"[i];
548 }
549 }
550 }
551
setHdcTypedSurfaceMessageMessageDecoderHDC552 void setHdcTypedSurfaceMessage(
553 bool isRead,
554 const char *doc,
555 const char *docXe,
556 bool returnsStatus = false)
557 {
558 std::string msgDesc = isRead ?
559 "typed surface read" : "typed surface write";
560 addField("MessageType", 14, 5, getDescBits(14, 5), msgDesc);
561
562 std::string msgSym = isRead ? "typed_load" : "typed_store";
563 if (decodeMDC_SG3()) {
564 msgDesc += " (high slot group)";
565 msgSym += "_sgh";
566 }
567 if (returnsStatus) {
568 msgDesc += " returning status";
569 msgSym += "_wstatus";
570 }
571 //
572 appendCMask(msgDesc);
573 //
574 setHdcMessage(
575 msgSym,
576 msgDesc,
577 isRead ? SendOp::LOAD_QUAD : SendOp::STORE_QUAD,
578 32, // addrSize
579 32, // dataSize
580 decodeMDC_CMASK(),
581 DEFAULT_EXEC_SIZE / 2, // HDC typed is always SIMD8
582 MessageInfo::Attr::HAS_CHMASK | MessageInfo::Attr::HAS_UVRLOD);
583 setDoc(doc, docXe, nullptr);
584 }
585
setHdcFloatAtomicMessageMessageDecoderHDC586 void setHdcFloatAtomicMessage(
587 const char *msgNameDesc, int addrSize, int dataSize,
588 const char *docNoRet, const char *docWiRet,
589 const char *docNoRetXe, const char *docWiRetXe)
590 {
591 addField("MessageType", 14, 5, getDescBits(14, 5), msgNameDesc);
592
593 std::string msgSym = "atomic_float?";
594 std::string msgDesc;
595 SendOp op = SendOp::INVALID;
596 auto atBits = getDescBits(8, 3);
597 switch (atBits) {
598 case 0x1:
599 op = SendOp::ATOMIC_FMAX;
600 msgSym ="atomic_fmax";
601 msgDesc = "max";
602 break;
603 case 0x2:
604 op = SendOp::ATOMIC_FMIN;
605 msgSym ="atomic_fmin";
606 msgDesc = "min";
607 break;
608 case 0x3: op = SendOp::ATOMIC_FCAS;
609 msgSym ="atomic_fcas";
610 msgDesc = "fp-compare and swap ";
611 break;
612 // XeHP+
613 case 0x4:
614 op = SendOp::ATOMIC_FADD;
615 msgSym ="atomic_fadd";
616 msgDesc = "add";
617 break;
618 case 0x5:
619 op = SendOp::ATOMIC_FSUB;
620 msgSym ="atomic_fsub";
621 msgDesc = "subtract";
622 break;
623 // they just wedged in 64b as part of the 32b float atomic message
624 case 0x6:
625 op = SendOp::ATOMIC_FADD;
626 msgSym ="atomic_fadd";
627 msgDesc = "64b add";
628 dataSize = 64;
629 break;
630 case 0x7:
631 op = SendOp::ATOMIC_FSUB;
632 msgSym ="atomic_fsub";
633 msgDesc = "64b subtract";
634 dataSize = 64;
635 break;
636 default:
637 error(8, 3, " (unknown float op)"); // fallthrough
638 }
639 std::stringstream ssDesc;
640 ssDesc << msgNameDesc << " " << msgDesc << " (" << dataSize << "b)";
641 addField("AtomicOp:MDC_AOP", 8, 3, atBits, ssDesc.str());
642
643 MessageInfo::Attr extraAttrs = MessageInfo::Attr::NONE;
644 if (decodeDescBitField(
645 "ReturnDataControl", 13, "no return value", "returns new value"))
646 {
647 extraAttrs |= MessageInfo::Attr::ATOMIC_RETURNS;
648 msgSym += "_ret";
649 ssDesc << " with return";
650 setDoc(docWiRet, docWiRetXe, nullptr);
651 }
652 else
653 {
654 setDoc(docNoRet, docNoRetXe, nullptr);
655 }
656 if (op != SendOp::INVALID) {
657 setHdcMessage(
658 msgSym,
659 ssDesc.str(),
660 op,
661 addrSize,
662 dataSize,
663 1,
664 addrSize == 64 ? decodeMDC_SM2S(12) : decodeMDC_SM2R(12),
665 extraAttrs);
666 }
667 } // setHdcFloatAtomicMessage
668
setHdcIntAtomicMessageMessageDecoderHDC669 void setHdcIntAtomicMessage(
670 const char *typedUntyped, // "typed" or "untyped"
671 const char *msgDesc0,
672 int addrSize,
673 int dataSize,
674 int simdSize,
675 const char *docNoRet, const char *docWiRet,
676 const char *docNoRet12, const char *docWiRet12)
677 {
678 std::stringstream msgSym;
679 msgSym << typedUntyped << "_";
680 std::stringstream msgDesc;
681 msgDesc << typedUntyped << " " << msgDesc0;
682
683 addField("MessageType", 14, 5, getDescBits(14, 5), msgDesc.str());
684
685 std::string mOpName;
686 SendOp op = SendOp::INVALID;
687 auto aopBits = getDescBits(8, 4);
688 std::string opDesc;
689 switch (aopBits) {
690 // again with case 0x0 they wedged in a 64b CAS as part of the
691 // 32b message (note there's also a QW atomic message)
692 case 0x0: op =
693 SendOp::ATOMIC_ICAS;
694 mOpName = "atomic_icas";
695 opDesc = "64b integer compare and swap";
696 dataSize = 64;
697 break;
698 // The rest are 32b (or 16b)
699 case 0x1:
700 op = SendOp::ATOMIC_AND;
701 mOpName = "atomic_and";
702 opDesc = "logical AND";
703 break;
704 case 0x2:
705 op = SendOp::ATOMIC_OR;
706 mOpName = "atomic_or";
707 opDesc = "logical OR";
708 break;
709 case 0x3:
710 op = SendOp::ATOMIC_XOR;
711 mOpName = "atomic_xor";
712 opDesc = "logical XOR";
713 break;
714 case 0x4:
715 op = SendOp::ATOMIC_STORE;
716 mOpName = "atomic_store";
717 opDesc = "store";
718 break;
719 case 0x5:
720 op = SendOp::ATOMIC_IINC;
721 mOpName = "atomic_iinc";
722 opDesc = "integer increment";
723 break;
724 case 0x6:
725 op = SendOp::ATOMIC_IDEC;
726 mOpName = "atomic_idec";
727 opDesc = "integer decrement";
728 break;
729 case 0xF:
730 op = SendOp::ATOMIC_IPDEC;
731 mOpName = "atomic_iipdec";
732 opDesc = "integer pre-decrement (returns pre-decrement value)";
733 break;
734 case 0x7:
735 op = SendOp::ATOMIC_IADD;
736 mOpName = "atomic_iadd";
737 opDesc = "integer add";
738 break;
739 case 0x8:
740 op = SendOp::ATOMIC_ISUB;
741 mOpName = "atomic_isub";
742 opDesc = "integer subtract";
743 break;
744 case 0x9:
745 op = SendOp::ATOMIC_IRSUB;
746 mOpName = "atomic_irsub";
747 opDesc = "commuted integer subtract";
748 break;
749 case 0xA:
750 op = SendOp::ATOMIC_SMAX;
751 mOpName = "atomic_smax";
752 opDesc = "signed-integer max";
753 break;
754 case 0xB:
755 op = SendOp::ATOMIC_SMIN;
756 mOpName = "atomic_smin";
757 opDesc = "signed-integer min";
758 break;
759 case 0xC:
760 op = SendOp::ATOMIC_UMAX;
761 mOpName = "atomic_umax";
762 opDesc = "unsigned-integer max";
763 break;
764 case 0xD:
765 op = SendOp::ATOMIC_UMIN;
766 mOpName = "atomic_umin";
767 opDesc = "unsigned-integer min";
768 break;
769 case 0xE:
770 op = SendOp::ATOMIC_ICAS;
771 mOpName = "atomic_icas";
772 opDesc = "integer compare and swap";
773 break;
774 //
775 default:
776 {
777 std::stringstream ss;
778 ss << "0x" << std::uppercase << std::hex <<
779 getDescBits(8,4) << "?";
780 mOpName = ss.str();
781 opDesc = mOpName;
782 error(8, 4, " unknown int atomic op");
783 }
784 }
785 msgSym << mOpName;
786 //
787 addField("AtomicIntegerOp", 8, 4, aopBits, opDesc);
788 //
789 MessageInfo::Attr extraAttrs = MessageInfo::Attr::NONE;
790 if (decodeDescBitField(
791 "ReturnDataControl", 13, "no return value", "returns new value"))
792 {
793 extraAttrs |= MessageInfo::Attr::ATOMIC_RETURNS;
794 msgSym << "_ret";
795 setDoc(docWiRet, docWiRet12, nullptr);
796 } else {
797 setDoc(docNoRet, docNoRet12, nullptr);
798 }
799 if (op != SendOp::INVALID) {
800 msgDesc << " " << opDesc;
801 setHdcMessage(
802 msgSym.str(),
803 msgDesc.str(),
804 op,
805 addrSize,
806 dataSize,
807 1,
808 simdSize,
809 extraAttrs);
810 }
811 } // setHdcIntAtomicMessage
812
813 ///////////////////////////////////////////////////////////////////////////
tryDecodeMessageDecoderHDC814 void tryDecode() {
815 switch (sfid) {
816 case SFID::DCRO: tryDecodeDCRO(); break;
817 case SFID::DC0: tryDecodeDC0(); break;
818 case SFID::DC1: tryDecodeDC1(); break;
819 //////////////////////////////////////////////////////////////
820 // DC2 shouldn't be used after SKL
821 case SFID::DC2: error(0, 32, "unsupported DC2 op"); break;
822 default:
823 error(0, 0, "unsupported sfid");
824 return;
825 }
826 }
827
828 void tryDecodeDCRO();
829 void tryDecodeDC0();
830 void tryDecodeDC0BSRW(bool isRead);
831 void tryDecodeDC0AlignedBlock();
832 void tryDecodeDC0Memfence();
833 void tryDecodeDC0ScratchBlock();
834 void tryDecodeDC1();
835 }; // MessageDecoderHDC
836
837
838 // Enum of all DCRO ops
839 // https://gfxspecs.intel.com/Predator/Home/Index/44785
840 enum DCRO_MT {
841 MT_CC_OWB = 0x00,
842 MT_CC_OWAB = 0x01,
843 MT_CC_DWS = 0x03,
844 // these are XeHP only
845 MT_US_CCS_OP = 0x08, // cannot find BXML page
846 MT_A64_US_CCS_OP = 0x18,
847 MT_A64_US_UCW = 0x19,
848 // XeHPG+
849 MT_TS_UCW = 0x0D,
850 MT_TS_CCS_OP = 0x0C,
851 MT_US_UCW = 0x09,
852 MT_A64_CCS_PG_OP = 0x17,
853 };
854
tryDecodeDCRO()855 void MessageDecoderHDC::tryDecodeDCRO() {
856 const int msgType = getDescBits(14, 5);
857 const char *desc = "???";
858
859 auto setMessageTypeDesc = [&](const char *d) {
860 desc = d;
861 addField("MessageType", 14, 5, msgType, d);
862 };
863 switch (msgType) {
864 case MT_CC_OWB: // constant oword block read
865 case MT_CC_OWAB: // constant unaligned oword block read
866 setMessageTypeDesc(
867 msgType == MT_CC_OWB ?
868 "constant " "oword block read" :
869 "constant aligned oword block read");
870 setHdcOwBlock(
871 msgType == MT_CC_OWB ?
872 "const_load_block" :
873 "aligned_const_load_block",
874 desc,
875 SendOp::LOAD,
876 32, // 32b address
877 MessageInfo::Attr::NONE);
878 result.info.cachingL3 = decodeMDC_IAR();
879 decodeMDC_HR();
880 setDoc(
881 msgType == MT_CC_OWB ? "7041" : "7043",
882 msgType == MT_CC_OWB ? "44767" : "44766",
883 nullptr);
884 break;
885 case MT_CC_DWS:
886 setMessageTypeDesc("constant dword gathering read");
887 result.info.cachingL3 = decodeMDC_IAR();
888 setHdcMessage(
889 "const_load",
890 "constant dword gathering read",
891 SendOp::LOAD,
892 32,
893 32,
894 decodeMDC_DWS_DS(10),
895 decodeMDC_SM2(8),
896 MessageInfo::Attr::NONE);
897 decodeExpected(9, 1, "LegacySimdMode", 1);
898 decodeMDC_H();
899 setDoc("7084", "44765", nullptr);
900 break;
901 // case MT_US_CCS_OP: // TODO: find BXML page
902 case MT_A64_US_CCS_OP:
903 {
904 setMessageTypeDesc("A64 untyped surface CCS operation");
905 decodeMDC_HF();
906 auto ccsOp = decodeDescField("SectorUpdateOpcode", 8, 4,
907 [] (std::stringstream &ss, uint32_t val){
908 switch (val) {
909 case 0x1: ss << "Slow Clear"; break;
910 case 0x3: ss << "Slow Uncompress"; break;
911 default: ss << "?";
912 }
913 });
914 setHdcMessage(
915 "a64_untyped_ccs_op",
916 desc,
917 ccsOp == 0x1 ? SendOp::CCS_SC : SendOp::CCS_SU,
918 64, // addr size
919 0, // data
920 1, // vec elems
921 decodeMDC_SM3(12),
922 MessageInfo::Attr::NONE);
923 setDoc("44763");
924 ensurePlatformGE(Platform::XE_HP);
925 break;
926 }
927 case MT_A64_US_UCW:
928 setMessageTypeDesc("A64 untyped surface uncompressed write");
929 setHdcMessage(
930 "a64_untyped_uncompressed_store_quad",
931 desc,
932 SendOp::STORE_UNCOMPRESSED_QUAD,
933 64, // addr size
934 32, // data size
935 decodeMDC_CMASK(),
936 decodeMDC_SM3(12),
937 MessageInfo::Attr::NONE);
938 decodeMDC_HF();
939 setDoc("44764");
940 ensurePlatformGE(Platform::XE_HP);
941 break;
942 case MT_A64_CCS_PG_OP:
943 {
944 setMessageTypeDesc("A64 page CCS update operation");
945 auto ccsOp = decodeDescField("PageUpdateOpcode", 8, 2,
946 [] (std::stringstream &ss, uint32_t val){
947 switch (val) {
948 case 0: ss << "Fast Clear"; break;
949 case 2: ss << "Fast Uncompress"; break;
950 default: ss << "?";
951 }
952 });
953 int surfId = decodeBTI(64);
954 setSpecialOpX(
955 "a64_ccs_update",
956 desc,
957 ccsOp == 0x0 ? SendOp::CCS_PC : SendOp::CCS_PU,
958 AddrType::BTI,
959 SendDesc(surfId),
960 1,
961 0,
962 MessageInfo::Attr::NONE);
963 decodeMDC_HR();
964 setDoc("44762");
965 ensurePlatformGE(Platform::XE_HPG);
966 break;
967 }
968 case MT_TS_UCW:
969 setMessageTypeDesc("typed surface uncompressed write");
970 setHdcMessage(
971 "typed_uncompressed_store_quad",
972 desc,
973 SendOp::STORE_UNCOMPRESSED_QUAD,
974 32, // addr size
975 32, // data size
976 decodeMDC_CMASK(),
977 decodeMDC_SG3(),
978 MessageInfo::Attr::NONE);
979 decodeMDC_H();
980 setDoc("44773");
981 ensurePlatformGE(Platform::XE_HPG);
982 break;
983 case MT_TS_CCS_OP:
984 {
985 setMessageTypeDesc("typed surface CCS update message");
986 auto ccsOp = decodeDescField("SectorUpdateOpcode", 8, 4,
987 [] (std::stringstream &ss, uint32_t val){
988 switch (val) {
989 case 1: ss << "Slow Clear"; break;
990 case 3: ss << "Slow Uncompress"; break;
991 default: ss << "?";
992 }
993 });
994 setHdcMessage(
995 "a64_typed_ccs_op",
996 desc,
997 ccsOp == 0x1 ? SendOp::CCS_SC : SendOp::CCS_SU,
998 32, // addr size
999 32, // data
1000 1, // vec elems
1001 decodeMDC_SG3(),
1002 MessageInfo::Attr::NONE);
1003 decodeMDC_H();
1004 setDoc("44763");
1005 break;
1006 }
1007 case MT_US_UCW:
1008 setMessageTypeDesc("untyped surface uncompressed write");
1009 setHdcMessage(
1010 "untyped_uncompressed_store_quad",
1011 desc,
1012 SendOp::STORE_UNCOMPRESSED_QUAD,
1013 32, // addr size
1014 32, // data size
1015 decodeMDC_CMASK(),
1016 decodeMDC_SM3(12),
1017 MessageInfo::Attr::NONE);
1018 decodeMDC_H();
1019 setDoc("44775");
1020 ensurePlatformGE(Platform::XE_HPG);
1021 break;
1022 default:
1023 setMessageTypeDesc("unknown DCRO message");
1024 decodeMDC_H();
1025 (void)decodeBTI(32);
1026 error(14, 5, "unsupported DCRO op");
1027 return;
1028 }
1029 }
1030
1031 // XE: DC0 https://gfxspecs.intel.com/Predator/Home/Index/44782
tryDecodeDC0()1032 void MessageDecoderHDC::tryDecodeDC0()
1033 {
1034 const int msgType = getDescBits(14, 5);
1035 const char *desc = "???";
1036 auto addMessageType = [&](const char *d) {
1037 addField("MessageType", 14, 5, msgType, d);
1038 desc = d;
1039 };
1040 switch (msgType) {
1041 case MSD0R_OWB: // oword block read (unaligned)
1042 addMessageType("oword block read");
1043 setHdcOwBlock(
1044 "load_block",
1045 desc,
1046 SendOp::LOAD,
1047 32, // all 32b addresses
1048 MessageInfo::Attr::NONE);
1049 setDoc("7028", "44722", nullptr);
1050 decodeMDC_HR();
1051 break;
1052 case MSD0R_OWAB: // aligned hword/oword block read
1053 tryDecodeDC0AlignedBlock();
1054 break;
1055 case MSD0W_OWB: // hword/oword block write
1056 addMessageType("oword block write");
1057 setHdcOwBlock(
1058 "store_block",
1059 desc,
1060 SendOp::STORE,
1061 32, // all 32b addresses
1062 MessageInfo::Attr::NONE);
1063 setDoc("7032", "44730", nullptr);
1064 decodeMDC_HR();
1065 break;
1066 case MSD0W_HWAB: // hword aligned block write
1067 addMessageType("hword aligned block write");
1068 setHdcOwBlock(
1069 "aligned_store_block",
1070 desc,
1071 SendOp::STORE,
1072 32, // all 32b addresses
1073 MessageInfo::Attr::NONE);
1074 setDoc("20862", "44727", nullptr);
1075 decodeMDC_HR();
1076 break;
1077 //
1078 case MSD0R_OWDB: // oword dual block read
1079 addMessageType("oword dual block read");
1080 setDoc("7029", nullptr, nullptr);
1081 result.info.description = desc;
1082 decodeMDC_HR();
1083 error(14, 5, "oword dual block read decode not supported");
1084 return;
1085 case MSD0W_OWDB: // oword dual block write
1086 addMessageType("oword dual block write");
1087 result.info.description = desc;
1088 setDoc("7033", nullptr, nullptr);
1089 decodeMDC_HR();
1090 error(14, 5, "oword dual block write decode not supported");
1091 return;
1092 //
1093 case MSD0R_BS: // byte gathered read
1094 case MSD0W_BS: // byte scattered write
1095 tryDecodeDC0BSRW(msgType == MSD0R_BS);
1096 break;
1097 //
1098 case MSD0R_DWS: // dword gathered read
1099 case MSD0W_DWS: // dword scattered write
1100 {
1101 bool isRead = msgType == MSD0R_DWS;
1102 const char *msgName = isRead ?
1103 "dword gathering read" : "dword scattering write";
1104 addMessageType(msgName);
1105 //
1106 int elemsPerAddr = decodeMDC_DWS_DS(10);
1107 std::stringstream ss;
1108 ss << msgName;
1109 if (elemsPerAddr != 1)
1110 ss << " x" << elemsPerAddr;
1111 //
1112 setHdcMessage(
1113 isRead ? "load" : "store",
1114 ss.str(),
1115 isRead ? SendOp::LOAD : SendOp::STORE,
1116 32,
1117 32,
1118 elemsPerAddr,
1119 decodeMDC_SM2(8),
1120 MessageInfo::Attr::NONE);
1121 result.info.cachingL3 = decodeMDC_IAR();
1122 setDoc(
1123 isRead ? "7067" : "7069",
1124 isRead ? "44718" : "44726",
1125 nullptr);
1126 decodeExpected(9, 1, "LegacySimdMode", 1);
1127 decodeMDC_H();
1128 break;
1129 }
1130 case MSD0R_QWS: // qword gather
1131 case MSD0W_QWS: // qword scatter
1132 {
1133 auto isRead = MSD0R_QWS;
1134 const char *msgName = isRead ?
1135 "qword gathering read" : "qword scattering write";
1136 addMessageType(msgName);
1137 //
1138 setHdcMessage(
1139 isRead ? "load" : "store",
1140 msgName,
1141 isRead ? SendOp::LOAD : SendOp::STORE,
1142 32, // addrs
1143 64, // data
1144 decodeMDC_DWS_DS(10),
1145 decodeMDC_SM2(8),
1146 MessageInfo::Attr::NONE);
1147 setDoc(
1148 isRead ? "33652" : "33653",
1149 isRead ? "44723" : "44731",
1150 nullptr);
1151 decodeExpected(9, 1, "LegacySimdMode", 1);
1152 decodeMDC_H();
1153 break;
1154 }
1155 case MSD_MEMFENCE:
1156 tryDecodeDC0Memfence();
1157 break;
1158 default:
1159 if (getDescBit(18) == 1) {
1160 tryDecodeDC0ScratchBlock();
1161 } else {
1162 addField("MessageType", 14, 5, msgType, "???");
1163 error(14, 5, "unsupported dc0 op");
1164 return;
1165 }
1166 } // end switch legacy DC0
1167 }
1168
tryDecodeDC0BSRW(bool isRead)1169 void MessageDecoderHDC::tryDecodeDC0BSRW(bool isRead)
1170 {
1171 const uint32_t msgType = getDescBits(14, 5);
1172 const char *msgName = isRead ?
1173 "byte gathering read" : "byte scattering write";
1174
1175 addField("MessageType", 14, 5, msgType, msgName);
1176
1177 std::stringstream descs;
1178 descs << msgName;
1179 int memBytes = decodeMDC_DS(10);
1180 if (memBytes == 1)
1181 descs << " 8b";
1182 else if (memBytes == 2)
1183 descs << " 16b";
1184 else if (memBytes == 4)
1185 descs << " 32b";
1186
1187 //
1188 // "byte" scattered always consumes a DW of GRF per channel,
1189 // but DWS_DS controls how many bytes are loaded per address
1190 // that might be 1, 2, 4 all packed into one DW.
1191 // So think of:
1192 // DWS_DS == 0 (byte) as u8 aligned to u32 (upper bits undefined)
1193 // DWS_DS == 1 (word) as u16 aligned to u32 (upper bits undefined)
1194 // DWS_DS == 2 (dword) as u32
1195 setHdcMessageX(
1196 isRead ? "load" : "store",
1197 descs.str(),
1198 isRead ? SendOp::LOAD : SendOp::STORE,
1199 32, // 32b addrs
1200 32, // each channel occupies a DW in the reg file
1201 8*memBytes, // in memory it can be 1, 2, or 4 bytes
1202 1, // vector size always 1
1203 decodeMDC_SM2(8),
1204 MessageInfo::Attr::NONE);
1205 result.info.cachingL3 = decodeMDC_IAR();
1206 setDoc(isRead ? "7066" : "7068", isRead ? "44717" : "44725", nullptr);
1207 decodeMDC_H();
1208 }
1209
tryDecodeDC0AlignedBlock()1210 void MessageDecoderHDC::tryDecodeDC0AlignedBlock()
1211 {
1212 const int msgType = getDescBits(14, 5);
1213 const char *descs ="aligned block read";
1214 const char *doc = "7030";
1215 bool isHw = false;
1216 if (platform() >= Platform::XE_HPG) {
1217 isHw = getDescBit(13);
1218 addField("BlockMessageSubtype", 13, 1, isHw, isHw ? "HWord" : "OWord");
1219 if (isHw) {
1220 descs ="aligned block read";
1221 doc = "44719";
1222 } else {
1223 doc = "44721";
1224 }
1225 } // else: [13] is reserved
1226 addField("MessageType", 14, 5, msgType, descs);
1227 if (isHw) {
1228 setHdcHwBlock(
1229 "aligned_load_block256",
1230 "hword aligned block read",
1231 SendOp::LOAD,
1232 32, // all 32b addresses
1233 8, 3, // [10:8]
1234 MessageInfo::Attr::NONE);
1235 } else {
1236 setHdcOwBlock(
1237 "aligned_load_block128",
1238 "oword aligned block read",
1239 SendOp::LOAD,
1240 32, // all 32b addresses
1241 MessageInfo::Attr::NONE);
1242 }
1243 setDoc(doc);
1244 decodeMDC_HR();
1245 }
1246
tryDecodeDC0Memfence()1247 void MessageDecoderHDC::tryDecodeDC0Memfence()
1248 {
1249 const int msgType = getDescBits(14, 5);
1250 // memory fence
1251 addField("MessageType", 14, 5, msgType, "fence");
1252 //
1253 std::stringstream sym, descs;
1254 uint32_t surfId = getDescBits(0, 8);
1255 MessageInfo::Attr extraAttrs = MessageInfo::Attr::NONE;
1256 if (decodeDescBitField("Commit", 13,
1257 "off (return immediately)",
1258 "on (wait for fence commit)"))
1259 {
1260 sym << "sync_";
1261 descs << "synchronized ";
1262 }
1263 if (surfId == SLM_BTI) {
1264 (void)decodeBTI(32); // add the field
1265 sym << "slm_fence";
1266 descs << "SLM fence";
1267 extraAttrs |= MessageInfo::Attr::SLM;
1268 } else if (surfId == 0) {
1269 sym << "global_fence";
1270 descs << "global fence";
1271 if (getDescBits(9, 4) && getDescBit(8)) {
1272 error(8, 1, "L3 implies L1 flush");
1273 }
1274 descs << " flushing";
1275 if (decodeDescBitField("L1Flush", 8, "Flush L3", "FLush L1") != 0) {
1276 sym << ".l1";
1277 descs << " L1";
1278 }
1279 if (decodeDescField("L3 Flush Targets", 9, 4)) {
1280 if (getDescBits(9, 4) == 0xF) {
1281 descs << " all L3 data";
1282 sym << ".dcti";// data, const?, text, inst
1283 } else {
1284 int n = 0;
1285 descs << " L3";
1286 sym << ".";
1287 if (getDescBit(12)) {
1288 sym << "d";
1289 descs << " r/w data";
1290 }
1291 if (getDescBit(11)) {
1292 if (n++ > 0)
1293 descs << ",";
1294 sym << "c";
1295 descs << " constant data";
1296 }
1297 if (getDescBit(10)) {
1298 if (n++ > 0)
1299 descs << ",";
1300 sym << "t";
1301 descs << " texture data";
1302 }
1303 if (getDescBit(9)) {
1304 if (n++ > 0)
1305 descs << ",";
1306 sym << "i";
1307 descs << " instruction data";
1308 }
1309 }
1310 }
1311 } else {
1312 error(0, 8, "invalid BTI for fence (must be 0x0 or 0xFE)");
1313 }
1314 setSpecialOpX(
1315 sym.str(),
1316 descs.str(),
1317 SendOp::FENCE,
1318 AddrType::FLAT,
1319 SendDesc(surfId),
1320 1,
1321 1,
1322 extraAttrs);
1323 setDoc("7049", "44768", nullptr);
1324 decodeMDC_HR();
1325 }
1326
tryDecodeDC0ScratchBlock()1327 void MessageDecoderHDC::tryDecodeDC0ScratchBlock()
1328 {
1329 const int msgType = getDescBits(14, 5);
1330 // scratch read
1331 // scratch write
1332 //
1333 // scratch block is a muddy situation
1334 // they used to have ChannelMode at 16, so we want to ignore that
1335 // and only use bits
1336 bool isRead = getDescBit(17) == 0;
1337 const char *msgName = isRead ?
1338 "hword scratch block read" : "hword scratch block write";
1339 addField("MessageType", 14, 5, msgType, msgName);
1340 //
1341 setHdcHwBlock(
1342 isRead ? "load_block" : "store_block",
1343 msgName,
1344 isRead ? SendOp::LOAD : SendOp::STORE,
1345 32, // r0.5
1346 12, 2, // [13:12] num HWs
1347 MessageInfo::Attr::SCRATCH);
1348 // scratch offset [11:0] (reg aligned)
1349 uint32_t hwOff = 32*
1350 decodeDescField("HWordOffset", 0, 12,
1351 [&] (std::stringstream &ss, uint32_t val) {
1352 ss << val << " HWords from scratch base";
1353 });
1354 result.info.immediateOffset = hwOff;
1355 if (platform() < Platform::GEN10) {
1356 decodeDescBitField("ChannelMode", 16, "OWord", "DWord");
1357 }
1358 setDoc(isRead ? "7027" : "7031", isRead ? "44724" : "44732", nullptr);
1359
1360 decodeMDC_HR();
1361 }
1362
1363 #if 0
1364 // experimental work in a table-based approach
1365
1366 struct Doc {
1367 Platform platform;
1368 const char *doc;
1369
1370 constexpr Doc() : Doc(Platform::INVALID, nullptr) { }
1371 constexpr Doc(const char *d) : Doc(Platform::GEN6, d) { }
1372 constexpr Doc(Platform p, const char *d) : platform(p), doc(d) { }
1373
1374 constexpr Doc(Doc &) = default;
1375 constexpr Doc(Doc &&) = default;
1376 constexpr Doc &operator=(const Doc &) = default;
1377 };
1378 static constexpr Doc INVALID_DOC;
1379
1380 struct AddrSize {
1381 enum class Ord {ORD_A16 = 1, ORD_A32, ORD_A64} ordinal;
1382 constexpr AddrSize(Ord o) : ordinal(o) { }
1383 constexpr int bits() const {return 8 << unsigned(ordinal);}
1384 // std::string symbol() {}
1385 // static AddrSize FromSyntax(std::string);
1386 };
1387 constexpr AddrSize A16(AddrSize::Ord::ORD_A16);
1388 constexpr AddrSize A32(AddrSize::Ord::ORD_A32);
1389 constexpr AddrSize A64(AddrSize::Ord::ORD_A64);
1390
1391 struct DataSize {
1392 int bitsInReg;
1393 int bitsInMem;
1394 // enum class ExtendFunction{NOP, ZEXT, SEXT} extend;
1395
1396 constexpr DataSize(int bRf, int bM) : bitsInReg(bRf), bitsInMem(bM) { }
1397 constexpr DataSize(int b) : DataSize(b, b) { }
1398 constexpr int bitsInRegisterFile() const {return bitsInReg;}
1399 constexpr int bitsInMemory() const {return bitsInMem;}
1400 };
1401 constexpr DataSize D8(8);
1402 constexpr DataSize D8U32(8, 32);
1403 constexpr DataSize D16U32(16, 32);
1404 constexpr DataSize D16(16);
1405 constexpr DataSize D32(32);
1406 constexpr DataSize D64(64);
1407
1408 struct DataFormat {
1409 enum class Order {NONTRANSPOSE = 0, TRANSPOSE = 1};
1410 enum class QuadMask {
1411 INVALID = 0,
1412 X = 1, Y = 2, Z = 4, W = 8,
1413 ///////////////////////////////////////////////
1414 // friendly combinations for debugger
1415 XY = X | Y, XZ = X | Z, XW = X | W,
1416 YZW = W | Z | W, YZ = Y | Z, YW = Y | W,
1417 };
1418
1419 Order dataOrder;
1420 DataSize dataSize;
1421 int dataElems = 0;
1422 QuadMask dataMask = QuadMask::INVALID; // only for load quad
1423
1424 constexpr DataFormat(Order ord, DataSize ds, int des = 1)
1425 : dataOrder(ord), dataSize(ds), dataElems(des) { }
1426 constexpr DataFormat(DataSize ds)
1427 : DataFormat(Order::NONTRANSPOSE, ds) { }
1428 constexpr DataFormat(DataSize ds, QuadMask qm)
1429 : DataFormat(Order::NONTRANSPOSE, ds), dataMask(qm),
1430 dataElems(
1431 (int(dataMask) & int(QuadMask::X) ? 1 : 0) +
1432 (int(dataMask) & int(QuadMask::Y) ? 1 : 0) +
1433 (int(dataMask) & int(QuadMask::Z) ? 1 : 0) +
1434 (int(dataMask) & int(QuadMask::W) ? 1 : 0))
1435 {
1436 }
1437
1438 constexpr int elems() const {return dataElems;}
1439 };
1440
1441
1442 struct Format {
1443 const char *description;
1444 const char *canonicalName;
1445 uint32_t encoding;
1446 uint32_t encodingMask;
1447
1448 SendOp op;
1449 AddrSize addrSize;
1450 DataFormat dataFormat;
1451
1452 int extraAttrs;
1453
1454 Doc docs[3];
1455
1456 constexpr Format(
1457 SendOp o,
1458 const char *desc,
1459 const char *canon,
1460 uint32_t enc, uint32_t encMask,
1461 DataFormat dFormat,
1462 AddrSize aSize,
1463 const Doc &d1 = INVALID_DOC,
1464 const Doc &d2 = INVALID_DOC,
1465 const Doc &d3 = INVALID_DOC)
1466 : op(o)
1467 , description(desc)
1468 , canonicalName(canon)
1469 , encoding(enc)
1470 , encodingMask(encMask)
1471 , dataBitsMemory(dSize)
1472 , dataBitsRegfile(dSize)
1473 , dataVectorSize(1)
1474 , addrBits(aSize)
1475 , extraAttrs(0)
1476 {
1477 docs[0] = d1;
1478 docs[1] = d2;
1479 docs[2] = d3;
1480 }
1481 };
1482
1483 static constexpr uint32_t DC1_OP_MASK = getFieldMask<uint32_t>(14, 4);
1484
1485 static constexpr Format DC1_OP(
1486 SendOp op,
1487 const char *desc,
1488 const char *canon,
1489 HDCOpcode enc,
1490 DataSize dSize,
1491 AddrSize aSize,
1492 const Doc &d1 = Doc(),
1493 const Doc &d2 = Doc())
1494 {
1495 return Format(mne, desc, canon, enc, DC1_OP_MASK, dSize, aSize, d1, d2);
1496 }
1497
1498 static constexpr uint32_t DC0_OP_MASK = getFieldMask<uint32_t>(14, 4);
1499
1500 static constexpr Format DC0_OP(
1501 SendOp op,
1502 const char *desc,
1503 const char *canon,
1504 HDCOpcode enc,
1505 DataSize dSize,
1506 AddrSize aSize,
1507 const Doc &d1 = Doc(),
1508 const Doc &d2 = Doc())
1509 {
1510 return Format(mne, desc, canon, enc, DC1_OP_MASK, dSize, aSize, d1, d2);
1511 }
1512
1513 // PROBLEM: how to actually decode all the desc fields...
1514 // (use smaller table groups and match on mask)
1515 static constexpr Format DC1_OPS[] {
1516 // must also decode cmask and BTI
1517 DC1_OP(SendOp::LOAD_QUAD, "untyped surface read", "MSD1R_US",
1518 0x01, D32, A32, "7088", "44747"),
1519 DC1_OP(SendOp::STORE_QUAD, "untyped surface write", "MSD1W_US",
1520 0x09, D32, A32, "7091", "44757"),
1521 DC1_OP(SendOp::LOAD_QUAD, "a64 untyped surface read", "MSD1R_A64_US",
1522 0x11, D32, A64, "7086", "44743"),
1523 DC1_OP(SendOp::STORE_QUAD, "a64 untyped surface write", "MSD1W_A64_US",
1524 0x19, D32, A64, "7089", "44754"),
1525 //
1526 // must also decode vector size and BTI
1527 DC1_OP(SendOp::LOAD, "a64 byte gathering read", "MSD1R_A64_BS",
1528 0x19, D8, A64, "7070"),
1529 DC1_OP(SendOp::STORE, "a64 byte scattering write", "MSD1W_A64_BS",
1530 0x1A, D8, A64, "7073"),
1531 };
1532 static constexpr Format DC0_OPS[] {
1533 DC0_OP(SendOp::LOAD, "byte gathering read", "MSD1R_BS",
1534 0x04, D8, A32, "7066", "44737"),
1535 DC0_OP(SendOp::STORE, "byte scattering write", "MSD1W_BS",
1536 0x0C, D8, A32, "7068", "44748"),
1537 //
1538 // bit [13:12] MBZ, [11:10]
1539 DC0_OP(SendOp::LOAD, "dword gathering read", "MSD0R_DWS",
1540 0x03, D32, A32, "7067", "44738"),
1541 DC0_OP(SendOp::STORE, "dword scattered write", "MSD0W_DWS",
1542 0x0B, D32, A32, "7069", "44749"),
1543 DC0_OP(SendOp::LOAD, "qword gathering read", "MSD0R_QWS",
1544 0x05, D64, A32, "33652", "44742"),
1545 DC0_OP(SendOp::STORE, "qword scattered write", "MSD0W_QWS",
1546 0x0D, D64, A32, "33653", "44753"),
1547 }
1548 #endif // end experimental work
1549
tryDecodeDC1()1550 void MessageDecoderHDC::tryDecodeDC1() {
1551 const int msgType = getDescBits(14, 5);
1552 switch (msgType)
1553 {
1554 case MSD1R_US: // untyped surface read
1555 case MSD1W_US: // untyped surface write
1556 {
1557 const char *msgName = msgType == MSD1R_US ?
1558 "untyped surface read" : "untyped surface write";
1559 addField("MessageType", 14, 5, msgType, msgName);
1560 //
1561 setHdcUntypedSurfaceMessage(
1562 msgName,
1563 msgType == MSD1R_US,
1564 32,
1565 MessageInfo::Attr::NONE);
1566 setDoc(
1567 msgType == MSD1R_US ? "7088" : "7091",
1568 msgType == MSD1R_US ? "44747" : "44757",
1569 nullptr);
1570 decodeMDC_H();
1571 break;
1572 }
1573 case MSD1R_A64_US: // a64 untype surface read
1574 case MSD1W_A64_US: // a64 untype surface write
1575 {
1576 const char *msgName = msgType == MSD1R_A64_US ?
1577 "a64 untyped surface read" : "a64 untyped surface write";
1578 addField("MessageType", 14, 5, msgType, msgName);
1579 //
1580 setHdcUntypedSurfaceMessage(
1581 msgName,
1582 msgType == MSD1R_A64_US,
1583 64, // 8B addrs
1584 MessageInfo::Attr::NONE);
1585 setDoc(
1586 msgType == MSD1R_A64_US ? "7086" : "7089",
1587 msgType == MSD1R_A64_US ? "44743" : "44754",
1588 nullptr);
1589 decodeMDC_HF();
1590 break;
1591 }
1592 case MSD1R_A64_BS: // a64 gathering read (byte/dw/qw)
1593 case MSD1W_A64_BS: // a64 scattered write (byte/dw/qw)
1594 {
1595 // 0 is byte-scattered, the others (DW/QW) are true SIMT
1596 int subType = getDescBits(8, 2);
1597 bool isRead = msgType == MSD1R_A64_BS;
1598 const auto BYTE_SUBTYPE = 0x0, BSRWSR_SUBTYPE = 0x3;
1599 if (subType == BYTE_SUBTYPE || subType == BSRWSR_SUBTYPE) {
1600 // c.f. handling above with non-A64 version of BSR
1601 const char *msgName = msgType == MSD1R_A64_BS ?
1602 "a64 byte gathering read" : "a64 byte scattering write";
1603 addField("MessageType", 14, 5, msgType, msgName);
1604 //
1605 if (subType == BYTE_SUBTYPE) {
1606 addField("SubType", 8, 2, subType, "Byte");
1607 setDoc(
1608 msgType == MSD1R_A64_BS ? "7070" : "7073",
1609 msgType == MSD1R_A64_BS ? "44737" : "44748",
1610 nullptr);
1611 } else { // subType == 0x3
1612 addField("SubType", 8, 2, subType, "Byte with Status Return");
1613 setDoc(msgType == MSD1R_A64_BS ? "19316" : nullptr);
1614 if (msgType == MSD1W_A64_BS)
1615 error(14, 5,
1616 "a64 byte scattering with status return message");
1617 }
1618 //
1619 std::stringstream descs;
1620 descs << msgName;
1621 int bExt = MDC_A64_DS(10);
1622 if (bExt == 1)
1623 descs << " 8b";
1624 else if (bExt == 2)
1625 descs << " 16b";
1626 else if (bExt == 4)
1627 descs << " 32b";
1628 //
1629 setHdcMessageX(
1630 isRead ? "load" : "store",
1631 descs.str(),
1632 isRead ? SendOp::LOAD : SendOp::STORE,
1633 64, // A64
1634 32, // widens to DW (similar to non-A64 version)
1635 8*bExt, // bits from memory
1636 1, //
1637 decodeMDC_SM2(12),
1638 MessageInfo::Attr::NONE);
1639 } else {
1640 const auto DW_SUBTYPE = 0x1;
1641 const auto QW_SUBTYPE = 0x2;
1642 bool isDword = subType == DW_SUBTYPE; // else QW
1643 // unlike non-A64 version, this variant supports DW and QW
1644 // in the same message type, the MDC_A64_DS is treated as a
1645 // vector length
1646 const char *msgTypeName = msgType == MSD1R_A64_BS ?
1647 "a64 gathering read" : "a64 scattering write";
1648 addField("MessageType", 14, 5, msgType, msgTypeName);
1649 //
1650 const char *msgName =
1651 isDword ?
1652 (isRead ?
1653 "a64 dword gathering read" :
1654 "a64 dword scattering write") :
1655 (isRead ?
1656 "a64 qword gathering read" :
1657 "a64 qword scattering write");
1658 //
1659 int elemsPerAddr = decodeMDC_DWS_DS(10);
1660 std::stringstream ss;
1661 if (elemsPerAddr != 1)
1662 ss << msgName << " x" << elemsPerAddr;
1663 //
1664 addField(
1665 "SubType", 8, 2, subType, subType == 1 ? "DWord" : "QWord");
1666 //
1667 setHdcMessage(
1668 isRead ? "load" : "store",
1669 msgName,
1670 isRead ? SendOp::LOAD : SendOp::STORE,
1671 64,
1672 isDword ? 32 : 64,
1673 elemsPerAddr, // true vector
1674 decodeMDC_SM2(12),
1675 MessageInfo::Attr::NONE);
1676 if (isDword) {
1677 setDoc(
1678 isRead ? "7071" : "7074",
1679 isRead ? "44738" : "44749",
1680 nullptr);
1681 } else {
1682 setDoc(isRead ? "7072" : "7075");
1683 }
1684 }
1685 result.info.cachingL3 = decodeMDC_IAR();
1686 decodeMDC_HF();
1687 break;
1688 }
1689 case MSD1R_A64_HWB: // a64 [un]aligned (hword|oword) block read
1690 case MSD1W_A64_HWB: // a64 [un]aligned (hword|oword) block write
1691 {
1692 bool isRead = msgType == MSD1R_A64_HWB;
1693
1694 addField("MessageType", 14, 5, msgType,
1695 isRead ? "a64 block read" :"a64 block write");
1696 bool isHword = false;
1697 bool isUnaligned = false;
1698 auto subType = decodeDescField("SubType", 11, 2,
1699 [&] (std::stringstream &ss, uint32_t val) {
1700 switch (val) {
1701 case 0x0:
1702 isUnaligned = true;
1703 ss << "oword unaligned";
1704 break;
1705 case 0x1:
1706 ss << "oword aligned";
1707 break;
1708 case 0x3:
1709 isHword = true;
1710 isUnaligned = true;
1711 ss << "hword unaligned";
1712 break;
1713 //
1714 default:
1715 ss << "dual block";
1716 isUnaligned = true;
1717 error(11, 2, "a64 dual block read/write unsupported");
1718 break;
1719 }
1720 });
1721
1722 if (isHword && isUnaligned)
1723 setDoc(
1724 isRead ? "7034" : "7038", isRead ? "44739" : "44750", nullptr);
1725 else if (isHword && !isUnaligned) {
1726 bool supported = platform() >= Platform::XE_HPG;
1727 setDoc(isRead ? "20861" : "20862");
1728 if (!supported)
1729 error(11, 2, "HWord aligned unsupported on this platform");
1730 } else if (!isHword && isUnaligned) {
1731 setDoc(
1732 isRead ? "7037" : "33440",
1733 isRead ? "44740" : "44751",
1734 nullptr); // MSD1R_A64_OWAB|MSD1W_A64_OWAB
1735 } else if (!isHword && !isUnaligned) {
1736 setDoc(
1737 isRead ? "7039" : "7039",
1738 isRead ? "44741" : "44752",
1739 nullptr); // MSD1R_A64_OWB|MSD1W_A64_OWB
1740 } else if (subType == 2) {
1741 setDoc(isRead ? "7036" : "7040");
1742 result.info.description = "a64 dual block ";
1743 result.info.description += (isRead ? " read" : " write");
1744 result.info.symbol =
1745 isRead ? "MSD1R_A64_OWDB" : "MSD1W_A64_OWDB";
1746 result.info.addrSizeBits = 64;
1747 decodeMDC_HR();
1748 break; // dual block (error)
1749 }
1750 //
1751 std::string msgSym = isRead ? "load_block" : "store_block";
1752 std::string msgDesc = "a64";
1753 if (isUnaligned) {
1754 msgDesc += " unaligned";
1755 } else {
1756 msgDesc += " aligned";
1757 msgSym += "_aligned";
1758 }
1759 if (isHword) {
1760 msgDesc += " hword";
1761 } else {
1762 msgDesc += " oword";
1763 }
1764 msgDesc += " block";
1765 if (msgType == 0x14) {
1766 msgDesc += " read";
1767 } else {
1768 msgDesc += " write";
1769 }
1770 if (isHword) {
1771 setHdcHwBlock(
1772 msgSym,
1773 msgDesc,
1774 isRead ? SendOp::LOAD : SendOp::STORE,
1775 64, // 64b addr
1776 8, 3, // offset of HWs
1777 MessageInfo::Attr::NONE);
1778 } else {
1779 setHdcOwBlock(
1780 msgSym,
1781 msgDesc,
1782 isRead ? SendOp::LOAD : SendOp::STORE,
1783 64, // 64b addr
1784 MessageInfo::Attr::NONE);
1785 }
1786 result.info.cachingL3 = decodeMDC_IAR();
1787 decodeMDC_HR(); // all block require a header
1788 break;
1789 }
1790 case MSD1W_A64_DWAF: // a64 untyped fp32 atomic
1791 setHdcFloatAtomicMessage(
1792 "a64 float atomic",
1793 64,
1794 32,
1795 "7126", "7118",
1796 "44682", "44649");
1797 decodeMDC_HF();
1798 break;
1799
1800 case MSD1W_DWAF: // a32 untyped fp32 atomic
1801 setHdcFloatAtomicMessage(
1802 "float atomic",
1803 32,
1804 32,
1805 "7130", "7122",
1806 "44697", "44664");
1807 decodeMDC_H();
1808 break;
1809 case MSD1W_A64_AI: // a64 untyped atomic int{32,64}
1810 {
1811 // the encoding repurposes the SIMD size as the data size and the
1812 // message and thus the SIMD size is always fixed
1813 int simd = platform() >= Platform::XE_HPC ? 16 : 8;
1814 auto is64b =
1815 decodeDescBitField("DataWidth", 12, "32b", "64b");
1816 const char *msgName = is64b ?
1817 "a64 atomic int64" : "a64 atomic int32";
1818 const char *docNoRet = is64b ? "7161" : "7155";
1819 const char *docNoRetXe = is64b ? "44688" : "44685";
1820 const char *docWiRet = is64b ? "7143" : "7137";
1821 const char *docWiRetXe = is64b ? "44655" : "44652";
1822 //
1823 setHdcIntAtomicMessage(
1824 "untyped",
1825 msgName,
1826 64,
1827 is64b ? 64 : 32,
1828 simd,
1829 docNoRet, docWiRet,
1830 docNoRetXe, docWiRetXe);
1831 decodeMDC_HF();
1832 break;
1833 }
1834 case MSD1W_DWAI: // atomic int32
1835 {
1836 const char *msgName = "untyped atomic int32";
1837 addField("MessageType", 14, 5, msgType, msgName);
1838 //
1839 setHdcIntAtomicMessage(
1840 "untyped",
1841 "atomic int32",
1842 32,
1843 32,
1844 decodeMDC_SM2R(12),
1845 "7167", "7149",
1846 "44700", "44667");
1847 decodeMDC_H();
1848 break;
1849 }
1850 case MSD1R_MB: // media block read
1851 case MSD1W_MB: // media block write
1852 {
1853 std::stringstream sym, descs;
1854 sym << "mb";
1855 descs << "media block ";
1856 int bytesTransmitted = 0;
1857 if (msgType == MSD1R_MB) {
1858 descs << "read";
1859 sym << "rd";
1860 bytesTransmitted = 2*DEFAULT_EXEC_SIZE*getDescBits(20,5);
1861 } else {
1862 descs << "write";
1863 sym << "wr";
1864 int mlen = getDescBits(25, 4);
1865 if (mlen == 0) {
1866 error(25, 4, "mlen == 0 on write");
1867 } else {
1868 bytesTransmitted = 2*DEFAULT_EXEC_SIZE*(mlen - 1);
1869 }
1870 }
1871 int vlso = getDescBits(8, 3); // [10:8] is vert. line stride overr.
1872 if (vlso) {
1873 descs << " with vertical line stride ";
1874 int n = 0;
1875 if (vlso & 0x2) {
1876 descs << "override";
1877 n++;
1878 }
1879 if (vlso & 0x1) {
1880 if ((vlso & 0x2) == 0)
1881 descs << " and ";
1882 else if (n > 0)
1883 descs << ",";
1884 descs << "skip";
1885 n++;
1886 }
1887 if (vlso & 0x2) {
1888 if (n >= 2)
1889 descs << ", and ";
1890 else if (n > 0)
1891 descs << " and ";
1892 descs << "offset";
1893 n++;
1894 if ((vlso & 0) == 0) {
1895 warning(8, 3,
1896 "stride offset meaningless when override not set");
1897 }
1898 }
1899 }
1900 setHdcMessage(sym.str(), descs.str(),
1901 msgType == 0x4 ? SendOp::LOAD : SendOp::STORE,
1902 32, 8, bytesTransmitted, 1,
1903 MessageInfo::Attr::TRANSPOSED);
1904 setDoc(
1905 msgType == MSD1R_MB ? "7046" : "7048",
1906 msgType == MSD1R_MB ? "44744" : "44755",
1907 nullptr);
1908 decodeMDC_HR();
1909 break;
1910 }
1911 case MSD1R_TS: // typed surface read
1912 setHdcTypedSurfaceMessage(true, "7087", "44745");
1913 decodeMDC_H();
1914 break;
1915 case MSD1W_TS: // typed surface write
1916 setHdcTypedSurfaceMessage(false, "7090", "44756");
1917 decodeMDC_H();
1918 break;
1919 case MSD1RS_TS: // typed surface read with status
1920 setHdcTypedSurfaceMessage(true, "19315", "44735", true);
1921 decodeMDC_H();
1922 break;
1923 case MSD1A_DWAC:
1924 setHdcIntAtomicMessage(
1925 "typed",
1926 "atomic 32-bit counter",
1927 32, // addrSize
1928 32, // dataSize
1929 decodeMDC_SM2R(12),
1930 "7109", "7099",
1931 "44696", "44663");
1932 decodeMDC_HR();
1933 result.info.attributeSet |= MessageInfo::Attr::HAS_UVRLOD;
1934 break;
1935 case MSD1A_DWTAI:
1936 {
1937 bool sgh = decodeMDC_SG2();
1938 setHdcIntAtomicMessage(
1939 sgh ? "typed_sgh" : "typed" ,
1940 sgh ?
1941 "atomic 32-bit integer (slot group high)" :
1942 "atomic 32-bit integer",
1943 32, // addrSize
1944 32, // dataSize
1945 DEFAULT_EXEC_SIZE / 2,
1946 "7113", "7103",
1947 "44703","44670");
1948 decodeMDC_H();
1949 break;
1950 }
1951 case MSD1A_WAC:
1952 setHdcIntAtomicMessage(
1953 "typed",
1954 "atomic 16-bit counter",
1955 32, // addrSize
1956 16, // dataSize
1957 decodeMDC_SM2R(12),
1958 "21412","21411",
1959 "44706", "44673");
1960 decodeMDC_HR();
1961 result.info.attributeSet |= MessageInfo::Attr::HAS_UVRLOD;
1962 break;
1963 case MSD1A_WTAI:
1964 {
1965 bool sgh = decodeMDC_SG2();
1966 setHdcIntAtomicMessage(
1967 sgh ?
1968 "typed_sgh" :
1969 "typed",
1970 sgh ?
1971 "atomic 16-bit integer (slot group high)" :
1972 "atomic 16-bit integer",
1973 32, // addrSize
1974 16, // dataSize
1975 DEFAULT_EXEC_SIZE / 2,
1976 "21416", "21415",
1977 "44703", "44670");
1978 decodeMDC_H();
1979 result.info.attributeSet |= MessageInfo::Attr::HAS_UVRLOD;
1980 break;
1981 }
1982 case MSD1A_A64_WAF: // a64 fp16 atomic
1983 case MSD1A_WAF: // fp16 atomic
1984 {
1985 if (platform() <= Platform::GEN11) {
1986 // these used to be SIMD4x2
1987 error(14, 5, "SIMD4x2 atomic float decode unsupported");
1988 return;
1989 }
1990 bool isA64 = msgType == MSD1A_A64_WAF;
1991 setHdcFloatAtomicMessage(
1992 isA64 ?
1993 "a64 untyped half-float atomic" : "untyped half-float atomic",
1994 isA64 ? 64 : 32,
1995 16,
1996 isA64 ? "21405" : "21407", isA64 ? "21404" : "21406",
1997 isA64 ? "44690" : "54102", isA64 ? "44657" : "54101");
1998 if (isA64)
1999 decodeMDC_HF();
2000 else
2001 decodeMDC_H();
2002 break;
2003 }
2004 case MSD1A_A64_WAI: // a64 int16 atomic
2005 case MSD1A_WAI: // int16 atomic
2006 {
2007 if (platform() <= Platform::GEN11) {
2008 // these used to be SIMD4x2
2009 error(14, 5, "SIMD4x2 atomic int decode unsupported");
2010 return;
2011 }
2012 bool isA64 = msgType == MSD1A_A64_WAI;
2013 setHdcIntAtomicMessage(
2014 "untyped",
2015 isA64 ? "a64 atomic int16" : "atomic int16",
2016 msgType == MSD1A_A64_WAI ? 64 : 32,
2017 16,
2018 decodeMDC_SM2R(12),
2019 isA64 ? "21390" : "21396", isA64 ? "21389" : "21397",
2020 isA64 ? "44693" : "44710", isA64 ? "44660" : "44677");
2021 if (isA64)
2022 decodeMDC_HF();
2023 else
2024 decodeMDC_H();
2025 break;
2026 }
2027 default:
2028 error(14, 5, "unsupported DC1 op");
2029 return;
2030 } // DC1 switch
2031 }
2032
2033
decodeDescriptorsHDC(Platform platform,SFID sfid,ExecSize execSize,SendDesc exDesc,SendDesc desc,DecodeResult & result)2034 void iga::decodeDescriptorsHDC(
2035 Platform platform, SFID sfid, ExecSize execSize,
2036 SendDesc exDesc, SendDesc desc,
2037 DecodeResult &result)
2038 {
2039 MessageDecoderHDC mdo(
2040 platform, sfid, execSize,
2041 exDesc, desc, result);
2042 mdo.tryDecode();
2043 }
2044
2045