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 VegaISA
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 /*
252 S_GETPC_B64 does not use SSRC0, so don't put anything on srcOps
253 for it (0x1c is 29 base 10, which is the opcode for S_GETPC_B64).
254 */
255 if (instData.OP != 0x1C) {
256 srcOps.emplace_back(reg, getOperandSize(opNum), true,
257 isScalarReg(instData.SSRC0), false, false);
258 opNum++;
259 }
260
261 /*
262 S_SETPC_B64, S_RFE_B64, S_CBRANCH_JOIN, and S_SET_GPR_IDX_IDX do not
263 use SDST, so don't put anything on dstOps for them.
264 */
265 if ((instData.OP != 0x1D) /* S_SETPC_B64 (29 base 10) */ &&
266 (instData.OP != 0x1F) /* S_RFE_B64 (31 base 10) */ &&
267 (instData.OP != 0x2E) /* S_CBRANCH_JOIN (46 base 10) */ &&
268 (instData.OP != 0x32)) /* S_SET_GPR_IDX_IDX (50 base 10) */ {
269 reg = instData.SDST;
270 dstOps.emplace_back(reg, getOperandSize(opNum), false,
271 isScalarReg(instData.SDST), false, false);
272 }
273
274 assert(srcOps.size() == numSrcRegOperands());
275 assert(dstOps.size() == numDstRegOperands());
276 }
277
278 int
280 {
281 return varSize;
282 } // instSize
283
284 bool
286 {
287 if (iFmt->SSRC0 == REG_SRC_LITERAL)
288 return true;
289
290 return false;
291 }
292
293 void
295 {
296 std::stringstream dis_stream;
297 dis_stream << _opcode << " ";
298 dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
299
301 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
302 << extData.imm_u32;
303 } else {
304 dis_stream << opSelectorToRegSym(instData.SSRC0);
305 }
306
307 disassembly = dis_stream.str();
308 }
309
310 // --- Inst_SOPC base class methods ---
311
312 Inst_SOPC::Inst_SOPC(InFmt_SOPC *iFmt, const std::string &opcode)
314 {
316
317 // copy first instruction DWORD
318 instData = iFmt[0];
319 if (hasSecondDword(iFmt)) {
320 // copy second instruction DWORD into union
321 extData = ((MachInst)iFmt)[1];
322 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
323 varSize = 4 + 4;
324 } else {
325 varSize = 4;
326 } // if
327 } // Inst_SOPC
328
330 {
331 } // ~Inst_SOPC
332
333 void
335 {
336 int opNum = 0;
337
338 // Needed because can't take addr of bitfield
339 int reg = instData.SSRC0;
340 srcOps.emplace_back(reg, getOperandSize(opNum), true,
341 isScalarReg(instData.SSRC0), false, false);
342 opNum++;
343
345 srcOps.emplace_back(reg, getOperandSize(opNum), true,
346 isScalarReg(instData.SSRC1), false, false);
347
348 }
349
350 int
352 {
353 return varSize;
354 } // instSize
355
356 bool
358 {
359 if (iFmt->SSRC0 == REG_SRC_LITERAL)
360 return true;
361
362 if (iFmt->SSRC1 == REG_SRC_LITERAL)
363 return true;
364
365 return false;
366 }
367
368 void
370 {
371 std::stringstream dis_stream;
372 dis_stream << _opcode << " ";
373
375 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
376 << extData.imm_u32;
377 } else {
378 dis_stream << opSelectorToRegSym(instData.SSRC0) << ", ";
379 }
380
382 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
383 << extData.imm_u32;
384 } else {
385 dis_stream << opSelectorToRegSym(instData.SSRC1);
386 }
387
388 disassembly = dis_stream.str();
389 }
390
391 // --- Inst_SOPP base class methods ---
392
393 Inst_SOPP::Inst_SOPP(InFmt_SOPP *iFmt, const std::string &opcode)
395 {
397
398 // copy first instruction DWORD
399 instData = iFmt[0];
400 } // Inst_SOPP
401
403 {
404 } // ~Inst_SOPP
405
406 void
408 {
409 int opNum = 0;
410
411
412 if (numSrcRegOperands()) {
413 // Needed because can't take addr of bitfield
414 int reg = instData.SIMM16;
415 srcOps.emplace_back(reg, getOperandSize(opNum), true,
416 false, false, true);
417
418 opNum++;
419
420 if (readsVCC()) {
421 srcOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), true,
422 true, false, false);
423 opNum++;
424 }
425 }
426 assert(srcOps.size() == numSrcRegOperands());
427 assert(dstOps.size() == numDstRegOperands());
428 }
429
430 int
432 {
433 return 4;
434 } // instSize
435
436 void
438 {
439 std::stringstream dis_stream;
440 dis_stream << _opcode;
441
442 switch (instData.OP) {
443 case 8:
444 {
445 dis_stream << " ";
446 int dest = 4 * instData.SIMM16 + 4;
447 dis_stream << "label_" << std::hex << dest;
448 }
449 break;
450 case 12:
451 {
452 dis_stream << " ";
453
454 int vm_cnt = 0;
455 int exp_cnt = 0;
456 int lgkm_cnt = 0;
457
458 vm_cnt = bits<uint16_t>(instData.SIMM16, 3, 0);
459 exp_cnt = bits<uint16_t>(instData.SIMM16, 6, 4);
460 lgkm_cnt = bits<uint16_t>(instData.SIMM16, 11, 8);
461
462 // if the counts are not maxed out, then we
463 // print out the count value
464 if (vm_cnt != 0xf) {
465 dis_stream << "vmcnt(" << vm_cnt << ")";
466 }
467
468 if (lgkm_cnt != 0xf) {
469 if (vm_cnt != 0xf)
470 dis_stream << " & ";
471
472 dis_stream << "lgkmcnt(" << lgkm_cnt << ")";
473 }
474
475 if (exp_cnt != 0x7) {
476 if (vm_cnt != 0xf || lgkm_cnt != 0xf)
477 dis_stream << " & ";
478
479 dis_stream << "expcnt(" << exp_cnt << ")";
480 }
481 }
482 break;
483 default:
484 break;
485 }
486
487 disassembly = dis_stream.str();
488 }
489
490 // --- Inst_SMEM base class methods ---
491
492 Inst_SMEM::Inst_SMEM(InFmt_SMEM *iFmt, const std::string &opcode)
494 {
496 setFlag(GlobalSegment);
497
498 // copy first instruction DWORD
499 instData = iFmt[0];
500 // copy second instruction DWORD
501 extData = ((InFmt_SMEM_1 *)iFmt)[1];
502 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
503
504 if (instData.GLC)
505 setFlag(GloballyCoherent);
506 } // Inst_SMEM
507
509 {
510 } // ~Inst_SMEM
511
512 void
514 {
515 // Formats:
516 // 0 src + 0 dst
517 // 3 src + 0 dst
518 // 2 src + 1 dst
519 // 0 src + 1 dst
520 int opNum = 0;
521 // Needed because can't take addr of bitfield
522 int reg = 0;
523
524 if (numSrcRegOperands()) {
527 srcOps.emplace_back(reg, getOperandSize(opNum), true,
528 isScalarReg(reg), false, false);
529 opNum++;
530 }
531
533 srcOps.emplace_back(reg, getOperandSize(opNum), true,
534 true, false, false);
535 opNum++;
536
538 if (instData.IMM) {
539 srcOps.emplace_back(reg, getOperandSize(opNum), true,
540 false, false, true);
541 } else {
542 srcOps.emplace_back(reg, getOperandSize(opNum), true,
543 isScalarReg(reg), false, false);
544 }
545 opNum++;
546 }
547
548 if (numDstRegOperands()) {
550 dstOps.emplace_back(reg, getOperandSize(opNum), false,
551 isScalarReg(reg), false, false);
552 }
553
554 assert(srcOps.size() == numSrcRegOperands());
555 assert(dstOps.size() == numDstRegOperands());
556 }
557
558 int
560 {
561 return 8;
562 } // instSize
563
564 void
566 {
567 std::stringstream dis_stream;
568 dis_stream << _opcode << " ";
569 if (numDstRegOperands()) {
570 if (getOperandSize(getNumOperands() - 1) > 4) {
571 dis_stream << "s[" << instData.SDATA << ":"
573 4 - 1 << "], ";
574 } else {
575 dis_stream << "s" << instData.SDATA << ", ";
576 }
577 }
578
579 // SBASE has an implied LSB of 0, so we need
580 // to shift by one to get the actual value
581 dis_stream << "s[" << (instData.SBASE << 1) << ":"
582 << ((instData.SBASE << 1) + 1) << "], ";
583
584 if (instData.IMM) {
585 // IMM == 1 implies OFFSET should be
586 // used as the offset
587 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(2)
588 << extData.OFFSET;
589 } else {
590 // IMM == 0 implies OFFSET should be
591 // used to specify SGRP in which the
592 // offset is held
593 dis_stream << "s" << extData.OFFSET;
594 }
595
596 disassembly = dis_stream.str();
597 }
598
599 // --- Inst_VOP2 base class methods ---
600
601 Inst_VOP2::Inst_VOP2(InFmt_VOP2 *iFmt, const std::string &opcode)
603 {
604 // copy first instruction DWORD
605 instData = iFmt[0];
606 if (hasSecondDword(iFmt)) {
607 // copy second instruction DWORD into union
608 extData = ((MachInst)iFmt)[1];
609 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
610 varSize = 4 + 4;
611 if (iFmt->SRC0 == REG_SRC_DPP) {
612 setFlag(IsDPP);
613 } else if (iFmt->SRC0 == REG_SRC_SWDA) {
614 setFlag(IsSDWA);
615 }
616 } else {
617 varSize = 4;
618 } // if
619 } // Inst_VOP2
620
622 {
623 } // ~Inst_VOP2
624
625 void
627 {
628 int opNum = 0;
629
630 // Needed because can't take addr of bitfield
631 int reg = instData.SRC0;
632 srcOps.emplace_back(reg, getOperandSize(opNum), true,
633 isScalarReg(reg), isVectorReg(reg), false);
634 opNum++;
635
637 srcOps.emplace_back(reg, getOperandSize(opNum), true,
638 false, true, false);
639 opNum++;
640
641 // VCC read
642 if (readsVCC()) {
643 srcOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), true,
644 true, false, false);
645 opNum++;
646 }
647
648 // VDST
649 reg = instData.VDST;
650 dstOps.emplace_back(reg, getOperandSize(opNum), false,
651 false, true, false);
652 opNum++;
653
654 // VCC write
655 if (writesVCC()) {
656 dstOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), false,
657 true, false, false);
658 }
659
660 assert(srcOps.size() == numSrcRegOperands());
661 assert(dstOps.size() == numDstRegOperands());
662 }
663
664 int
666 {
667 return varSize;
668 } // instSize
669
670 bool
672 {
673 /*
674 There are a few cases where VOP2 instructions have a second dword:
675
676 1. SRC0 is a literal
677 2. SRC0 is being used to add a data parallel primitive (DPP)
678 operation to the instruction.
679 3. SRC0 is being used for sub d-word addressing (SDWA) of the
680 operands in the instruction.
681 4. VOP2 instructions also have four special opcodes:',
682 V_MADMK_{F16, F32} (0x24, 0x17), and V_MADAK_{F16, F32}',
683 (0x25, 0x18), that are always 64b. the only way to',
684 detect these special cases is to explicitly check,',
685 the opcodes',
686 */
687 if (iFmt->SRC0 == REG_SRC_LITERAL || (iFmt->SRC0 == REG_SRC_DPP) ||
688 (iFmt->SRC0 == REG_SRC_SWDA) || iFmt->OP == 0x17 ||
689 iFmt->OP == 0x18 || iFmt->OP == 0x24 || iFmt->OP == 0x25)
690 return true;
691
692 return false;
693 }
694
695 void
697 {
698 std::stringstream dis_stream;
699 dis_stream << _opcode << " ";
700 dis_stream << "v" << instData.VDST << ", ";
701
702 if (writesVCC())
703 dis_stream << "vcc, ";
704
705 if ((instData.SRC0 == REG_SRC_LITERAL) ||
708 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
709 << _srcLiteral << ", ";
710 } else {
711 dis_stream << opSelectorToRegSym(instData.SRC0) << ", ";
712 }
713
714 // VOP2 instructions have four special opcodes:',
715 // V_MADMK_{F16, F32} (0x24, 0x17), and V_MADAK_{F16, F32}',
716 // (0x25, 0x18), that are always 64b. the only way to',
717 // detect these special cases is to explicitly check,',
718 // the opcodes',
719 if (instData.OP == 0x17 || instData.OP == 0x18 || instData.OP == 0x24
720 || instData.OP == 0x25) {
721 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
722 << extData.imm_u32 << ", ";
723 }
724
725 dis_stream << std::resetiosflags(std::ios_base::basefield) << "v"
726 << instData.VSRC1;
727
728 if (readsVCC())
729 dis_stream << ", vcc";
730
731 disassembly = dis_stream.str();
732 }
733
734 // --- Inst_VOP1 base class methods ---
735
736 Inst_VOP1::Inst_VOP1(InFmt_VOP1 *iFmt, const std::string &opcode)
738 {
739 // copy first instruction DWORD
740 instData = iFmt[0];
741 if (hasSecondDword(iFmt)) {
742 // copy second instruction DWORD into union
743 extData = ((MachInst)iFmt)[1];
744 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
745 varSize = 4 + 4;
746 if (iFmt->SRC0 == REG_SRC_DPP) {
747 setFlag(IsDPP);
748 } else if (iFmt->SRC0 == REG_SRC_SWDA) {
749 setFlag(IsSDWA);
750 }
751 } else {
752 varSize = 4;
753 } // if
754 } // Inst_VOP1
755
757 {
758 } // ~Inst_VOP1
759
760 void
762 {
763 int opNum = 0;
764 // Needed because can't take addr of bitfield
765 int reg = instData.SRC0;
766
767 if (numSrcRegOperands()) {
768 srcOps.emplace_back(reg, getOperandSize(opNum), true,
769 isScalarReg(reg), isVectorReg(reg), false);
770 opNum++;
771 }
772
773 if (numDstRegOperands()) {
774 reg = instData.VDST;
775 /*
776 The v_readfirstlane_b32 instruction (op = 2) is a special case
777 VOP1 instruction which has a scalar register as the destination.
778 (See section 6.6.2 "Special Cases" in the Vega ISA manual)
779
780 Therefore we change the dest op to be scalar reg = true and
781 vector reg = false in reserve of all other instructions.
782 */
783 if (instData.OP == 2) {
784 dstOps.emplace_back(reg, getOperandSize(opNum), false,
785 true, false, false);
786 } else {
787 dstOps.emplace_back(reg, getOperandSize(opNum), false,
788 false, true, false);
789 }
790 }
791
792 assert(srcOps.size() == numSrcRegOperands());
793 assert(dstOps.size() == numDstRegOperands());
794 }
795
796 int
798 {
799 return varSize;
800 } // instSize
801
802 bool
804 {
805 /*
806 There are several cases where VOP1 instructions have a second dword:
807
808 1. SRC0 is a literal.
809 2. SRC0 is being used to add a data parallel primitive (DPP)
810 operation to the instruction.
811 3. SRC0 is being used for sub d-word addressing (SDWA) of the
812 operands in the instruction.
813 */
814 if ((iFmt->SRC0 == REG_SRC_LITERAL) || (iFmt->SRC0 == REG_SRC_DPP) ||
815 (iFmt->SRC0 == REG_SRC_SWDA))
816 return true;
817
818 return false;
819 }
820
821 void
823 {
824 std::stringstream dis_stream;
825 dis_stream << _opcode << " ";
826 dis_stream << "v" << instData.VDST << ", ";
827
828 if ((instData.SRC0 == REG_SRC_LITERAL) ||
831 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
832 << _srcLiteral;
833 } else {
834 dis_stream << opSelectorToRegSym(instData.SRC0);
835 }
836
837 disassembly = dis_stream.str();
838 }
839
840 // --- Inst_VOPC base class methods ---
841
842 Inst_VOPC::Inst_VOPC(InFmt_VOPC *iFmt, const std::string &opcode)
844 {
845 setFlag(WritesVCC);
846 // copy first instruction DWORD
847 instData = iFmt[0];
848 if (hasSecondDword(iFmt)) {
849 // copy second instruction DWORD into union
850 extData = ((MachInst)iFmt)[1];
851 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
852 varSize = 4 + 4;
853 if (iFmt->SRC0 == REG_SRC_DPP) {
854 setFlag(IsDPP);
855 } else if (iFmt->SRC0 == REG_SRC_SWDA) {
856 setFlag(IsSDWA);
857 }
858 } else {
859 varSize = 4;
860 } // if
861 } // Inst_VOPC
862
864 {
865 } // ~Inst_VOPC
866
867 void
869 {
870 int opNum = 0;
871
872 // Needed because can't take addr of bitfield
873 int reg = instData.SRC0;
874 srcOps.emplace_back(reg, getOperandSize(opNum), true,
875 isScalarReg(reg), isVectorReg(reg), false);
876 opNum++;
877
879 srcOps.emplace_back(reg, getOperandSize(opNum), true,
880 false, true, false);
881 opNum++;
882
883 assert(writesVCC());
884 dstOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), false,
885 true, false, false);
886
887 assert(srcOps.size() == numSrcRegOperands());
888 assert(dstOps.size() == numDstRegOperands());
889 }
890
891 int
893 {
894 return varSize;
895 } // instSize
896
897 bool
899 {
900 /*
901 There are several cases where VOPC instructions have a second dword:
902
903 1. SRC0 is a literal.
904 2. SRC0 is being used to add a data parallel primitive (DPP)
905 operation to the instruction.
906 3. SRC0 is being used for sub d-word addressing (SDWA) of the
907 operands in the instruction.
908 */
909 if ((iFmt->SRC0 == REG_SRC_LITERAL) || (iFmt->SRC0 == REG_SRC_DPP) ||
910 (iFmt->SRC0 == REG_SRC_SWDA))
911 return true;
912
913 return false;
914 }
915
916 void
918 {
919 std::stringstream dis_stream;
920 dis_stream << _opcode << " vcc, ";
921
922 if ((instData.SRC0 == REG_SRC_LITERAL) ||
925 dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
926 << _srcLiteral << ", ";
927 } else {
928 dis_stream << opSelectorToRegSym(instData.SRC0) << ", ";
929 }
930 dis_stream << "v" << instData.VSRC1;
931
932 disassembly = dis_stream.str();
933 }
934
935 // --- Inst_VINTRP base class methods ---
936
939 {
940 // copy first instruction DWORD
941 instData = iFmt[0];
942 } // Inst_VINTRP
943
945 {
946 } // ~Inst_VINTRP
947
948 int
950 {
951 return 4;
952 } // instSize
953
954 // --- Inst_VOP3A base class methods ---
955
956 Inst_VOP3A::Inst_VOP3A(InFmt_VOP3A *iFmt, const std::string &opcode,
957 bool sgpr_dst)
958 : VEGAGPUStaticInst(opcode), sgprDst(sgpr_dst)
959 {
960 // copy first instruction DWORD
961 instData = iFmt[0];
962 // copy second instruction DWORD
963 extData = ((InFmt_VOP3_1 *)iFmt)[1];
964 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
965 } // Inst_VOP3A
966
968 {
969 } // ~Inst_VOP3A
970
971 void
973 {
974 // Also takes care of bitfield addr issue
975 unsigned int srcs[3] = {extData.SRC0, extData.SRC1, extData.SRC2};
976
977 int opNum = 0;
978
979 int numSrc = numSrcRegOperands() - readsVCC();
980 int numDst = numDstRegOperands() - writesVCC();
981
982 for (opNum = 0; opNum < numSrc; opNum++) {
983 srcOps.emplace_back(srcs[opNum], getOperandSize(opNum), true,
984 isScalarReg(srcs[opNum]),
985 isVectorReg(srcs[opNum]), false);
986 }
987
988 if (readsVCC()) {
989 srcOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), true,
990 true, false, false);
991 opNum++;
992 }
993
994 if (numDst) {
995 // Needed because can't take addr of bitfield
996 int reg = instData.VDST;
997 dstOps.emplace_back(reg, getOperandSize(opNum), false,
998 sgprDst, !sgprDst, false);
999 opNum++;
1000 }
1001
1002 if (writesVCC()) {
1003 dstOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), false,
1004 true, false, false);
1005 }
1006
1007 assert(srcOps.size() == numSrcRegOperands());
1008 assert(dstOps.size() == numDstRegOperands());
1009 }
1010
1011 int
1013 {
1014 return 8;
1015 } // instSize
1016
1017 void
1019 {
1020 std::stringstream dis_stream;
1021 dis_stream << _opcode << " ";
1022 int num_regs = 0;
1023
1024 if (getOperandSize(getNumOperands() - 1) > 4) {
1025 num_regs = getOperandSize(getNumOperands() - 1) / 4;
1026 if (sgprDst)
1027 dis_stream << "s[";
1028 else
1029 dis_stream << "v[";
1030 dis_stream << instData.VDST << ":" << instData.VDST +
1031 num_regs - 1 << "], ";
1032 } else {
1033 if (sgprDst)
1034 dis_stream << "s";
1035 else
1036 dis_stream << "v";
1037 dis_stream << instData.VDST << ", ";
1038 }
1039
1040 num_regs = getOperandSize(0) / 4;
1041
1042 if (extData.NEG & 0x1) {
1043 dis_stream << "-" << opSelectorToRegSym(extData.SRC0, num_regs);
1044 } else {
1045 dis_stream << opSelectorToRegSym(extData.SRC0, num_regs);
1046 }
1047
1048 if (numSrcRegOperands() > 1) {
1049 num_regs = getOperandSize(1) / 4;
1050
1051 if (extData.NEG & 0x2) {
1052 dis_stream << ", -"
1053 << opSelectorToRegSym(extData.SRC1, num_regs);
1054 } else {
1055 dis_stream << ", "
1056 << opSelectorToRegSym(extData.SRC1, num_regs);
1057 }
1058 }
1059
1060 if (numSrcRegOperands() > 2) {
1061 num_regs = getOperandSize(2) / 4;
1062
1063 if (extData.NEG & 0x4) {
1064 dis_stream << ", -"
1065 << opSelectorToRegSym(extData.SRC2, num_regs);
1066 } else {
1067 dis_stream << ", "
1068 << opSelectorToRegSym(extData.SRC2, num_regs);
1069 }
1070 }
1071
1072 disassembly = dis_stream.str();
1073 }
1074
1075 // --- Inst_VOP3B base class methods ---
1076
1077 Inst_VOP3B::Inst_VOP3B(InFmt_VOP3B *iFmt, const std::string &opcode)
1079 {
1080 // copy first instruction DWORD
1081 instData = iFmt[0];
1082 // copy second instruction DWORD
1083 extData = ((InFmt_VOP3_1 *)iFmt)[1];
1084 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1085 } // Inst_VOP3B
1086
1088 {
1089 } // ~Inst_VOP3B
1090
1091 void
1093 {
1094 // Also takes care of bitfield addr issue
1095 unsigned int srcs[3] = {extData.SRC0, extData.SRC1, extData.SRC2};
1096
1097 int opNum = 0;
1098
1099 int numSrc = numSrcRegOperands() - readsVCC();
1100 int numDst = numDstRegOperands() - writesVCC();
1101
1102 for (opNum = 0; opNum < numSrc; opNum++) {
1103 srcOps.emplace_back(srcs[opNum], getOperandSize(opNum), true,
1104 isScalarReg(srcs[opNum]),
1105 isVectorReg(srcs[opNum]), false);
1106 }
1107
1108 if (readsVCC()) {
1109 srcOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), true,
1110 true, false, false);
1111 opNum++;
1112 }
1113
1114 if (numDst) {
1115 // Needed because can't take addr of bitfield
1116 int reg = instData.VDST;
1117 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1118 false, true, false);
1119 opNum++;
1120 }
1121
1122 if (writesVCC()) {
1123 dstOps.emplace_back(REG_VCC_LO, getOperandSize(opNum), false,
1124 true, false, false);
1125 }
1126
1127 assert(srcOps.size() == numSrcRegOperands());
1128 assert(dstOps.size() == numDstRegOperands());
1129 }
1130
1131 int
1133 {
1134 return 8;
1135 } // instSize
1136
1137 void
1139 {
1140 std::stringstream dis_stream;
1141 dis_stream << _opcode << " ";
1142
1143 dis_stream << "v" << instData.VDST << ", ";
1144
1145 if (numDstRegOperands() == 2) {
1146 if (getOperandSize(getNumOperands() - 1) > 4) {
1147 int num_regs = getOperandSize(getNumOperands() - 1) / 4;
1148 dis_stream << opSelectorToRegSym(instData.SDST, num_regs)
1149 << ", ";
1150 } else {
1151 dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
1152 }
1153 }
1154
1155 if (extData.NEG & 0x1) {
1156 dis_stream << "-" << opSelectorToRegSym(extData.SRC0) << ", ";
1157 } else {
1158 dis_stream << opSelectorToRegSym(extData.SRC0) << ", ";
1159 }
1160
1161 if (extData.NEG & 0x2) {
1162 dis_stream << "-" << opSelectorToRegSym(extData.SRC1);
1163 } else {
1164 dis_stream << opSelectorToRegSym(extData.SRC1);
1165 }
1166
1167 if (numSrcRegOperands() == 3) {
1168 if (extData.NEG & 0x4) {
1169 dis_stream << ", -" << opSelectorToRegSym(extData.SRC2);
1170 } else {
1171 dis_stream << ", " << opSelectorToRegSym(extData.SRC2);
1172 }
1173 }
1174
1175 if (readsVCC())
1176 dis_stream << ", vcc";
1177
1178 disassembly = dis_stream.str();
1179 }
1180
1181 // --- Inst_DS base class methods ---
1182
1183 Inst_DS::Inst_DS(InFmt_DS *iFmt, const std::string &opcode)
1185 {
1186 setFlag(GroupSegment);
1187
1188 // copy first instruction DWORD
1189 instData = iFmt[0];
1190 // copy second instruction DWORD
1191 extData = ((InFmt_DS_1 *)iFmt)[1];
1192 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1193 } // Inst_DS
1194
1196 {
1197 } // ~Inst_DS
1198
1199 void
1201 {
1202 unsigned int srcs[3] = {extData.ADDR, extData.DATA0, extData.DATA1};
1203
1204 int opIdx = 0;
1205
1206 for (opIdx = 0; opIdx < numSrcRegOperands(); opIdx++){
1207 srcOps.emplace_back(srcs[opIdx], getOperandSize(opIdx), true,
1208 false, true, false);
1209 }
1210
1211 if (numDstRegOperands()) {
1212 // Needed because can't take addr of bitfield
1213 int reg = extData.VDST;
1214 dstOps.emplace_back(reg, getOperandSize(opIdx), false,
1215 false, true, false);
1216 }
1217
1218 assert(srcOps.size() == numSrcRegOperands());
1219 assert(dstOps.size() == numDstRegOperands());
1220 }
1221
1222 int
1224 {
1225 return 8;
1226 } // instSize
1227
1228 void
1230 {
1231 std::stringstream dis_stream;
1232 dis_stream << _opcode << " ";
1233
1234 if (numDstRegOperands())
1235 dis_stream << "v" << extData.VDST << ", ";
1236
1237 dis_stream << "v" << extData.ADDR;
1238
1239 if (numSrcRegOperands() > 1)
1240 dis_stream << ", v" << extData.DATA0;
1241
1242 if (numSrcRegOperands() > 2)
1243 dis_stream << ", v" << extData.DATA1;
1244
1245 uint16_t offset = 0;
1246
1247 if (instData.OFFSET1) {
1249 offset <<= 8;
1250 }
1251
1252 if (instData.OFFSET0)
1254
1255 if (offset)
1256 dis_stream << " offset:" << offset;
1257
1258 disassembly = dis_stream.str();
1259 }
1260
1261 // --- Inst_MUBUF base class methods ---
1262
1263 Inst_MUBUF::Inst_MUBUF(InFmt_MUBUF *iFmt, const std::string &opcode)
1265 {
1266 // copy first instruction DWORD
1267 instData = iFmt[0];
1268 // copy second instruction DWORD
1269 extData = ((InFmt_MUBUF_1 *)iFmt)[1];
1270 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1271
1272 if (instData.GLC)
1273 setFlag(GloballyCoherent);
1274
1275 if (instData.SLC)
1276 setFlag(SystemCoherent);
1277 } // Inst_MUBUF
1278
1280 {
1281 } // ~Inst_MUBUF
1282
1283 void
1285 {
1286 // Currently there are three formats:
1287 // 0 src + 0 dst
1288 // 3 src + 1 dst
1289 // 4 src + 0 dst
1290 int opNum = 0;
1291
1292 // Needed because can't take addr of bitfield;
1293 int reg = 0;
1294
1295 if (numSrcRegOperands()) {
1296 if (numSrcRegOperands() == getNumOperands()) {
1297 reg = extData.VDATA;
1298 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1299 false, true, false);
1300 opNum++;
1301 }
1302
1303 reg = extData.VADDR;
1304 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1305 false, true, false);
1306 opNum++;
1307
1308 reg = extData.SRSRC;
1309 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1310 isScalarReg(reg), false, false);
1311 opNum++;
1312
1314 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1315 isScalarReg(reg), false, false);
1316 opNum++;
1317 }
1318
1319 // extData.VDATA moves in the reg list depending on the instruction
1320 if (numDstRegOperands()) {
1321 reg = extData.VDATA;
1322 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1323 false, true, false);
1324 }
1325
1326 assert(srcOps.size() == numSrcRegOperands());
1327 assert(dstOps.size() == numDstRegOperands());
1328 }
1329
1330 int
1332 {
1333 return 8;
1334 } // instSize
1335
1336 void
1338 {
1339 // SRSRC is always in units of 4 SGPRs
1340 int srsrc_val = extData.SRSRC * 4;
1341 std::stringstream dis_stream;
1342 dis_stream << _opcode << " ";
1343 dis_stream << "v" << extData.VDATA << ", v" << extData.VADDR << ", ";
1344 dis_stream << "s[" << srsrc_val << ":"
1345 << srsrc_val + 3 << "], ";
1346 dis_stream << "s" << extData.SOFFSET;
1347
1348 if (instData.OFFSET)
1349 dis_stream << ", offset:" << instData.OFFSET;
1350
1351 disassembly = dis_stream.str();
1352 }
1353
1354 // --- Inst_MTBUF base class methods ---
1355
1356 Inst_MTBUF::Inst_MTBUF(InFmt_MTBUF *iFmt, const std::string &opcode)
1358 {
1359 // copy first instruction DWORD
1360 instData = iFmt[0];
1361 // copy second instruction DWORD
1362 extData = ((InFmt_MTBUF_1 *)iFmt)[1];
1363 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1364
1365 if (instData.GLC)
1366 setFlag(GloballyCoherent);
1367
1368 if (extData.SLC)
1369 setFlag(SystemCoherent);
1370 } // Inst_MTBUF
1371
1373 {
1374 } // ~Inst_MTBUF
1375
1376 void
1378 {
1379 // Currently there are two formats:
1380 // 3 src + 1 dst
1381 // 4 src + 0 dst
1382 int opNum = 0;
1383
1384 // Needed because can't take addr of bitfield
1385 int reg = 0;
1386
1387 if (numSrcRegOperands() == getNumOperands()) {
1388 reg = extData.VDATA;
1389 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1390 false, true, false);
1391 opNum++;
1392 }
1393
1394 reg = extData.VADDR;
1395 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1396 false, true, false);
1397 opNum++;
1398
1399 reg = extData.SRSRC;
1400 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1401 isScalarReg(reg), false, false);
1402 opNum++;
1403
1405 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1406 isScalarReg(reg), false, false);
1407 opNum++;
1408
1409 // extData.VDATA moves in the reg list depending on the instruction
1410 if (numDstRegOperands()) {
1411 reg = extData.VDATA;
1412 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1413 false, true, false);
1414 }
1415
1416 assert(srcOps.size() == numSrcRegOperands());
1417 assert(dstOps.size() == numDstRegOperands());
1418 }
1419
1420 int
1422 {
1423 return 8;
1424 } // instSize
1425
1426 // --- Inst_MIMG base class methods ---
1427
1428 Inst_MIMG::Inst_MIMG(InFmt_MIMG *iFmt, const std::string &opcode)
1430 {
1431 // copy first instruction DWORD
1432 instData = iFmt[0];
1433 // copy second instruction DWORD
1434 extData = ((InFmt_MIMG_1 *)iFmt)[1];
1435 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1436
1437 if (instData.GLC)
1438 setFlag(GloballyCoherent);
1439
1440 if (instData.SLC)
1441 setFlag(SystemCoherent);
1442 } // Inst_MIMG
1443
1445 {
1446 } // ~Inst_MIMG
1447
1448 void
1450 {
1451 // Three formats:
1452 // 1 dst + 2 src : s,s,d
1453 // 0 dst + 3 src : s,s,s
1454 // 1 dst + 3 src : s,s,s,d
1455 int opNum = 0;
1456
1457 // Needed because can't take addr of bitfield
1458 int reg = 0;
1459
1460 if (numSrcRegOperands() == getNumOperands()) {
1461 reg = extData.VDATA;
1462 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1463 false, true, false);
1464 opNum++;
1465 }
1466
1467 reg = extData.VADDR;
1468 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1469 false, true, false);
1470 opNum++;
1471
1472 reg = extData.SRSRC;
1473 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1474 isScalarReg(reg), false, false);
1475 opNum++;
1476
1477 if (getNumOperands() == 4) {
1478 reg = extData.SSAMP;
1479 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1480 isScalarReg(reg), false, false);
1481 opNum++;
1482 }
1483
1484 // extData.VDATA moves in the reg list depending on the instruction
1485 if (numDstRegOperands()) {
1486 reg = extData.VDATA;
1487 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1488 false, true, false);
1489 }
1490
1491 assert(srcOps.size() == numSrcRegOperands());
1492 assert(dstOps.size() == numDstRegOperands());
1493 }
1494
1495 int
1497 {
1498 return 8;
1499 } // instSize
1500
1501 // --- Inst_EXP base class methods ---
1502
1503 Inst_EXP::Inst_EXP(InFmt_EXP *iFmt, const std::string &opcode)
1505 {
1506 // copy first instruction DWORD
1507 instData = iFmt[0];
1508 // copy second instruction DWORD
1509 extData = ((InFmt_EXP_1 *)iFmt)[1];
1510 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1511 } // Inst_EXP
1512
1514 {
1515 } // ~Inst_EXP
1516
1517 void
1519 {
1520 // Only 1 instruction, 1 format: 1 dst + 4 src
1521 int opNum = 0;
1522
1523 // Avoids taking addr of bitfield
1524 unsigned int srcs[4] = {extData.VSRC0, extData.VSRC1,
1526
1527 for (opNum = 0; opNum < 4; opNum++) {
1528 srcOps.emplace_back(srcs[opNum], getOperandSize(opNum), true,
1529 false, true, false);
1530 }
1531
1532 //TODO: Add the dst operand, don't know what it is right now
1533 }
1534
1535 int
1537 {
1538 return 8;
1539 } // instSize
1540
1541 // --- Inst_FLAT base class methods ---
1542
1543 Inst_FLAT::Inst_FLAT(InFmt_FLAT *iFmt, const std::string &opcode)
1545 {
1546 // The SEG field specifies FLAT(0) SCRATCH(1) or GLOBAL(2)
1547 if (iFmt->SEG == 0) {
1548 setFlag(Flat);
1549 } else if (iFmt->SEG == 2) {
1550 setFlag(FlatGlobal);
1551 } else {
1552 panic("Unknown flat segment: %d\n", iFmt->SEG);
1553 }
1554
1555 // copy first instruction DWORD
1556 instData = iFmt[0];
1557 // copy second instruction DWORD
1558 extData = ((InFmt_FLAT_1 *)iFmt)[1];
1559 _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1560
1561 if (instData.GLC)
1562 setFlag(GloballyCoherent);
1563
1564 if (instData.SLC)
1565 setFlag(SystemCoherent);
1566 } // Inst_FLAT
1567
1569 {
1570 } // ~Inst_FLAT
1571
1572 void
1574 {
1575 // One of the flat subtypes should be specified via flags
1576 assert(isFlat() ^ isFlatGlobal());
1577
1578 if (isFlat()) {
1580 } else if (isFlatGlobal()) {
1582 } else {
1583 panic("Unknown flat subtype!\n");
1584 }
1585 }
1586
1587 void
1589 {
1590 //3 formats:
1591 // 1 dst + 1 src (load)
1592 // 0 dst + 2 src (store)
1593 // 1 dst + 2 src (atomic)
1594 int opNum = 0;
1595
1596 // Needed because can't take addr of bitfield
1597 int reg = 0;
1598
1599 if (getNumOperands() > 2)
1600 assert(isAtomic());
1601
1602 reg = extData.ADDR;
1603 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1604 false, true, false);
1605 opNum++;
1606
1607 if (numSrcRegOperands() == 2) {
1608 reg = extData.DATA;
1609 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1610 false, true, false);
1611 opNum++;
1612 }
1613
1614 if (numDstRegOperands()) {
1615 reg = extData.VDST;
1616 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1617 false, true, false);
1618 }
1619
1620 assert(srcOps.size() == numSrcRegOperands());
1621 assert(dstOps.size() == numDstRegOperands());
1622 }
1623
1624 void
1626 {
1627 //3 formats:
1628 // 1 dst + 2 src (load)
1629 // 0 dst + 3 src (store)
1630 // 1 dst + 3 src (atomic)
1631 int opNum = 0;
1632
1633 // Needed because can't take addr of bitfield
1634 int reg = 0;
1635
1636 if (getNumOperands() > 3)
1637 assert(isAtomic());
1638
1639 reg = extData.ADDR;
1640 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1641 false, true, false);
1642 opNum++;
1643
1644 if (numSrcRegOperands() == 2) {
1645 reg = extData.SADDR;
1646 // 0x7f (off) means the sgpr is not used. Don't read it
1647 if (reg != 0x7f) {
1648 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1649 true, false, false);
1650 }
1651 opNum++;
1652 }
1653
1654 if (numSrcRegOperands() == 3) {
1655 reg = extData.DATA;
1656 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1657 false, true, false);
1658 opNum++;
1659
1660 reg = extData.SADDR;
1661 // 0x7f (off) means the sgpr is not used. Don't read it
1662 if (reg != 0x7f) {
1663 srcOps.emplace_back(reg, getOperandSize(opNum), true,
1664 true, false, false);
1665 }
1666 opNum++;
1667 }
1668
1669 if (numDstRegOperands()) {
1670 reg = extData.VDST;
1671 dstOps.emplace_back(reg, getOperandSize(opNum), false,
1672 false, true, false);
1673 }
1674
1675 reg = extData.SADDR;
1676 if (reg != 0x7f) {
1677 assert(srcOps.size() == numSrcRegOperands());
1678 } else {
1679 assert(srcOps.size() == numSrcRegOperands() - 1);
1680 }
1681 assert(dstOps.size() == numDstRegOperands());
1682 }
1683
1684 int
1686 {
1687 return 8;
1688 } // instSize
1689
1690 void
1692 {
1693 // One of the flat subtypes should be specified via flags
1694 assert(isFlat() ^ isFlatGlobal());
1695
1696 if (isFlat()) {
1698 } else if (isFlatGlobal()) {
1700 } else {
1701 panic("Unknown flat subtype!\n");
1702 }
1703 }
1704
1705 void
1707 {
1708 std::stringstream dis_stream;
1709 dis_stream << _opcode << " ";
1710
1711 if (isLoad())
1712 dis_stream << "v" << extData.VDST << ", ";
1713
1714 dis_stream << "v[" << extData.ADDR << ":" << extData.ADDR + 1 << "]";
1715
1716 if (isStore())
1717 dis_stream << ", v" << extData.DATA;
1718
1719 disassembly = dis_stream.str();
1720 }
1721
1722 void
1724 {
1725 // Replace flat_ with global_ in assembly string
1726 std::string global_opcode = _opcode;
1727 global_opcode.replace(0, 4, "global");
1728
1729 std::stringstream dis_stream;
1730 dis_stream << global_opcode << " ";
1731
1732 if (isLoad())
1733 dis_stream << "v" << extData.VDST << ", ";
1734
1735 if (extData.SADDR == 0x7f)
1736 dis_stream << "v[" << extData.ADDR << ":" << extData.ADDR+1 << "]";
1737 else
1738 dis_stream << "v" << extData.ADDR;
1739
1740 if (isStore())
1741 dis_stream << ", v" << extData.DATA;
1742
1743 if (extData.SADDR == 0x7f)
1744 dis_stream << ", off";
1745 else
1746 dis_stream << ", s[" << extData.SADDR << ":" << extData.SADDR+1
1747 << "]";
1748
1749 if (instData.OFFSET)
1750 dis_stream << " offset:" << instData.OFFSET;
1751
1752 disassembly = dis_stream.str();
1753 }
1754} // namespace VegaISA
1755} // 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
void initOperandInfo() override
Inst_DS(InFmt_DS *, const std::string &opcode)
void generateDisassembly() override
int instSize() const override
Inst_EXP(InFmt_EXP *, const std::string &opcode)
void initOperandInfo() override
int instSize() const override
Inst_FLAT(InFmt_FLAT *, const std::string &opcode)
void generateDisassembly() override
void initOperandInfo() override
int instSize() const override
int instSize() const override
void initOperandInfo() override
Inst_MIMG(InFmt_MIMG *, const std::string &opcode)
int instSize() const override
void initOperandInfo() override
Inst_MTBUF(InFmt_MTBUF *, const std::string &opcode)
void initOperandInfo() override
void generateDisassembly() override
Inst_MUBUF(InFmt_MUBUF *, const std::string &opcode)
int instSize() const override
void initOperandInfo() override
Inst_SMEM(InFmt_SMEM *, const std::string &opcode)
void generateDisassembly() override
int instSize() const override
int instSize() const override
void generateDisassembly() override
void initOperandInfo() override
Inst_SOP1(InFmt_SOP1 *, const std::string &opcode)
bool hasSecondDword(InFmt_SOP1 *)
bool hasSecondDword(InFmt_SOP2 *)
void generateDisassembly() override
Inst_SOP2(InFmt_SOP2 *, const std::string &opcode)
void initOperandInfo() override
int instSize() const override
int instSize() const override
bool hasSecondDword(InFmt_SOPC *)
void generateDisassembly() override
void initOperandInfo() override
Inst_SOPC(InFmt_SOPC *, const std::string &opcode)
Inst_SOPK(InFmt_SOPK *, const std::string &opcode)
int instSize() const override
void generateDisassembly() override
bool hasSecondDword(InFmt_SOPK *)
void initOperandInfo() override
void generateDisassembly() override
void initOperandInfo() override
int instSize() const override
Inst_SOPP(InFmt_SOPP *, const std::string &opcode)
int instSize() const override
Inst_VINTRP(InFmt_VINTRP *, const std::string &opcode)
Inst_VOP1(InFmt_VOP1 *, const std::string &opcode)
void generateDisassembly() override
void initOperandInfo() override
int instSize() const override
bool hasSecondDword(InFmt_VOP1 *)
void initOperandInfo() override
int instSize() const override
bool hasSecondDword(InFmt_VOP2 *)
Inst_VOP2(InFmt_VOP2 *, const std::string &opcode)
void generateDisassembly() override
Inst_VOP3A(InFmt_VOP3A *, const std::string &opcode, bool sgpr_dst)
void generateDisassembly() 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 initOperandInfo() override
Inst_VOP3B(InFmt_VOP3B *, const std::string &opcode)
void initOperandInfo() override
void generateDisassembly() override
int instSize() const override
bool hasSecondDword(InFmt_VOPC *)
void generateDisassembly() override
void initOperandInfo() override
int instSize() const override
Inst_VOPC(InFmt_VOPC *, const std::string &opcode)
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
This is a simple scalar statistic, like a counter.
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 24, 21 > opcode
Definition types.hh:92
bool isVectorReg(int opIdx)
Definition registers.cc:241
InstFormat * MachInst
used to represent the encoding of a VEGA 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:228
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:56 for gem5 by doxygen 1.9.7