gem5  v22.1.0.0
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 
36 namespace gem5
37 {
38 
39 namespace Gcn3ISA
40 {
41  // --- Inst_SOP2 base class methods ---
42 
43  Inst_SOP2::Inst_SOP2(InFmt_SOP2 *iFmt, const std::string &opcode)
45  {
46  setFlag(Scalar);
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 
71  reg = instData.SSRC1;
72  srcOps.emplace_back(reg, getOperandSize(opNum), true,
73  isScalarReg(instData.SSRC1), false, false);
74  opNum++;
75 
76  reg = instData.SDST;
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 
109  if (instData.SSRC0 == REG_SRC_LITERAL) {
110  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
111  << _srcLiteral << ", ";
112  } else {
113  dis_stream << opSelectorToRegSym(instData.SSRC0) << ", ";
114  }
115 
116  if (instData.SSRC1 == REG_SRC_LITERAL) {
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  {
131  setFlag(Scalar);
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;
156  if (numSrcRegOperands() == getNumOperands()) {
157  srcOps.emplace_back(reg, getOperandSize(opNum), true,
158  isScalarReg(reg), false, false);
159  opNum++;
160  }
161 
162  reg = instData.SIMM16;
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  {
226  setFlag(Scalar);
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 
287  if (instData.SSRC0 == REG_SRC_LITERAL) {
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  {
302  setFlag(Scalar);
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 
331  reg = instData.SSRC1;
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 
361  if (instData.SSRC0 == REG_SRC_LITERAL) {
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 
368  if (instData.SSRC1 == REG_SRC_LITERAL) {
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  {
383  setFlag(Scalar);
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  {
482  setFlag(Scalar);
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()) {
512  reg = instData.SDATA;
513  if (numSrcRegOperands() == getNumOperands()) {
514  srcOps.emplace_back(reg, getOperandSize(opNum), true,
515  isScalarReg(reg), false, false);
516  opNum++;
517  }
518 
519  reg = instData.SBASE;
520  srcOps.emplace_back(reg, getOperandSize(opNum), true,
521  true, false, false);
522  opNum++;
523 
524  reg = extData.OFFSET;
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()) {
536  reg = instData.SDATA;
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 
623  reg = instData.VSRC1;
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) ||
693  (instData.SRC0 == REG_SRC_DPP) ||
694  (instData.SRC0 == REG_SRC_SWDA)) {
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) ||
803  (instData.SRC0 == REG_SRC_DPP) ||
804  (instData.SRC0 == REG_SRC_SWDA)) {
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 
852  reg = instData.VSRC1;
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 
904  Inst_VINTRP::Inst_VINTRP(InFmt_VINTRP *iFmt, const std::string &opcode)
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) {
1216  offset += instData.OFFSET1;
1217  offset <<= 8;
1218  }
1219 
1220  if (instData.OFFSET0)
1221  offset += 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 
1281  reg = extData.SOFFSET;
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 
1372  reg = extData.SOFFSET;
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 *)
Definition: op_encodings.cc:91
void generateDisassembly() override
Inst_SOP2(InFmt_SOP2 *, const std::string &opcode)
Definition: op_encodings.cc:43
void initOperandInfo() override
Definition: op_encodings.cc:61
int instSize() const override
Definition: op_encodings.cc:85
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.
Definition: statistics.hh:1931
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 Wed Dec 21 2022 10:22:23 for gem5 by doxygen 1.9.1