gem5 v23.0.0.1
Loading...
Searching...
No Matches
op_encodings.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016-2021 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
33
34#include <iomanip>
35
36namespace gem5
37{
38
39namespace Gcn3ISA
40{
41 // --- Inst_SOP2 base class methods ---
42
43 Inst_SOP2::Inst_SOP2(InFmt_SOP2 *iFmt, const std::string &opcode)
45 {
47
48 // copy first instruction DWORD
49 instData = iFmt[0];
50 if (hasSecondDword(iFmt)) {
51 // copy second instruction DWORD into union
52 extData = ((MachInst)iFmt)[1];
53 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
54 varSize = 4 + 4;
55 } else {
56 varSize = 4;
57 } // if
58 } // Inst_SOP2
59
60 void
62 {
63 int opNum = 0;
64
65 // Needed because can't take addr of bitfield
66 int reg = instData.SSRC0;
67 srcOps.emplace_back(reg, getOperandSize(opNum), true,
68 isScalarReg(instData.SSRC0), false, false);
69 opNum++;
70
72 srcOps.emplace_back(reg, getOperandSize(opNum), true,
73 isScalarReg(instData.SSRC1), false, false);
74 opNum++;
75
77 dstOps.emplace_back(reg, getOperandSize(opNum), false,
78 isScalarReg(instData.SDST), false, false);
79
80 assert(srcOps.size() == numSrcRegOperands());
81 assert(dstOps.size() == numDstRegOperands());
82 }
83
84 int
86 {
87 return varSize;
88 } // instSize
89
90 bool
92 {
93 if (iFmt->SSRC0 == REG_SRC_LITERAL)
94 return true;
95
96 if (iFmt->SSRC1 == REG_SRC_LITERAL)
97 return true;
98
99 return false;
100 }
101
102 void
104 {
105 std::stringstream dis_stream;
106 dis_stream << _opcode << " ";
107 dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
108
110 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
111 << _srcLiteral << ", ";
112 } else {
113 dis_stream << opSelectorToRegSym(instData.SSRC0) << ", ";
114 }
115
117 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
118 << _srcLiteral;
119 } else {
120 dis_stream << opSelectorToRegSym(instData.SSRC1);
121 }
122
123 disassembly = dis_stream.str();
124 }
125
126 // --- Inst_SOPK base class methods ---
127
128 Inst_SOPK::Inst_SOPK(InFmt_SOPK *iFmt, const std::string &opcode)
130 {
132
133 // copy first instruction DWORD
134 instData = iFmt[0];
135 if (hasSecondDword(iFmt)) {
136 // copy second instruction DWORD into union
137 extData = ((MachInst)iFmt)[1];
138 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
139 varSize = 4 + 4;
140 } else {
141 varSize = 4;
142 } // if
143 } // Inst_SOPK
144
146 {
147 } // ~Inst_SOPK
148
149 void
151 {
152 int opNum = 0;
153
154 // Needed because can't take addr of bitfield
155 int reg = instData.SDST;
157 srcOps.emplace_back(reg, getOperandSize(opNum), true,
158 isScalarReg(reg), false, false);
159 opNum++;
160 }
161
163 srcOps.emplace_back(reg, getOperandSize(opNum), true,
164 false, false, true);
165 opNum++;
166
167 if (numDstRegOperands()){
168 reg = instData.SDST;
169 dstOps.emplace_back(reg, getOperandSize(opNum), false,
170 isScalarReg(reg), false, false);
171 }
172
173 assert(srcOps.size() == numSrcRegOperands());
174 assert(dstOps.size() == numDstRegOperands());
175 }
176
177 int
179 {
180 return varSize;
181 } // instSize
182
183 bool
185 {
186 /*
187 SOPK can be a 64-bit instruction, i.e., have a second dword:
188 S_SETREG_IMM32_B32 writes some or all of the LSBs of a 32-bit
189 literal constant into a hardware register;
190 the way to detect such special case is to explicitly check the
191 opcode (20/0x14)
192 */
193 if (iFmt->OP == 0x14)
194 return true;
195
196 return false;
197 }
198
199
200 void
202 {
203 std::stringstream dis_stream;
204 dis_stream << _opcode << " ";
205
206 // S_SETREG_IMM32_B32 is a 64-bit instruction, using a
207 // 32-bit literal constant
208 if (instData.OP == 0x14) {
209 dis_stream << "0x" << std::hex << std::setfill('0')
210 << std::setw(8) << extData.imm_u32 << ", ";
211 } else {
212 dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
213 }
214
215 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(4)
216 << instData.SIMM16;
217
218 disassembly = dis_stream.str();
219 }
220
221 // --- Inst_SOP1 base class methods ---
222
223 Inst_SOP1::Inst_SOP1(InFmt_SOP1 *iFmt, const std::string &opcode)
225 {
227
228 // copy first instruction DWORD
229 instData = iFmt[0];
230 if (hasSecondDword(iFmt)) {
231 // copy second instruction DWORD into union
232 extData = ((MachInst)iFmt)[1];
233 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
234 varSize = 4 + 4;
235 } else {
236 varSize = 4;
237 } // if
238 } // Inst_SOP1
239
241 {
242 } // ~Inst_SOP1
243
244 void
246 {
247 int opNum = 0;
248
249 // Needed because can't take addr of bitfield
250 int reg = instData.SSRC0;
251 if (instData.OP != 0x1C) {
252 srcOps.emplace_back(reg, getOperandSize(opNum), true,
253 isScalarReg(instData.SSRC0), false, false);
254 opNum++;
255 }
256
257 reg = instData.SDST;
258 dstOps.emplace_back(reg, getOperandSize(opNum), false,
259 isScalarReg(instData.SDST), false, false);
260
261 assert(srcOps.size() == numSrcRegOperands());
262 assert(dstOps.size() == numDstRegOperands());
263 }
264
265 int
267 {
268 return varSize;
269 } // instSize
270
271 bool
273 {
274 if (iFmt->SSRC0 == REG_SRC_LITERAL)
275 return true;
276
277 return false;
278 }
279
280 void
282 {
283 std::stringstream dis_stream;
284 dis_stream << _opcode << " ";
285 dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
286
288 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
289 << extData.imm_u32;
290 } else {
291 dis_stream << opSelectorToRegSym(instData.SSRC0);
292 }
293
294 disassembly = dis_stream.str();
295 }
296
297 // --- Inst_SOPC base class methods ---
298
299 Inst_SOPC::Inst_SOPC(InFmt_SOPC *iFmt, const std::string &opcode)
301 {
303
304 // copy first instruction DWORD
305 instData = iFmt[0];
306 if (hasSecondDword(iFmt)) {
307 // copy second instruction DWORD into union
308 extData = ((MachInst)iFmt)[1];
309 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
310 varSize = 4 + 4;
311 } else {
312 varSize = 4;
313 } // if
314 } // Inst_SOPC
315
317 {
318 } // ~Inst_SOPC
319
320 void
322 {
323 int opNum = 0;
324
325 // Needed because can't take addr of bitfield
326 int reg = instData.SSRC0;
327 srcOps.emplace_back(reg, getOperandSize(opNum), true,
328 isScalarReg(instData.SSRC0), false, false);
329 opNum++;
330
332 srcOps.emplace_back(reg, getOperandSize(opNum), true,
333 isScalarReg(instData.SSRC1), false, false);
334
335 }
336
337 int
339 {
340 return varSize;
341 } // instSize
342
343 bool
345 {
346 if (iFmt->SSRC0 == REG_SRC_LITERAL)
347 return true;
348
349 if (iFmt->SSRC1 == REG_SRC_LITERAL)
350 return true;
351
352 return false;
353 }
354
355 void
357 {
358 std::stringstream dis_stream;
359 dis_stream << _opcode << " ";
360
362 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
363 << extData.imm_u32;
364 } else {
365 dis_stream << opSelectorToRegSym(instData.SSRC0) << ", ";
366 }
367
369 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
370 << extData.imm_u32;
371 } else {
372 dis_stream << opSelectorToRegSym(instData.SSRC1);
373 }
374
375 disassembly = dis_stream.str();
376 }
377
378 // --- Inst_SOPP base class methods ---
379
380 Inst_SOPP::Inst_SOPP(InFmt_SOPP *iFmt, const std::string &opcode)
382 {
384
385 // copy first instruction DWORD
386 instData = iFmt[0];
387 } // Inst_SOPP
388
390 {
391 } // ~Inst_SOPP
392
393 void
395 {
396 int opNum = 0;
397
398
399 if (numSrcRegOperands()) {
400 // Needed because can't take addr of bitfield
401 int reg = instData.SIMM16;
402 srcOps.emplace_back(reg, getOperandSize(opNum), true,
403 false, false, true);
404
405 opNum++;
406
407 if (readsVCC()) {
408 srcOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), true,
409 true, false, false);
410 opNum++;
411 }
412 }
413 assert(srcOps.size() == numSrcRegOperands());
414 assert(dstOps.size() == numDstRegOperands());
415 }
416
417 int
419 {
420 return 4;
421 } // instSize
422
423 void
425 {
426 std::stringstream dis_stream;
427 dis_stream << _opcode;
428
429 switch (instData.OP) {
430 case 8:
431 {
432 dis_stream << " ";
433 int dest = 4 * instData.SIMM16 + 4;
434 dis_stream << "label_" << std::hex << dest;
435 }
436 break;
437 case 12:
438 {
439 dis_stream << " ";
440
441 int vm_cnt = 0;
442 int exp_cnt = 0;
443 int lgkm_cnt = 0;
444
445 vm_cnt = bits<uint16_t>(instData.SIMM16, 3, 0);
446 exp_cnt = bits<uint16_t>(instData.SIMM16, 6, 4);
447 lgkm_cnt = bits<uint16_t>(instData.SIMM16, 11, 8);
448
449 // if the counts are not maxed out, then we
450 // print out the count value
451 if (vm_cnt != 0xf) {
452 dis_stream << "vmcnt(" << vm_cnt << ")";
453 }
454
455 if (lgkm_cnt != 0xf) {
456 if (vm_cnt != 0xf)
457 dis_stream << " & ";
458
459 dis_stream << "lgkmcnt(" << lgkm_cnt << ")";
460 }
461
462 if (exp_cnt != 0x7) {
463 if (vm_cnt != 0xf || lgkm_cnt != 0xf)
464 dis_stream << " & ";
465
466 dis_stream << "expcnt(" << exp_cnt << ")";
467 }
468 }
469 break;
470 default:
471 break;
472 }
473
474 disassembly = dis_stream.str();
475 }
476
477 // --- Inst_SMEM base class methods ---
478
479 Inst_SMEM::Inst_SMEM(InFmt_SMEM *iFmt, const std::string &opcode)
481 {
483 setFlag(GlobalSegment);
484
485 // copy first instruction DWORD
486 instData = iFmt[0];
487 // copy second instruction DWORD
488 extData = ((InFmt_SMEM_1 *)iFmt)[1];
489 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
490
491 if (instData.GLC)
492 setFlag(GloballyCoherent);
493 } // Inst_SMEM
494
496 {
497 } // ~Inst_SMEM
498
499 void
501 {
502 // Formats:
503 // 0 src + 0 dst
504 // 3 src + 0 dst
505 // 2 src + 1 dst
506 // 0 src + 1 dst
507 int opNum = 0;
508 // Needed because can't take addr of bitfield
509 int reg = 0;
510
511 if (numSrcRegOperands()) {
514 srcOps.emplace_back(reg, getOperandSize(opNum), true,
515 isScalarReg(reg), false, false);
516 opNum++;
517 }
518
520 srcOps.emplace_back(reg, getOperandSize(opNum), true,
521 true, false, false);
522 opNum++;
523
525 if (instData.IMM) {
526 srcOps.emplace_back(reg, getOperandSize(opNum), true,
527 false, false, true);
528 } else {
529 srcOps.emplace_back(reg, getOperandSize(opNum), true,
530 isScalarReg(reg), false, false);
531 }
532 opNum++;
533 }
534
535 if (numDstRegOperands()) {
537 dstOps.emplace_back(reg, getOperandSize(opNum), false,
538 isScalarReg(reg), false, false);
539 }
540
541 assert(srcOps.size() == numSrcRegOperands());
542 assert(dstOps.size() == numDstRegOperands());
543 }
544
545 int
547 {
548 return 8;
549 } // instSize
550
551 void
553 {
554 std::stringstream dis_stream;
555 dis_stream << _opcode << " ";
556 if (numDstRegOperands()) {
557 if (getOperandSize(getNumOperands() - 1) > 4) {
558 dis_stream << "s[" << instData.SDATA << ":"
560 4 - 1 << "], ";
561 } else {
562 dis_stream << "s" << instData.SDATA << ", ";
563 }
564 }
565
566 // SBASE has an implied LSB of 0, so we need
567 // to shift by one to get the actual value
568 dis_stream << "s[" << (instData.SBASE << 1) << ":"
569 << ((instData.SBASE << 1) + 1) << "], ";
570
571 if (instData.IMM) {
572 // IMM == 1 implies OFFSET should be
573 // used as the offset
574 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(2)
575 << extData.OFFSET;
576 } else {
577 // IMM == 0 implies OFFSET should be
578 // used to specify SGRP in which the
579 // offset is held
580 dis_stream << "s" << extData.OFFSET;
581 }
582
583 disassembly = dis_stream.str();
584 }
585
586 // --- Inst_VOP2 base class methods ---
587
588 Inst_VOP2::Inst_VOP2(InFmt_VOP2 *iFmt, const std::string &opcode)
590 {
591 // copy first instruction DWORD
592 instData = iFmt[0];
593 if (hasSecondDword(iFmt)) {
594 // copy second instruction DWORD into union
595 extData = ((MachInst)iFmt)[1];
596 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
597 varSize = 4 + 4;
598 if (iFmt->SRC0 == REG_SRC_DPP) {
599 setFlag(IsDPP);
600 } else if (iFmt->SRC0 == REG_SRC_SWDA) {
601 setFlag(IsSDWA);
602 }
603 } else {
604 varSize = 4;
605 } // if
606 } // Inst_VOP2
607
609 {
610 } // ~Inst_VOP2
611
612 void
614 {
615 int opNum = 0;
616
617 // Needed because can't take addr of bitfield
618 int reg = instData.SRC0;
619 srcOps.emplace_back(reg, getOperandSize(opNum), true,
620 isScalarReg(reg), isVectorReg(reg), false);
621 opNum++;
622
624 srcOps.emplace_back(reg, getOperandSize(opNum), true,
625 false, true, false);
626 opNum++;
627
628 // VCC read
629 if (readsVCC()) {
630 srcOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), true,
631 true, false, false);
632 opNum++;
633 }
634
635 // VDST
636 reg = instData.VDST;
637 dstOps.emplace_back(reg, getOperandSize(opNum), false,
638 false, true, false);
639 opNum++;
640
641 // VCC write
642 if (writesVCC()) {
643 dstOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), false,
644 true, false, false);
645 }
646
647 assert(srcOps.size() == numSrcRegOperands());
648 assert(dstOps.size() == numDstRegOperands());
649 }
650
651 int
653 {
654 return varSize;
655 } // instSize
656
657 bool
659 {
660 /*
661 There are a few cases where VOP2 instructions have a second dword:
662
663 1. SRC0 is a literal
664 2. SRC0 is being used to add a data parallel primitive (DPP)
665 operation to the instruction.
666 3. SRC0 is being used for sub d-word addressing (SDWA) of the
667 operands in the instruction.
668 4. VOP2 instructions also have four special opcodes:',
669 V_MADMK_{F16, F32} (0x24, 0x17), and V_MADAK_{F16, F32}',
670 (0x25, 0x18), that are always 64b. the only way to',
671 detect these special cases is to explicitly check,',
672 the opcodes',
673 */
674 if (iFmt->SRC0 == REG_SRC_LITERAL || (iFmt->SRC0 == REG_SRC_DPP) ||
675 (iFmt->SRC0 == REG_SRC_SWDA) || iFmt->OP == 0x17 ||
676 iFmt->OP == 0x18 || iFmt->OP == 0x24 || iFmt->OP == 0x25)
677 return true;
678
679 return false;
680 }
681
682 void
684 {
685 std::stringstream dis_stream;
686 dis_stream << _opcode << " ";
687 dis_stream << "v" << instData.VDST << ", ";
688
689 if (writesVCC())
690 dis_stream << "vcc, ";
691
692 if ((instData.SRC0 == REG_SRC_LITERAL) ||
695 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
696 << _srcLiteral << ", ";
697 } else {
698 dis_stream << opSelectorToRegSym(instData.SRC0) << ", ";
699 }
700
701 // VOP2 instructions have four special opcodes:',
702 // V_MADMK_{F16, F32} (0x24, 0x17), and V_MADAK_{F16, F32}',
703 // (0x25, 0x18), that are always 64b. the only way to',
704 // detect these special cases is to explicitly check,',
705 // the opcodes',
706 if (instData.OP == 0x17 || instData.OP == 0x18 || instData.OP == 0x24
707 || instData.OP == 0x25) {
708 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
709 << extData.imm_u32 << ", ";
710 }
711
712 dis_stream << std::resetiosflags(std::ios_base::basefield) << "v"
713 << instData.VSRC1;
714
715 if (readsVCC())
716 dis_stream << ", vcc";
717
718 disassembly = dis_stream.str();
719 }
720
721 // --- Inst_VOP1 base class methods ---
722
723 Inst_VOP1::Inst_VOP1(InFmt_VOP1 *iFmt, const std::string &opcode)
725 {
726 // copy first instruction DWORD
727 instData = iFmt[0];
728 if (hasSecondDword(iFmt)) {
729 // copy second instruction DWORD into union
730 extData = ((MachInst)iFmt)[1];
731 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
732 varSize = 4 + 4;
733 if (iFmt->SRC0 == REG_SRC_DPP) {
734 setFlag(IsDPP);
735 } else if (iFmt->SRC0 == REG_SRC_SWDA) {
736 setFlag(IsSDWA);
737 }
738 } else {
739 varSize = 4;
740 } // if
741 } // Inst_VOP1
742
744 {
745 } // ~Inst_VOP1
746
747 void
749 {
750 int opNum = 0;
751 // Needed because can't take addr of bitfield
752 int reg = instData.SRC0;
753
754 if (numSrcRegOperands()) {
755 srcOps.emplace_back(reg, getOperandSize(opNum), true,
756 isScalarReg(reg), isVectorReg(reg), false);
757 opNum++;
758 }
759
760 if (numDstRegOperands()) {
761 reg = instData.VDST;
762 dstOps.emplace_back(reg, getOperandSize(opNum), false,
763 false, true, false);
764 }
765
766 assert(srcOps.size() == numSrcRegOperands());
767 assert(dstOps.size() == numDstRegOperands());
768 }
769
770 int
772 {
773 return varSize;
774 } // instSize
775
776 bool
778 {
779 /*
780 There are several cases where VOP1 instructions have a second dword:
781
782 1. SRC0 is a literal.
783 2. SRC0 is being used to add a data parallel primitive (DPP)
784 operation to the instruction.
785 3. SRC0 is being used for sub d-word addressing (SDWA) of the
786 operands in the instruction.
787 */
788 if ((iFmt->SRC0 == REG_SRC_LITERAL) || (iFmt->SRC0 == REG_SRC_DPP) ||
789 (iFmt->SRC0 == REG_SRC_SWDA))
790 return true;
791
792 return false;
793 }
794
795 void
797 {
798 std::stringstream dis_stream;
799 dis_stream << _opcode << " ";
800 dis_stream << "v" << instData.VDST << ", ";
801
802 if ((instData.SRC0 == REG_SRC_LITERAL) ||
805 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
806 << _srcLiteral;
807 } else {
808 dis_stream << opSelectorToRegSym(instData.SRC0);
809 }
810
811 disassembly = dis_stream.str();
812 }
813
814 // --- Inst_VOPC base class methods ---
815
816 Inst_VOPC::Inst_VOPC(InFmt_VOPC *iFmt, const std::string &opcode)
818 {
819 setFlag(WritesVCC);
820 // copy first instruction DWORD
821 instData = iFmt[0];
822 if (hasSecondDword(iFmt)) {
823 // copy second instruction DWORD into union
824 extData = ((MachInst)iFmt)[1];
825 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
826 varSize = 4 + 4;
827 if (iFmt->SRC0 == REG_SRC_DPP) {
828 setFlag(IsDPP);
829 } else if (iFmt->SRC0 == REG_SRC_SWDA) {
830 setFlag(IsSDWA);
831 }
832 } else {
833 varSize = 4;
834 } // if
835 } // Inst_VOPC
836
838 {
839 } // ~Inst_VOPC
840
841 void
843 {
844 int opNum = 0;
845
846 // Needed because can't take addr of bitfield
847 int reg = instData.SRC0;
848 srcOps.emplace_back(reg, getOperandSize(opNum), true,
849 isScalarReg(reg), isVectorReg(reg), false);
850 opNum++;
851
853 srcOps.emplace_back(reg, getOperandSize(opNum), true,
854 false, true, false);
855 opNum++;
856
857 assert(writesVCC());
858 dstOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), false,
859 true, false, false);
860
861 assert(srcOps.size() == numSrcRegOperands());
862 assert(dstOps.size() == numDstRegOperands());
863 }
864
865 int
867 {
868 return varSize;
869 } // instSize
870
871 bool
873 {
874 /*
875 There are several cases where VOPC instructions have a second dword:
876
877 1. SRC0 is a literal.
878 2. SRC0 is being used to add a data parallel primitive (DPP)
879 operation to the instruction.
880 3. SRC0 is being used for sub d-word addressing (SDWA) of the
881 operands in the instruction.
882 */
883 if ((iFmt->SRC0 == REG_SRC_LITERAL) || (iFmt->SRC0 == REG_SRC_DPP) ||
884 (iFmt->SRC0 == REG_SRC_SWDA))
885 return true;
886
887 return false;
888 }
889
890 void
892 {
893 std::stringstream dis_stream;
894 dis_stream << _opcode << " vcc, ";
895
896 dis_stream << opSelectorToRegSym(instData.SRC0) << ", ";
897 dis_stream << "v" << instData.VSRC1;
898
899 disassembly = dis_stream.str();
900 }
901
902 // --- Inst_VINTRP base class methods ---
903
906 {
907 // copy first instruction DWORD
908 instData = iFmt[0];
909 } // Inst_VINTRP
910
912 {
913 } // ~Inst_VINTRP
914
915 int
917 {
918 return 4;
919 } // instSize
920
921 // --- Inst_VOP3 base class methods ---
922
923 Inst_VOP3::Inst_VOP3(InFmt_VOP3 *iFmt, const std::string &opcode,
924 bool sgpr_dst)
925 : GCN3GPUStaticInst(opcode), sgprDst(sgpr_dst)
926 {
927 // copy first instruction DWORD
928 instData = iFmt[0];
929 // copy second instruction DWORD
930 extData = ((InFmt_VOP3_1 *)iFmt)[1];
931 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
932 } // Inst_VOP3
933
935 {
936 } // ~Inst_VOP3
937
938 void
940 {
941 // Also takes care of bitfield addr issue
942 unsigned int srcs[3] = {extData.SRC0, extData.SRC1, extData.SRC2};
943
944 int opNum = 0;
945
946 int numSrc = numSrcRegOperands() - readsVCC();
947 int numDst = numDstRegOperands() - writesVCC();
948
949 for (opNum = 0; opNum < numSrc; opNum++) {
950 srcOps.emplace_back(srcs[opNum], getOperandSize(opNum), true,
951 isScalarReg(srcs[opNum]),
952 isVectorReg(srcs[opNum]), false);
953 }
954
955 if (readsVCC()) {
956 srcOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), true,
957 true, false, false);
958 opNum++;
959 }
960
961 if (numDst) {
962 // Needed because can't take addr of bitfield
963 int reg = instData.VDST;
964 dstOps.emplace_back(reg, getOperandSize(opNum), false,
965 sgprDst, !sgprDst, false);
966 opNum++;
967 }
968
969 if (writesVCC()) {
970 dstOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), false,
971 true, false, false);
972 }
973
974 assert(srcOps.size() == numSrcRegOperands());
975 assert(dstOps.size() == numDstRegOperands());
976 }
977
978 int
980 {
981 return 8;
982 } // instSize
983
984 void
986 {
987 std::stringstream dis_stream;
988 dis_stream << _opcode << " ";
989 int num_regs = 0;
990
991 if (getOperandSize(getNumOperands() - 1) > 4) {
992 num_regs = getOperandSize(getNumOperands() - 1) / 4;
993 if (sgprDst)
994 dis_stream << "s[";
995 else
996 dis_stream << "v[";
997 dis_stream << instData.VDST << ":" << instData.VDST +
998 num_regs - 1 << "], ";
999 } else {
1000 if (sgprDst)
1001 dis_stream << "s";
1002 else
1003 dis_stream << "v";
1004 dis_stream << instData.VDST << ", ";
1005 }
1006
1007 num_regs = getOperandSize(0) / 4;
1008
1009 if (extData.NEG & 0x1) {
1010 dis_stream << "-" << opSelectorToRegSym(extData.SRC0, num_regs);
1011 } else {
1012 dis_stream << opSelectorToRegSym(extData.SRC0, num_regs);
1013 }
1014
1015 if (numSrcRegOperands() > 1) {
1016 num_regs = getOperandSize(1) / 4;
1017
1018 if (extData.NEG & 0x2) {
1019 dis_stream << ", -"
1020 << opSelectorToRegSym(extData.SRC1, num_regs);
1021 } else {
1022 dis_stream << ", "
1023 << opSelectorToRegSym(extData.SRC1, num_regs);
1024 }
1025 }
1026
1027 if (numSrcRegOperands() > 2) {
1028 num_regs = getOperandSize(2) / 4;
1029
1030 if (extData.NEG & 0x4) {
1031 dis_stream << ", -"
1032 << opSelectorToRegSym(extData.SRC2, num_regs);
1033 } else {
1034 dis_stream << ", "
1035 << opSelectorToRegSym(extData.SRC2, num_regs);
1036 }
1037 }
1038
1039 disassembly = dis_stream.str();
1040 }
1041
1042 // --- Inst_VOP3_SDST_ENC base class methods ---
1043
1045 const std::string &opcode)
1047 {
1048 // copy first instruction DWORD
1049 instData = iFmt[0];
1050 // copy second instruction DWORD
1051 extData = ((InFmt_VOP3_1 *)iFmt)[1];
1052 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1053 } // Inst_VOP3_SDST_ENC
1054
1056 {
1057 } // ~Inst_VOP3_SDST_ENC
1058
1059 void
1061 {
1062 // Also takes care of bitfield addr issue
1063 unsigned int srcs[3] = {extData.SRC0, extData.SRC1, extData.SRC2};
1064
1065 int opNum = 0;
1066
1067 int numSrc = numSrcRegOperands() - readsVCC();
1068 int numDst = numDstRegOperands() - writesVCC();
1069
1070 for (opNum = 0; opNum < numSrc; opNum++) {
1071 srcOps.emplace_back(srcs[opNum], getOperandSize(opNum), true,
1072 isScalarReg(srcs[opNum]),
1073 isVectorReg(srcs[opNum]), false);
1074 }
1075
1076 if (readsVCC()) {
1077 srcOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), true,
1078 true, false, false);
1079 opNum++;
1080 }
1081
1082 if (numDst) {
1083 // Needed because can't take addr of bitfield
1084 int reg = instData.VDST;
1085 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1086 false, true, false);
1087 opNum++;
1088 }
1089
1090 if (writesVCC()) {
1091 dstOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), false,
1092 true, false, false);
1093 }
1094
1095 assert(srcOps.size() == numSrcRegOperands());
1096 assert(dstOps.size() == numDstRegOperands());
1097 }
1098
1099 int
1101 {
1102 return 8;
1103 } // instSize
1104
1105 void
1107 {
1108 std::stringstream dis_stream;
1109 dis_stream << _opcode << " ";
1110
1111 dis_stream << "v" << instData.VDST << ", ";
1112
1113 if (numDstRegOperands() == 2) {
1114 if (getOperandSize(getNumOperands() - 1) > 4) {
1115 int num_regs = getOperandSize(getNumOperands() - 1) / 4;
1116 dis_stream << opSelectorToRegSym(instData.SDST, num_regs)
1117 << ", ";
1118 } else {
1119 dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
1120 }
1121 }
1122
1123 if (extData.NEG & 0x1) {
1124 dis_stream << "-" << opSelectorToRegSym(extData.SRC0) << ", ";
1125 } else {
1126 dis_stream << opSelectorToRegSym(extData.SRC0) << ", ";
1127 }
1128
1129 if (extData.NEG & 0x2) {
1130 dis_stream << "-" << opSelectorToRegSym(extData.SRC1);
1131 } else {
1132 dis_stream << opSelectorToRegSym(extData.SRC1);
1133 }
1134
1135 if (numSrcRegOperands() == 3) {
1136 if (extData.NEG & 0x4) {
1137 dis_stream << ", -" << opSelectorToRegSym(extData.SRC2);
1138 } else {
1139 dis_stream << ", " << opSelectorToRegSym(extData.SRC2);
1140 }
1141 }
1142
1143 if (readsVCC())
1144 dis_stream << ", vcc";
1145
1146 disassembly = dis_stream.str();
1147 }
1148
1149 // --- Inst_DS base class methods ---
1150
1151 Inst_DS::Inst_DS(InFmt_DS *iFmt, const std::string &opcode)
1153 {
1154 setFlag(GroupSegment);
1155
1156 // copy first instruction DWORD
1157 instData = iFmt[0];
1158 // copy second instruction DWORD
1159 extData = ((InFmt_DS_1 *)iFmt)[1];
1160 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1161 } // Inst_DS
1162
1164 {
1165 } // ~Inst_DS
1166
1167 void
1169 {
1170 unsigned int srcs[3] = {extData.ADDR, extData.DATA0, extData.DATA1};
1171
1172 int opIdx = 0;
1173
1174 for (opIdx = 0; opIdx < numSrcRegOperands(); opIdx++){
1175 srcOps.emplace_back(srcs[opIdx], getOperandSize(opIdx), true,
1176 false, true, false);
1177 }
1178
1179 if (numDstRegOperands()) {
1180 // Needed because can't take addr of bitfield
1181 int reg = extData.VDST;
1182 dstOps.emplace_back(reg, getOperandSize(opIdx), false,
1183 false, true, false);
1184 }
1185
1186 assert(srcOps.size() == numSrcRegOperands());
1187 assert(dstOps.size() == numDstRegOperands());
1188 }
1189
1190 int
1192 {
1193 return 8;
1194 } // instSize
1195
1196 void
1198 {
1199 std::stringstream dis_stream;
1200 dis_stream << _opcode << " ";
1201
1202 if (numDstRegOperands())
1203 dis_stream << "v" << extData.VDST << ", ";
1204
1205 dis_stream << "v" << extData.ADDR;
1206
1207 if (numSrcRegOperands() > 1)
1208 dis_stream << ", v" << extData.DATA0;
1209
1210 if (numSrcRegOperands() > 2)
1211 dis_stream << ", v" << extData.DATA1;
1212
1213 uint16_t offset = 0;
1214
1215 if (instData.OFFSET1) {
1217 offset <<= 8;
1218 }
1219
1220 if (instData.OFFSET0)
1222
1223 if (offset)
1224 dis_stream << " offset:" << offset;
1225
1226 disassembly = dis_stream.str();
1227 }
1228
1229 // --- Inst_MUBUF base class methods ---
1230
1231 Inst_MUBUF::Inst_MUBUF(InFmt_MUBUF *iFmt, const std::string &opcode)
1233 {
1234 // copy first instruction DWORD
1235 instData = iFmt[0];
1236 // copy second instruction DWORD
1237 extData = ((InFmt_MUBUF_1 *)iFmt)[1];
1238 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1239
1240 if (instData.GLC)
1241 setFlag(GloballyCoherent);
1242
1243 if (instData.SLC)
1244 setFlag(SystemCoherent);
1245 } // Inst_MUBUF
1246
1248 {
1249 } // ~Inst_MUBUF
1250
1251 void
1253 {
1254 // Currently there are three formats:
1255 // 0 src + 0 dst
1256 // 3 src + 1 dst
1257 // 4 src + 0 dst
1258 int opNum = 0;
1259
1260 // Needed because can't take addr of bitfield;
1261 int reg = 0;
1262
1263 if (numSrcRegOperands()) {
1264 if (numSrcRegOperands() == getNumOperands()) {
1265 reg = extData.VDATA;
1266 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1267 false, true, false);
1268 opNum++;
1269 }
1270
1271 reg = extData.VADDR;
1272 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1273 false, true, false);
1274 opNum++;
1275
1276 reg = extData.SRSRC;
1277 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1278 isScalarReg(reg), false, false);
1279 opNum++;
1280
1282 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1283 isScalarReg(reg), false, false);
1284 opNum++;
1285 }
1286
1287 // extData.VDATA moves in the reg list depending on the instruction
1288 if (numDstRegOperands()) {
1289 reg = extData.VDATA;
1290 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1291 false, true, false);
1292 }
1293
1294 assert(srcOps.size() == numSrcRegOperands());
1295 assert(dstOps.size() == numDstRegOperands());
1296 }
1297
1298 int
1300 {
1301 return 8;
1302 } // instSize
1303
1304 void
1306 {
1307 // SRSRC is always in units of 4 SGPRs
1308 int srsrc_val = extData.SRSRC * 4;
1309 std::stringstream dis_stream;
1310 dis_stream << _opcode << " ";
1311 dis_stream << "v" << extData.VDATA << ", v" << extData.VADDR << ", ";
1312 dis_stream << "s[" << srsrc_val << ":"
1313 << srsrc_val + 3 << "], ";
1314 dis_stream << "s" << extData.SOFFSET;
1315
1316 if (instData.OFFSET)
1317 dis_stream << ", offset:" << instData.OFFSET;
1318
1319 disassembly = dis_stream.str();
1320 }
1321
1322 // --- Inst_MTBUF base class methods ---
1323
1324 Inst_MTBUF::Inst_MTBUF(InFmt_MTBUF *iFmt, const std::string &opcode)
1326 {
1327 // copy first instruction DWORD
1328 instData = iFmt[0];
1329 // copy second instruction DWORD
1330 extData = ((InFmt_MTBUF_1 *)iFmt)[1];
1331 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1332
1333 if (instData.GLC)
1334 setFlag(GloballyCoherent);
1335
1336 if (extData.SLC)
1337 setFlag(SystemCoherent);
1338 } // Inst_MTBUF
1339
1341 {
1342 } // ~Inst_MTBUF
1343
1344 void
1346 {
1347 // Currently there are two formats:
1348 // 3 src + 1 dst
1349 // 4 src + 0 dst
1350 int opNum = 0;
1351
1352 // Needed because can't take addr of bitfield
1353 int reg = 0;
1354
1355 if (numSrcRegOperands() == getNumOperands()) {
1356 reg = extData.VDATA;
1357 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1358 false, true, false);
1359 opNum++;
1360 }
1361
1362 reg = extData.VADDR;
1363 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1364 false, true, false);
1365 opNum++;
1366
1367 reg = extData.SRSRC;
1368 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1369 isScalarReg(reg), false, false);
1370 opNum++;
1371
1373 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1374 isScalarReg(reg), false, false);
1375 opNum++;
1376
1377 // extData.VDATA moves in the reg list depending on the instruction
1378 if (numDstRegOperands()) {
1379 reg = extData.VDATA;
1380 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1381 false, true, false);
1382 }
1383
1384 assert(srcOps.size() == numSrcRegOperands());
1385 assert(dstOps.size() == numDstRegOperands());
1386 }
1387
1388 int
1390 {
1391 return 8;
1392 } // instSize
1393
1394 // --- Inst_MIMG base class methods ---
1395
1396 Inst_MIMG::Inst_MIMG(InFmt_MIMG *iFmt, const std::string &opcode)
1398 {
1399 // copy first instruction DWORD
1400 instData = iFmt[0];
1401 // copy second instruction DWORD
1402 extData = ((InFmt_MIMG_1 *)iFmt)[1];
1403 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1404
1405 if (instData.GLC)
1406 setFlag(GloballyCoherent);
1407
1408 if (instData.SLC)
1409 setFlag(SystemCoherent);
1410 } // Inst_MIMG
1411
1413 {
1414 } // ~Inst_MIMG
1415
1416 void
1418 {
1419 // Three formats:
1420 // 1 dst + 2 src : s,s,d
1421 // 0 dst + 3 src : s,s,s
1422 // 1 dst + 3 src : s,s,s,d
1423 int opNum = 0;
1424
1425 // Needed because can't take addr of bitfield
1426 int reg = 0;
1427
1428 if (numSrcRegOperands() == getNumOperands()) {
1429 reg = extData.VDATA;
1430 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1431 false, true, false);
1432 opNum++;
1433 }
1434
1435 reg = extData.VADDR;
1436 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1437 false, true, false);
1438 opNum++;
1439
1440 reg = extData.SRSRC;
1441 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1442 isScalarReg(reg), false, false);
1443 opNum++;
1444
1445 if (getNumOperands() == 4) {
1446 reg = extData.SSAMP;
1447 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1448 isScalarReg(reg), false, false);
1449 opNum++;
1450 }
1451
1452 // extData.VDATA moves in the reg list depending on the instruction
1453 if (numDstRegOperands()) {
1454 reg = extData.VDATA;
1455 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1456 false, true, false);
1457 }
1458
1459 assert(srcOps.size() == numSrcRegOperands());
1460 assert(dstOps.size() == numDstRegOperands());
1461 }
1462
1463 int
1465 {
1466 return 8;
1467 } // instSize
1468
1469 // --- Inst_EXP base class methods ---
1470
1471 Inst_EXP::Inst_EXP(InFmt_EXP *iFmt, const std::string &opcode)
1473 {
1474 // copy first instruction DWORD
1475 instData = iFmt[0];
1476 // copy second instruction DWORD
1477 extData = ((InFmt_EXP_1 *)iFmt)[1];
1478 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1479 } // Inst_EXP
1480
1482 {
1483 } // ~Inst_EXP
1484
1485 void
1487 {
1488 // Only 1 instruction, 1 format: 1 dst + 4 src
1489 int opNum = 0;
1490
1491 // Avoids taking addr of bitfield
1492 unsigned int srcs[4] = {extData.VSRC0, extData.VSRC1,
1494
1495 for (opNum = 0; opNum < 4; opNum++) {
1496 srcOps.emplace_back(srcs[opNum], getOperandSize(opNum), true,
1497 false, true, false);
1498 }
1499
1500 //TODO: Add the dst operand, don't know what it is right now
1501 }
1502
1503 int
1505 {
1506 return 8;
1507 } // instSize
1508
1509 // --- Inst_FLAT base class methods ---
1510
1511 Inst_FLAT::Inst_FLAT(InFmt_FLAT *iFmt, const std::string &opcode)
1513 {
1514 setFlag(Flat);
1515 // copy first instruction DWORD
1516 instData = iFmt[0];
1517 // copy second instruction DWORD
1518 extData = ((InFmt_FLAT_1 *)iFmt)[1];
1519 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1520
1521 if (instData.GLC)
1522 setFlag(GloballyCoherent);
1523
1524 if (instData.SLC)
1525 setFlag(SystemCoherent);
1526 } // Inst_FLAT
1527
1529 {
1530 } // ~Inst_FLAT
1531
1532 void
1534 {
1535 //3 formats:
1536 // 1 dst + 1 src (load)
1537 // 0 dst + 2 src (store)
1538 // 1 dst + 2 src (atomic)
1539 int opNum = 0;
1540
1541 // Needed because can't take addr of bitfield
1542 int reg = 0;
1543
1544 if (getNumOperands() > 2)
1545 assert(isAtomic());
1546
1547 reg = extData.ADDR;
1548 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1549 false, true, false);
1550 opNum++;
1551
1552 if (numSrcRegOperands() == 2) {
1553 reg = extData.DATA;
1554 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1555 false, true, false);
1556 opNum++;
1557 }
1558
1559 if (numDstRegOperands()) {
1560 reg = extData.VDST;
1561 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1562 false, true, false);
1563 }
1564
1565 assert(srcOps.size() == numSrcRegOperands());
1566 assert(dstOps.size() == numDstRegOperands());
1567 }
1568
1569 int
1571 {
1572 return 8;
1573 } // instSize
1574
1575 void
1577 {
1578 std::stringstream dis_stream;
1579 dis_stream << _opcode << " ";
1580
1581 if (isLoad())
1582 dis_stream << "v" << extData.VDST << ", ";
1583
1584 dis_stream << "v[" << extData.ADDR << ":" << extData.ADDR + 1 << "]";
1585
1586 if (isStore())
1587 dis_stream << ", v" << extData.DATA;
1588
1589 disassembly = dis_stream.str();
1590 }
1591} // namespace Gcn3ISA
1592} // namespace gem5
virtual int numDstRegOperands()=0
std::vector< OperandInfo > srcOps
void setFlag(Flags flag)
std::vector< OperandInfo > dstOps
virtual int getNumOperands()=0
const std::string _opcode
virtual int numSrcRegOperands()=0
ScalarRegU32 _srcLiteral
if the instruction has a src literal - an immediate value that is part of the instruction stream - we...
int getOperandSize(int opIdx) override
void generateDisassembly() override
void initOperandInfo() override
Inst_DS(InFmt_DS *, const std::string &opcode)
int instSize() const override
Inst_EXP(InFmt_EXP *, const std::string &opcode)
int instSize() const override
void initOperandInfo() override
Inst_FLAT(InFmt_FLAT *, const std::string &opcode)
int instSize() const override
void generateDisassembly() override
void initOperandInfo() override
int instSize() const override
void initOperandInfo() override
Inst_MIMG(InFmt_MIMG *, const std::string &opcode)
Inst_MTBUF(InFmt_MTBUF *, const std::string &opcode)
void initOperandInfo() override
int instSize() const override
void initOperandInfo() override
Inst_MUBUF(InFmt_MUBUF *, const std::string &opcode)
int instSize() const override
void generateDisassembly() override
void generateDisassembly() override
Inst_SMEM(InFmt_SMEM *, const std::string &opcode)
void initOperandInfo() override
int instSize() const override
Inst_SOP1(InFmt_SOP1 *, const std::string &opcode)
int instSize() const override
bool hasSecondDword(InFmt_SOP1 *)
void initOperandInfo() override
void generateDisassembly() override
bool hasSecondDword(InFmt_SOP2 *)
void generateDisassembly() override
Inst_SOP2(InFmt_SOP2 *, const std::string &opcode)
void initOperandInfo() override
int instSize() const override
bool hasSecondDword(InFmt_SOPC *)
int instSize() const override
void initOperandInfo() override
Inst_SOPC(InFmt_SOPC *, const std::string &opcode)
void generateDisassembly() override
int instSize() const override
void generateDisassembly() override
Inst_SOPK(InFmt_SOPK *, const std::string &opcode)
bool hasSecondDword(InFmt_SOPK *)
void initOperandInfo() override
Inst_SOPP(InFmt_SOPP *, const std::string &opcode)
void initOperandInfo() override
void generateDisassembly() override
int instSize() const override
int instSize() const override
Inst_VINTRP(InFmt_VINTRP *, const std::string &opcode)
void generateDisassembly() override
int instSize() const override
Inst_VOP1(InFmt_VOP1 *, const std::string &opcode)
void initOperandInfo() override
bool hasSecondDword(InFmt_VOP1 *)
int instSize() const override
void initOperandInfo() override
Inst_VOP2(InFmt_VOP2 *, const std::string &opcode)
void generateDisassembly() override
bool hasSecondDword(InFmt_VOP2 *)
Inst_VOP3_SDST_ENC(InFmt_VOP3_SDST_ENC *, const std::string &opcode)
void initOperandInfo() override
const bool sgprDst
the v_cmp and readlane instructions in the VOP3 encoding are unique because they are the only instruc...
int instSize() const override
void generateDisassembly() override
Inst_VOP3(InFmt_VOP3 *, const std::string &opcode, bool sgpr_dst)
bool hasSecondDword(InFmt_VOPC *)
void initOperandInfo() override
void generateDisassembly() override
Inst_VOPC(InFmt_VOPC *, const std::string &opcode)
int instSize() const override
This is a simple scalar statistic, like a counter.
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 24, 21 > opcode
Definition types.hh:92
InstFormat * MachInst
used to represent the encoding of a GCN3 inst.
Definition gpu_types.hh:61
std::string opSelectorToRegSym(int opIdx, int numRegs=0)
Definition registers.cc:40
bool isScalarReg(int opIdx)
Definition registers.cc:219
bool isVectorReg(int opIdx)
Definition registers.cc:232
Bitfield< 5, 3 > reg
Definition types.hh:92
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....

Generated on Mon Jul 10 2023 15:31:55 for gem5 by doxygen 1.9.7