gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
op_encodings.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2017 Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * For use for simulation and test purposes only
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Authors: Anthony Gutierrez
34  */
35 
37 
38 #include <iomanip>
39 
40 namespace Gcn3ISA
41 {
42  // --- Inst_SOP2 base class methods ---
43 
44  Inst_SOP2::Inst_SOP2(InFmt_SOP2 *iFmt, const std::string &opcode)
45  : GCN3GPUStaticInst(opcode)
46  {
47  setFlag(Scalar);
48 
49  // copy first instruction DWORD
50  instData = iFmt[0];
51  if (hasSecondDword(iFmt)) {
52  // copy second instruction DWORD into union
53  extData = ((MachInst)iFmt)[1];
54  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
55  varSize = 4 + 4;
56  } else {
57  varSize = 4;
58  } // if
59  } // Inst_SOP2
60 
61  int
63  {
64  return varSize;
65  } // instSize
66 
67  bool
69  {
70  if (iFmt->SSRC0 == REG_SRC_LITERAL)
71  return true;
72 
73  if (iFmt->SSRC1 == REG_SRC_LITERAL)
74  return true;
75 
76  return false;
77  }
78 
79  void
81  {
82  std::stringstream dis_stream;
83  dis_stream << _opcode << " ";
84  dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
85 
87  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
88  << _srcLiteral << ", ";
89  } else {
90  dis_stream << opSelectorToRegSym(instData.SSRC0) << ", ";
91  }
92 
94  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
95  << _srcLiteral;
96  } else {
97  dis_stream << opSelectorToRegSym(instData.SSRC1);
98  }
99 
100  disassembly = dis_stream.str();
101  }
102 
103  bool
105  {
106  assert(opIdx >= 0);
107  assert(opIdx < getNumOperands());
108 
109  switch (opIdx) {
110  case 0:
111  return isScalarReg(instData.SSRC0);
112  case 1:
113  return isScalarReg(instData.SSRC1);
114  case 2:
115  return isScalarReg(instData.SDST);
116  default:
117  fatal("Operand at idx %i does not exist\n", opIdx);
118  return false;
119  }
120  }
121 
122  bool
124  {
125  assert(opIdx >= 0);
126  assert(opIdx < getNumOperands());
127 
128  // SOP2 instructions cannot access VGPRs
129  return false;
130  }
131 
132  int
134  {
135  assert(opIdx >= 0);
136  assert(opIdx < getNumOperands());
137 
138  switch (opIdx) {
139  case 0:
141  gpuDynInst->wavefront()->reservedScalarRegs);
142  case 1:
144  gpuDynInst->wavefront()->reservedScalarRegs);
145  case 2:
147  gpuDynInst->wavefront()->reservedScalarRegs);
148  default:
149  fatal("Operand at idx %i does not exist\n", opIdx);
150  return -1;
151  }
152  }
153 
154  // --- Inst_SOPK base class methods ---
155 
156  Inst_SOPK::Inst_SOPK(InFmt_SOPK *iFmt, const std::string &opcode)
157  : GCN3GPUStaticInst(opcode)
158  {
159  setFlag(Scalar);
160 
161  // copy first instruction DWORD
162  instData = iFmt[0];
163  } // Inst_SOPK
164 
166  {
167  } // ~Inst_SOPK
168 
169  int
171  {
172  return 4;
173  } // instSize
174 
175  void
177  {
178  std::stringstream dis_stream;
179  dis_stream << _opcode << " ";
180  dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
181 
182  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(4)
183  << instData.SIMM16;
184 
185  disassembly = dis_stream.str();
186  }
187 
188  bool
190  {
191  assert(opIdx >= 0);
192  assert(opIdx < getNumOperands());
193 
194  switch (opIdx) {
195  case 0:
196  return false;
197  case 1:
198  return isScalarReg(instData.SDST);
199  default:
200  fatal("Operand at idx %i does not exist\n", opIdx);
201  return false;
202  }
203  }
204 
205  bool
207  {
208  assert(opIdx >= 0);
209  assert(opIdx < getNumOperands());
210 
211  // SOPK instruction cannot access VGPRs
212  return false;
213  }
214 
215  int
217  {
218  assert(opIdx >= 0);
219  assert(opIdx < getNumOperands());
220 
221  switch (opIdx) {
222  case 0:
223  return -1;
224  case 1:
226  gpuDynInst->wavefront()->reservedScalarRegs);
227  default:
228  fatal("Operand at idx %i does not exist\n", opIdx);
229  return -1;
230  }
231  }
232 
233  // --- Inst_SOP1 base class methods ---
234 
235  Inst_SOP1::Inst_SOP1(InFmt_SOP1 *iFmt, const std::string &opcode)
236  : GCN3GPUStaticInst(opcode)
237  {
238  setFlag(Scalar);
239 
240  // copy first instruction DWORD
241  instData = iFmt[0];
242  if (hasSecondDword(iFmt)) {
243  // copy second instruction DWORD into union
244  extData = ((MachInst)iFmt)[1];
245  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
246  varSize = 4 + 4;
247  } else {
248  varSize = 4;
249  } // if
250  } // Inst_SOP1
251 
253  {
254  } // ~Inst_SOP1
255 
256  int
258  {
259  return varSize;
260  } // instSize
261 
262  bool
264  {
265  if (iFmt->SSRC0 == REG_SRC_LITERAL)
266  return true;
267 
268  return false;
269  }
270 
271  void
273  {
274  std::stringstream dis_stream;
275  dis_stream << _opcode << " ";
276  dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
277 
278  if (instData.SSRC0 == REG_SRC_LITERAL) {
279  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
280  << extData.imm_u32;
281  } else {
282  dis_stream << opSelectorToRegSym(instData.SSRC0);
283  }
284 
285  disassembly = dis_stream.str();
286  }
287 
288  bool
290  {
291  assert(opIdx >= 0);
292  assert(opIdx < getNumOperands());
293 
294  switch (opIdx) {
295  case 0:
296  return isScalarReg(instData.SSRC0);
297  case 1:
298  return isScalarReg(instData.SDST);
299  default:
300  fatal("Operand at idx %i does not exist\n", opIdx);
301  return false;
302  }
303  }
304 
305  bool
307  {
308  assert(opIdx >= 0);
309  assert(opIdx < getNumOperands());
310 
311  // SOP1 instruction cannot access VGPRs
312  return false;
313  }
314 
315  int
317  {
318  assert(opIdx >= 0);
319  assert(opIdx < getNumOperands());
320 
321  switch (opIdx) {
322  case 0:
324  gpuDynInst->wavefront()->reservedScalarRegs);
325  case 1:
327  gpuDynInst->wavefront()->reservedScalarRegs);
328  default:
329  fatal("Operand at idx %i does not exist\n", opIdx);
330  return -1;
331  }
332  }
333 
334  // --- Inst_SOPC base class methods ---
335 
336  Inst_SOPC::Inst_SOPC(InFmt_SOPC *iFmt, const std::string &opcode)
337  : GCN3GPUStaticInst(opcode)
338  {
339  setFlag(Scalar);
340 
341  // copy first instruction DWORD
342  instData = iFmt[0];
343  if (hasSecondDword(iFmt)) {
344  // copy second instruction DWORD into union
345  extData = ((MachInst)iFmt)[1];
346  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
347  varSize = 4 + 4;
348  } else {
349  varSize = 4;
350  } // if
351  } // Inst_SOPC
352 
354  {
355  } // ~Inst_SOPC
356 
357  int
359  {
360  return varSize;
361  } // instSize
362 
363  bool
365  {
366  if (iFmt->SSRC0 == REG_SRC_LITERAL)
367  return true;
368 
369  if (iFmt->SSRC1 == REG_SRC_LITERAL)
370  return true;
371 
372  return false;
373  }
374 
375  void
377  {
378  std::stringstream dis_stream;
379  dis_stream << _opcode << " ";
380 
381  if (instData.SSRC0 == REG_SRC_LITERAL) {
382  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
383  << extData.imm_u32;
384  } else {
385  dis_stream << opSelectorToRegSym(instData.SSRC0) << ", ";
386  }
387 
388  if (instData.SSRC1 == REG_SRC_LITERAL) {
389  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
390  << extData.imm_u32;
391  } else {
392  dis_stream << opSelectorToRegSym(instData.SSRC1);
393  }
394 
395  disassembly = dis_stream.str();
396  }
397 
398  bool
400  {
401  assert(opIdx >= 0);
402  assert(opIdx < getNumOperands());
403 
404  switch (opIdx) {
405  case 0:
406  // SSRC0 is always a scalar reg or a constant
407  return isScalarReg(instData.SSRC0);
408  case 1:
409  // SSRC1 is always a scalar reg or a constant
410  return isScalarReg(instData.SSRC1);
411  default:
412  fatal("Operand at idx %i does not exist\n", opIdx);
413  return false;
414  }
415  }
416 
417  bool
419  {
420  assert(opIdx >= 0);
421  assert(opIdx < getNumOperands());
422 
423  // SOPC instructions cannot access VGPRs
424  return false;
425  }
426 
427  int
429  {
430  assert(opIdx >= 0);
431  assert(opIdx < getNumOperands());
432 
433  switch (opIdx) {
434  case 0:
436  gpuDynInst->wavefront()->reservedScalarRegs);
437  case 1:
439  gpuDynInst->wavefront()->reservedScalarRegs);
440  default:
441  fatal("Operand at idx %i does not exist\n", opIdx);
442  return -1;
443  }
444  }
445 
446  // --- Inst_SOPP base class methods ---
447 
448  Inst_SOPP::Inst_SOPP(InFmt_SOPP *iFmt, const std::string &opcode)
449  : GCN3GPUStaticInst(opcode)
450  {
451  setFlag(Scalar);
452 
453  // copy first instruction DWORD
454  instData = iFmt[0];
455  } // Inst_SOPP
456 
458  {
459  } // ~Inst_SOPP
460 
461  int
463  {
464  return 4;
465  } // instSize
466 
467  void
469  {
470  std::stringstream dis_stream;
471  dis_stream << _opcode;
472 
473  switch (instData.OP) {
474  case 8:
475  {
476  dis_stream << " ";
477  int dest = 4 * instData.SIMM16 + 4;
478  dis_stream << "label_" << std::hex << dest;
479  }
480  break;
481  case 12:
482  {
483  dis_stream << " ";
484 
485  int vm_cnt = 0;
486  int exp_cnt = 0;
487  int lgkm_cnt = 0;
488 
489  vm_cnt = bits<uint16_t>(instData.SIMM16, 3, 0);
490  exp_cnt = bits<uint16_t>(instData.SIMM16, 6, 4);
491  lgkm_cnt = bits<uint16_t>(instData.SIMM16, 11, 8);
492 
493  // if the counts are not maxed out, then we
494  // print out the count value
495  if (vm_cnt != 0xf) {
496  dis_stream << "vmcnt(" << vm_cnt << ")";
497  }
498 
499  if (lgkm_cnt != 0xf) {
500  if (vm_cnt != 0xf)
501  dis_stream << " & ";
502 
503  dis_stream << "lgkmcnt(" << lgkm_cnt << ")";
504  }
505 
506  if (exp_cnt != 0x7) {
507  if (vm_cnt != 0xf || lgkm_cnt != 0xf)
508  dis_stream << " & ";
509 
510  dis_stream << "expcnt(" << exp_cnt << ")";
511  }
512  }
513  break;
514  default:
515  break;
516  }
517 
518  disassembly = dis_stream.str();
519  }
520 
521  bool
523  {
524  assert(opIdx >= 0);
525  assert(opIdx < getNumOperands());
526 
527  // SOPP instructions have a maximum of 1 operand,
528  // and it's always an immediate value
529  return false;
530  }
531 
532  bool
534  {
535  assert(opIdx >= 0);
536  assert(opIdx < getNumOperands());
537 
538  // SOPP instructions have a maximum of 1 operand,
539  // and it's always an immediate value
540  return false;
541  }
542 
543  int
545  {
546  assert(opIdx >= 0);
547  assert(opIdx < getNumOperands());
548 
549  // SOPP instructions have a maximum of 1 operand,
550  // and it's always an immediate value
551  return -1;
552  }
553 
554  // --- Inst_SMEM base class methods ---
555 
556  Inst_SMEM::Inst_SMEM(InFmt_SMEM *iFmt, const std::string &opcode)
557  : GCN3GPUStaticInst(opcode)
558  {
559  setFlag(Scalar);
560  setFlag(GlobalSegment);
561 
562  // copy first instruction DWORD
563  instData = iFmt[0];
564  // copy second instruction DWORD
565  extData = ((InFmt_SMEM_1 *)iFmt)[1];
566  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
567 
568  if (instData.GLC)
569  setFlag(GloballyCoherent);
570  } // Inst_SMEM
571 
573  {
574  } // ~Inst_SMEM
575 
576  int
578  {
579  return 8;
580  } // instSize
581 
582  void
584  {
585  std::stringstream dis_stream;
586  dis_stream << _opcode << " ";
587  if (numDstRegOperands()) {
588  if (getOperandSize(getNumOperands() - 1) > 4) {
589  dis_stream << "s[" << instData.SDATA << ":"
591  4 - 1 << "], ";
592  } else {
593  dis_stream << "s" << instData.SDATA << ", ";
594  }
595  }
596 
597  // SBASE has an implied LSB of 0, so we need
598  // to shift by one to get the actual value
599  dis_stream << "s[" << (instData.SBASE << 1) << ":"
600  << ((instData.SBASE << 1) + 1) << "], ";
601 
602  if (instData.IMM) {
603  // IMM == 1 implies OFFSET should be
604  // used as the offset
605  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(2)
606  << extData.OFFSET;
607  } else {
608  // IMM == 0 implies OFFSET should be
609  // used to specify SGRP in which the
610  // offset is held
611  dis_stream << "s" << extData.OFFSET;
612  }
613 
614  disassembly = dis_stream.str();
615  }
616 
617  bool
619  {
620  assert(opIdx >= 0);
621  assert(opIdx < getNumOperands());
622 
623  switch (opIdx) {
624  case 0:
625  // SBASE is always a scalar
626  return true;
627  case 1:
628  if (instData.IMM) {
629  return false;
630  } else {
631  return isScalarReg(extData.OFFSET);
632  }
633  case 2:
634  return isScalarReg(instData.SDATA);
635  default:
636  fatal("Operand at idx %i does not exist\n", opIdx);
637  return false;
638  }
639  }
640 
641  bool
643  {
644  assert(opIdx >= 0);
645  assert(opIdx < getNumOperands());
646 
647  // SMEM instructions cannot access VGPRs
648  return false;
649  }
650 
651  int
653  {
654  assert(opIdx >= 0);
655  assert(opIdx < getNumOperands());
656 
657  switch (opIdx) {
658  case 0:
659  // SBASE has an implied LSB of 0, so we need
660  // to shift by one to get the actual value
661  return opSelectorToRegIdx(instData.SBASE << 1,
662  gpuDynInst->wavefront()->reservedScalarRegs);
663  case 1:
664  if (instData.IMM) {
665  // operand is an immediate value, not a register
666  return -1;
667  } else {
668  return extData.OFFSET;
669  }
670  case 2:
672  gpuDynInst->wavefront()->reservedScalarRegs);
673  default:
674  fatal("Operand at idx %i does not exist\n", opIdx);
675  return -1;
676  }
677  }
678 
679  // --- Inst_VOP2 base class methods ---
680 
681  Inst_VOP2::Inst_VOP2(InFmt_VOP2 *iFmt, const std::string &opcode)
682  : GCN3GPUStaticInst(opcode)
683  {
684  // copy first instruction DWORD
685  instData = iFmt[0];
686  if (hasSecondDword(iFmt)) {
687  // copy second instruction DWORD into union
688  extData = ((MachInst)iFmt)[1];
689  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
690  varSize = 4 + 4;
691  if (iFmt->SRC0 == REG_SRC_DPP) {
692  setFlag(IsDPP);
693  } else if (iFmt->SRC0 == REG_SRC_SWDA) {
694  setFlag(IsSDWA);
695  }
696  } else {
697  varSize = 4;
698  } // if
699  } // Inst_VOP2
700 
702  {
703  } // ~Inst_VOP2
704 
705  int
707  {
708  return varSize;
709  } // instSize
710 
711  bool
713  {
714  /*
715  There are a few cases where VOP2 instructions have a second dword:
716 
717  1. SRC0 is a literal
718  2. SRC0 is being used to add a data parallel primitive (DPP)
719  operation to the instruction.
720  3. SRC0 is being used for sub d-word addressing (SDWA) of the
721  operands in the instruction.
722  4. VOP2 instructions also have four special opcodes:',
723  V_MADMK_{F16, F32} (0x24, 0x17), and V_MADAK_{F16, F32}',
724  (0x25, 0x18), that are always 64b. the only way to',
725  detect these special cases is to explicitly check,',
726  the opcodes',
727  */
728  if (iFmt->SRC0 == REG_SRC_LITERAL || (iFmt->SRC0 == REG_SRC_DPP) ||
729  (iFmt->SRC0 == REG_SRC_SWDA) || iFmt->OP == 0x17 ||
730  iFmt->OP == 0x18 || iFmt->OP == 0x24 || iFmt->OP == 0x25)
731  return true;
732 
733  return false;
734  }
735 
736  void
738  {
739  std::stringstream dis_stream;
740  dis_stream << _opcode << " ";
741  dis_stream << "v" << instData.VDST << ", ";
742 
743  if (writesVCC())
744  dis_stream << "vcc, ";
745 
746  if ((instData.SRC0 == REG_SRC_LITERAL) ||
747  (instData.SRC0 == REG_SRC_DPP) ||
748  (instData.SRC0 == REG_SRC_SWDA)) {
749  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
750  << _srcLiteral << ", ";
751  } else {
752  dis_stream << opSelectorToRegSym(instData.SRC0) << ", ";
753  }
754 
755  // VOP2 instructions have four special opcodes:',
756  // V_MADMK_{F16, F32} (0x24, 0x17), and V_MADAK_{F16, F32}',
757  // (0x25, 0x18), that are always 64b. the only way to',
758  // detect these special cases is to explicitly check,',
759  // the opcodes',
760  if (instData.OP == 0x17 || instData.OP == 0x18 || instData.OP == 0x24
761  || instData.OP == 0x25) {
762  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
763  << extData.imm_u32 << ", ";
764  }
765 
766  dis_stream << "v" << instData.VSRC1;
767 
768  if (readsVCC())
769  dis_stream << ", vcc";
770 
771  disassembly = dis_stream.str();
772  }
773 
774  bool
776  {
777  assert(opIdx >= 0);
778  assert(opIdx < getNumOperands());
779 
780  switch (opIdx) {
781  case 0:
782  // SRC0 may be a scalar or vector register, an
783  // inline constant, or a special HW register
784  return isScalarReg(instData.SRC0);
785  case 1:
786  // instData.VSRC1 is never a scalar reg
787  return false;
788  case 2:
789  if (readsVCC()) {
790  return true;
791  } else {
792  // instData.VDST is never a scalar reg
793  return false;
794  }
795  case 3:
796  // if a VOP2 instruction has more than 3 ops
797  // it must read from or write to VCC, and
798  // VCC is always in an SGPR
799  assert(readsVCC() || writesVCC());
800  if (readsVCC()) {
801  return false;
802  } else {
803  return true;
804  }
805  case 4:
806  // if a VOP2 instruction has more than 4 ops
807  // it must read from and write to VCC, and
808  // VCC is always in an SGPR
809  assert(writesVCC() && readsVCC());
810  return true;
811  default:
812  fatal("Operand at idx %i does not exist\n", opIdx);
813  return false;
814  }
815  }
816 
817  bool
819  {
820  assert(opIdx >= 0);
821  assert(opIdx < getNumOperands());
822 
823  switch (opIdx) {
824  case 0:
825  // SRC0 may be a scalar or vector register, an
826  // inline constant, or a special HW register
827  return isVectorReg(instData.SRC0);
828  case 1:
829  // instData.VSRC1 is always a vector reg
830  return true;
831  case 2:
832  if (readsVCC()) {
833  return false;
834  } else {
835  // instData.VDST is always a vector reg
836  return true;
837  }
838  case 3:
839  // if a VOP2 instruction has more than 3 ops
840  // it must read from or write to VCC, and
841  // VCC is always in an SGPR
842  assert(writesVCC() || readsVCC());
843  if (readsVCC()) {
844  return true;
845  } else {
846  return false;
847  }
848  case 4:
849  // if a VOP2 instruction has more than 4 ops
850  // it must read from and write to VCC, and
851  // VCC is always in an SGPR
852  assert(writesVCC() && readsVCC());
853  return false;
854  default:
855  fatal("Operand at idx %i does not exist\n", opIdx);
856  return false;
857  }
858  }
859 
860  int
862  {
863  assert(opIdx >= 0);
864  assert(opIdx < getNumOperands());
865 
866  switch (opIdx) {
867  case 0:
869  gpuDynInst->wavefront()->reservedScalarRegs);
870  case 1:
871  return instData.VSRC1;
872  case 2:
873  if (readsVCC()) {
875  gpuDynInst->wavefront()->reservedScalarRegs);
876  } else {
877  return instData.VDST;
878  }
879  case 3:
880  assert(writesVCC() || readsVCC());
881  if (readsVCC()) {
882  return instData.VDST;
883  } else {
885  gpuDynInst->wavefront()->reservedScalarRegs);
886  }
887  case 4:
888  assert(writesVCC() && readsVCC());
890  gpuDynInst->wavefront()->reservedScalarRegs);
891  default:
892  fatal("Operand at idx %i does not exist\n", opIdx);
893  return -1;
894  }
895  }
896 
897  // --- Inst_VOP1 base class methods ---
898 
899  Inst_VOP1::Inst_VOP1(InFmt_VOP1 *iFmt, const std::string &opcode)
900  : GCN3GPUStaticInst(opcode)
901  {
902  // copy first instruction DWORD
903  instData = iFmt[0];
904  if (hasSecondDword(iFmt)) {
905  // copy second instruction DWORD into union
906  extData = ((MachInst)iFmt)[1];
907  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
908  varSize = 4 + 4;
909  if (iFmt->SRC0 == REG_SRC_DPP) {
910  setFlag(IsDPP);
911  } else if (iFmt->SRC0 == REG_SRC_SWDA) {
912  setFlag(IsSDWA);
913  }
914  } else {
915  varSize = 4;
916  } // if
917  } // Inst_VOP1
918 
920  {
921  } // ~Inst_VOP1
922 
923  int
925  {
926  return varSize;
927  } // instSize
928 
929  bool
931  {
932  /*
933  There are several cases where VOP1 instructions have a second dword:
934 
935  1. SRC0 is a literal.
936  2. SRC0 is being used to add a data parallel primitive (DPP)
937  operation to the instruction.
938  3. SRC0 is being used for sub d-word addressing (SDWA) of the
939  operands in the instruction.
940  */
941  if ((iFmt->SRC0 == REG_SRC_LITERAL) || (iFmt->SRC0 == REG_SRC_DPP) ||
942  (iFmt->SRC0 == REG_SRC_SWDA))
943  return true;
944 
945  return false;
946  }
947 
948  void
950  {
951  std::stringstream dis_stream;
952  dis_stream << _opcode << " ";
953  dis_stream << "v" << instData.VDST << ", ";
954 
955  if ((instData.SRC0 == REG_SRC_LITERAL) ||
956  (instData.SRC0 == REG_SRC_DPP) ||
957  (instData.SRC0 == REG_SRC_SWDA)) {
958  dis_stream << "0x" << std::hex << std::setfill('0') << std::setw(8)
959  << _srcLiteral;
960  } else {
961  dis_stream << opSelectorToRegSym(instData.SRC0);
962  }
963 
964  disassembly = dis_stream.str();
965  }
966 
967  bool
969  {
970  assert(opIdx >= 0);
971  assert(opIdx < getNumOperands());
972 
973  switch (opIdx) {
974  case 0:
975  return isScalarReg(instData.SRC0);
976  case 1:
977  // VDST is never a scalar reg
978  return false;
979  default:
980  fatal("Operand at idx %i does not exist\n", opIdx);
981  return false;
982  }
983  }
984 
985  bool
987  {
988  assert(opIdx >= 0);
989  assert(opIdx < getNumOperands());
990 
991  switch (opIdx) {
992  case 0:
993  return isVectorReg(instData.SRC0);
994  case 1:
995  // VDST is always a vector reg
996  return true;
997  default:
998  fatal("Operand at idx %i does not exist\n", opIdx);
999  return false;
1000  }
1001  }
1002 
1003  int
1005  {
1006  assert(opIdx >= 0);
1007  assert(opIdx < getNumOperands());
1008 
1009  switch (opIdx) {
1010  case 0:
1012  gpuDynInst->wavefront()->reservedScalarRegs);
1013  case 1:
1014  return instData.VDST;
1015  default:
1016  fatal("Operand at idx %i does not exist\n", opIdx);
1017  return -1;
1018  }
1019  }
1020 
1021  // --- Inst_VOPC base class methods ---
1022 
1023  Inst_VOPC::Inst_VOPC(InFmt_VOPC *iFmt, const std::string &opcode)
1024  : GCN3GPUStaticInst(opcode)
1025  {
1026  // copy first instruction DWORD
1027  instData = iFmt[0];
1028  if (hasSecondDword(iFmt)) {
1029  // copy second instruction DWORD into union
1030  extData = ((MachInst)iFmt)[1];
1031  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1032  varSize = 4 + 4;
1033  if (iFmt->SRC0 == REG_SRC_DPP) {
1034  setFlag(IsDPP);
1035  } else if (iFmt->SRC0 == REG_SRC_SWDA) {
1036  setFlag(IsSDWA);
1037  }
1038  } else {
1039  varSize = 4;
1040  } // if
1041  } // Inst_VOPC
1042 
1044  {
1045  } // ~Inst_VOPC
1046 
1047  int
1049  {
1050  return varSize;
1051  } // instSize
1052 
1053  bool
1055  {
1056  /*
1057  There are several cases where VOPC instructions have a second dword:
1058 
1059  1. SRC0 is a literal.
1060  2. SRC0 is being used to add a data parallel primitive (DPP)
1061  operation to the instruction.
1062  3. SRC0 is being used for sub d-word addressing (SDWA) of the
1063  operands in the instruction.
1064  */
1065  if ((iFmt->SRC0 == REG_SRC_LITERAL) || (iFmt->SRC0 == REG_SRC_DPP) ||
1066  (iFmt->SRC0 == REG_SRC_SWDA))
1067  return true;
1068 
1069  return false;
1070  }
1071 
1072  void
1074  {
1075  std::stringstream dis_stream;
1076  dis_stream << _opcode << " vcc, ";
1077 
1078  dis_stream << opSelectorToRegSym(instData.SRC0) << ", ";
1079  dis_stream << "v" << instData.VSRC1;
1080 
1081  disassembly = dis_stream.str();
1082  }
1083 
1084  bool
1086  {
1087  assert(opIdx >= 0);
1088  assert(opIdx < getNumOperands());
1089 
1090  switch (opIdx) {
1091  case 0:
1092  return isScalarReg(instData.SRC0);
1093  case 1:
1094  // VSRC1 is never a scalar register
1095  return false;
1096  case 2:
1097  // VCC is always a scalar register
1098  return true;
1099  default:
1100  fatal("Operand at idx %i does not exist\n", opIdx);
1101  return false;
1102  }
1103  }
1104 
1105  bool
1107  {
1108  assert(opIdx >= 0);
1109  assert(opIdx < getNumOperands());
1110 
1111  switch (opIdx) {
1112  case 0:
1113  return isVectorReg(instData.SRC0);
1114  case 1:
1115  // VSRC1 is never a scalar register
1116  return true;
1117  case 2:
1118  // VCC is always a scalar register
1119  return false;
1120  default:
1121  fatal("Operand at idx %i does not exist\n", opIdx);
1122  return false;
1123  }
1124  }
1125 
1126  int
1128  {
1129  assert(opIdx >= 0);
1130  assert(opIdx < getNumOperands());
1131 
1132  switch (opIdx) {
1133  case 0:
1135  gpuDynInst->wavefront()->reservedScalarRegs);
1136  case 1:
1137  return instData.VSRC1;
1138  case 2:
1139  // VCC
1141  gpuDynInst->wavefront()->reservedScalarRegs);
1142  default:
1143  fatal("Operand at idx %i does not exist\n", opIdx);
1144  return -1;
1145  }
1146  }
1147 
1148  // --- Inst_VINTRP base class methods ---
1149 
1150  Inst_VINTRP::Inst_VINTRP(InFmt_VINTRP *iFmt, const std::string &opcode)
1151  : GCN3GPUStaticInst(opcode)
1152  {
1153  // copy first instruction DWORD
1154  instData = iFmt[0];
1155  } // Inst_VINTRP
1156 
1158  {
1159  } // ~Inst_VINTRP
1160 
1161  int
1163  {
1164  return 4;
1165  } // instSize
1166 
1167  // --- Inst_VOP3 base class methods ---
1168 
1169  Inst_VOP3::Inst_VOP3(InFmt_VOP3 *iFmt, const std::string &opcode,
1170  bool sgpr_dst)
1171  : GCN3GPUStaticInst(opcode), sgprDst(sgpr_dst)
1172  {
1173  // copy first instruction DWORD
1174  instData = iFmt[0];
1175  // copy second instruction DWORD
1176  extData = ((InFmt_VOP3_1 *)iFmt)[1];
1177  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1178  } // Inst_VOP3
1179 
1181  {
1182  } // ~Inst_VOP3
1183 
1184  int
1186  {
1187  return 8;
1188  } // instSize
1189 
1190  void
1192  {
1193  std::stringstream dis_stream;
1194  dis_stream << _opcode << " ";
1195  int num_regs = 0;
1196 
1197  if (getOperandSize(getNumOperands() - 1) > 4) {
1198  num_regs = getOperandSize(getNumOperands() - 1) / 4;
1199  if (sgprDst)
1200  dis_stream << "s[";
1201  else
1202  dis_stream << "v[";
1203  dis_stream << instData.VDST << ":" << instData.VDST +
1204  num_regs - 1 << "], ";
1205  } else {
1206  if (sgprDst)
1207  dis_stream << "s";
1208  else
1209  dis_stream << "v";
1210  dis_stream << instData.VDST << ", ";
1211  }
1212 
1213  num_regs = getOperandSize(0) / 4;
1214 
1215  if (extData.NEG & 0x1) {
1216  dis_stream << "-" << opSelectorToRegSym(extData.SRC0, num_regs);
1217  } else {
1218  dis_stream << opSelectorToRegSym(extData.SRC0, num_regs);
1219  }
1220 
1221  if (numSrcRegOperands() > 1) {
1222  num_regs = getOperandSize(1) / 4;
1223 
1224  if (extData.NEG & 0x2) {
1225  dis_stream << ", -"
1226  << opSelectorToRegSym(extData.SRC1, num_regs);
1227  } else {
1228  dis_stream << ", "
1229  << opSelectorToRegSym(extData.SRC1, num_regs);
1230  }
1231  }
1232 
1233  if (numSrcRegOperands() > 2) {
1234  num_regs = getOperandSize(2) / 4;
1235 
1236  if (extData.NEG & 0x4) {
1237  dis_stream << ", -"
1238  << opSelectorToRegSym(extData.SRC2, num_regs);
1239  } else {
1240  dis_stream << ", "
1241  << opSelectorToRegSym(extData.SRC2, num_regs);
1242  }
1243  }
1244 
1245  disassembly = dis_stream.str();
1246  }
1247 
1248  bool
1250  {
1251  assert(opIdx >= 0);
1252  assert(opIdx < getNumOperands());
1253 
1254  switch (opIdx) {
1255  case 0:
1256  // SRC0 may be a scalar or vector register, an
1257  // inline constant, or a special HW register
1258  return isScalarReg(extData.SRC0);
1259  case 1:
1260  if (numSrcRegOperands() > 1) {
1261  // if we have more than 1 source operand then
1262  // op index 1 corresponds to SRC1. SRC1 may be
1263  // a scalar or vector register, an inline
1264  // constant, or a special HW register
1265  return isScalarReg(extData.SRC1);
1266  } else {
1267  // if we only have 1 source operand, opIdx 1
1268  // will be VDST, and VDST is only a scalar
1269  // for v_cmp instructions
1270  if (sgprDst)
1271  return true;
1272  return false;
1273  }
1274  case 2:
1275  if (numSrcRegOperands() > 2) {
1276  // if we have more than 2 source operand then
1277  // op index 2 corresponds to SRC2. SRC2 may be
1278  // a scalar or vector register, an inline
1279  // constant, or a special HW register
1280  return isScalarReg(extData.SRC2);
1281  } else if (numSrcRegOperands() == 2) {
1282  // if we only have 2 source operands, opIdx 2
1283  // will be VDST, and VDST is only a scalar
1284  // for v_cmp instructions
1285  if (sgprDst)
1286  return true;
1287  return false;
1288  } else {
1289  // if this idx doesn't correspond to SRCX or
1290  // VDST then it must be a VCC read or write,
1291  // and VCC is always stored in an SGPR pair
1292  assert(writesVCC() || readsVCC());
1293  return true;
1294  }
1295  case 3:
1296  if (numSrcRegOperands() == 3) {
1297  // if we have 3 source operands, opIdx 3
1298  // will be VDST, and VDST is only a scalar
1299  // for v_cmp instructions
1300  if (sgprDst)
1301  return true;
1302  return false;
1303  } else {
1304  // if this idx doesn't correspond to VDST
1305  // then it must be a VCC read or write, and
1306  // and VCC is always stored in an SGPR pair
1307  assert(writesVCC() || readsVCC());
1308  return true;
1309  }
1310  case 4:
1311  // if a VOP3 instruction has more than 4 ops
1312  // it must read from and write to VCC, and
1313  // VCC is always in an SGPR
1314  assert(writesVCC() || readsVCC());
1315  return true;
1316  default:
1317  fatal("Operand at idx %i does not exist\n", opIdx);
1318  return false;
1319  }
1320  }
1321 
1322  bool
1324  {
1325  assert(opIdx >= 0);
1326  assert(opIdx < getNumOperands());
1327 
1328  switch (opIdx) {
1329  case 0:
1330  // SRC0 may be a scalar or vector register, an
1331  // inline constant, or a special HW register
1332  return isVectorReg(extData.SRC0);
1333  case 1:
1334  if (numSrcRegOperands() > 1) {
1335  // if we have more than 1 source operand then
1336  // op index 1 corresponds to SRC1. SRC1 may be
1337  // a scalar or vector register, an inline
1338  // constant, or a special HW register
1339  return isVectorReg(extData.SRC1);
1340  } else {
1341  // if we only have 1 source operands, opIdx 1
1342  // will be VDST, and VDST is a scalar for v_cmp
1343  // instructions
1344  if (sgprDst)
1345  return false;
1346  return true;
1347  }
1348  case 2:
1349  if (numSrcRegOperands() > 2) {
1350  // if we have more than 2 source operand then
1351  // op index 2 corresponds to SRC2. SRC2 may be
1352  // a scalar or vector register, an inline
1353  // constant, or a special HW register
1354  return isVectorReg(extData.SRC2);
1355  } else if (numSrcRegOperands() == 2) {
1356  // if we only have 2 source operands, opIdx 2
1357  // will be VDST, and VDST is a scalar for v_cmp
1358  // instructions
1359  if (sgprDst)
1360  return false;
1361  return true;
1362  } else {
1363  // if this idx doesn't correspond to SRCX or
1364  // VDST then it must be a VCC read or write,
1365  // and VCC is never stored in a VGPR
1366  assert(writesVCC() || readsVCC());
1367  return false;
1368  }
1369  case 3:
1370  if (numSrcRegOperands() == 3) {
1371  // if we have 3 source operands, opIdx 3
1372  // will be VDST, and VDST is a scalar for v_cmp
1373  // instructions
1374  if (sgprDst)
1375  return false;
1376  return true;
1377  } else {
1378  // if this idx doesn't correspond to VDST
1379  // then it must be a VCC read or write, and
1380  // and VCC is never stored in a VGPR
1381  assert(writesVCC() || readsVCC());
1382  return false;
1383  }
1384  case 4:
1385  // if a VOP3 instruction has more than 4 ops
1386  // it must read from and write to VCC, and
1387  // VCC is never stored in a VGPR
1388  assert(writesVCC() || readsVCC());
1389  return false;
1390  default:
1391  fatal("Operand at idx %i does not exist\n", opIdx);
1392  return false;
1393  }
1394  }
1395 
1396  int
1398  {
1399  assert(opIdx >= 0);
1400  assert(opIdx < getNumOperands());
1401 
1402  switch (opIdx) {
1403  case 0:
1404  // SRC0
1406  gpuDynInst->wavefront()->reservedScalarRegs);
1407  case 1:
1408  if (numSrcRegOperands() > 1) {
1409  // if we have more than 1 source operand then
1410  // op index 1 corresponds to SRC1
1412  gpuDynInst->wavefront()->reservedScalarRegs);
1413  } else {
1414  // if we only have 1 source operand, opIdx 1
1415  // will be VDST
1416  if (sgprDst) {
1418  gpuDynInst->wavefront()->reservedScalarRegs);
1419  }
1420  return instData.VDST;
1421  }
1422  case 2:
1423  if (numSrcRegOperands() > 2) {
1424  // if we have more than 2 source operand then
1425  // op index 2 corresponds to SRC2. SRC2 may be
1426  // a scalar or vector register, an inline
1427  // constant, or a special HW register
1429  gpuDynInst->wavefront()->reservedScalarRegs);
1430  } else if (numSrcRegOperands() == 2) {
1431  // if we only have 2 source operands, opIdx 2
1432  // will be VDST, and VDST is always a vector
1433  // reg
1434  if (sgprDst) {
1436  gpuDynInst->wavefront()->reservedScalarRegs);
1437  }
1438  return instData.VDST;
1439  } else {
1440  // if this idx doesn't correspond to SRCX or
1441  // VDST then it must be a VCC read or write,
1442  // and VCC is never stored in a VGPR
1443  assert(writesVCC() || readsVCC());
1445  gpuDynInst->wavefront()->reservedScalarRegs);
1446  }
1447  case 3:
1448  if (numSrcRegOperands() == 3) {
1449  // if we have 3 source operands then op
1450  // idx 3 will correspond to VDST
1451  if (sgprDst) {
1453  gpuDynInst->wavefront()->reservedScalarRegs);
1454  }
1455  return instData.VDST;
1456  } else {
1457  // if this idx doesn't correspond to VDST
1458  // then it must be a VCC read or write
1459  assert(writesVCC() || readsVCC());
1461  gpuDynInst->wavefront()->reservedScalarRegs);
1462  }
1463  case 4:
1464  // if a VOP3 instruction has more than 4 ops
1465  // it must read from and write to VCC
1466  assert(writesVCC() || readsVCC());
1468  gpuDynInst->wavefront()->reservedScalarRegs);
1469  default:
1470  fatal("Operand at idx %i does not exist\n", opIdx);
1471  return -1;
1472  }
1473  }
1474 
1475  // --- Inst_VOP3_SDST_ENC base class methods ---
1476 
1478  const std::string &opcode)
1479  : GCN3GPUStaticInst(opcode)
1480  {
1481  // copy first instruction DWORD
1482  instData = iFmt[0];
1483  // copy second instruction DWORD
1484  extData = ((InFmt_VOP3_1 *)iFmt)[1];
1485  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1486  } // Inst_VOP3_SDST_ENC
1487 
1489  {
1490  } // ~Inst_VOP3_SDST_ENC
1491 
1492  int
1494  {
1495  return 8;
1496  } // instSize
1497 
1498  void
1500  {
1501  std::stringstream dis_stream;
1502  dis_stream << _opcode << " ";
1503 
1504  dis_stream << "v" << instData.VDST << ", ";
1505 
1506  if (numDstRegOperands() == 2) {
1507  if (getOperandSize(getNumOperands() - 1) > 4) {
1508  int num_regs = getOperandSize(getNumOperands() - 1) / 4;
1509  dis_stream << opSelectorToRegSym(instData.SDST, num_regs)
1510  << ", ";
1511  } else {
1512  dis_stream << opSelectorToRegSym(instData.SDST) << ", ";
1513  }
1514  }
1515 
1516  if (extData.NEG & 0x1) {
1517  dis_stream << "-" << opSelectorToRegSym(extData.SRC0) << ", ";
1518  } else {
1519  dis_stream << opSelectorToRegSym(extData.SRC0) << ", ";
1520  }
1521 
1522  if (extData.NEG & 0x2) {
1523  dis_stream << "-" << opSelectorToRegSym(extData.SRC1);
1524  } else {
1525  dis_stream << opSelectorToRegSym(extData.SRC1);
1526  }
1527 
1528  if (numSrcRegOperands() == 3) {
1529  if (extData.NEG & 0x4) {
1530  dis_stream << ", -" << opSelectorToRegSym(extData.SRC2);
1531  } else {
1532  dis_stream << ", " << opSelectorToRegSym(extData.SRC2);
1533  }
1534  }
1535 
1536  if (readsVCC())
1537  dis_stream << ", vcc";
1538 
1539  disassembly = dis_stream.str();
1540  }
1541 
1542  bool
1544  {
1545  assert(opIdx >= 0);
1546  assert(opIdx < getNumOperands());
1547 
1548  switch (opIdx) {
1549  case 0:
1550  // SRC0 may be a scalar or vector register, an
1551  // inline constant, or a special HW register
1552  return isScalarReg(extData.SRC0);
1553  case 1:
1554  if (numSrcRegOperands() > 1) {
1555  // if we have more than 1 source operand then
1556  // op index 1 corresponds to SRC1. SRC1 may be
1557  // a scalar or vector register, an inline
1558  // constant, or a special HW register
1559  return isScalarReg(extData.SRC1);
1560  } else {
1561  // if we only have 1 source operand, opIdx 1
1562  // will be VDST, and VDST is never a scalar
1563  // reg
1564  if (instData.VDST == REG_VCC_LO)
1565  return true;
1566  return false;
1567  }
1568  case 2:
1569  if (numSrcRegOperands() > 2) {
1570  // if we have more than 2 source operand then
1571  // op index 2 corresponds to SRC2. SRC2 may be
1572  // a scalar or vector register, an inline
1573  // constant, or a special HW register
1574  return isScalarReg(extData.SRC2);
1575  } else if (numSrcRegOperands() == 2) {
1576  // if we only have 2 source operands, opIdx 2
1577  // will be VDST, and VDST is never a scalar
1578  // reg
1579  if (instData.VDST == REG_VCC_LO)
1580  return true;
1581  return false;
1582  } else {
1583  // if this idx doesn't correspond to SRCX or
1584  // VDST then it must be a VCC read or write,
1585  // and VCC is always stored in an SGPR pair
1586  assert(writesVCC() || readsVCC());
1587  return true;
1588  }
1589  case 3:
1590  if (numSrcRegOperands() == 3) {
1591  // if we have 3 source operands then op
1592  // idx 3 will correspond to VDST, and VDST
1593  // is never a scalar reg
1594  if (instData.VDST == REG_VCC_LO)
1595  return true;
1596  return false;
1597  } else {
1598  // if this idx doesn't correspond to VDST
1599  // then it must be a VCC read or write, and
1600  // and VCC is always stored in an SGPR pair
1601  assert(writesVCC() || readsVCC());
1602  return true;
1603  }
1604  case 4:
1605  // if a VOP3 instruction has more than 4 ops
1606  // it must read from and write to VCC, and
1607  // VCC is always in an SGPR
1608  assert(writesVCC() || readsVCC());
1609  return true;
1610  default:
1611  fatal("Operand at idx %i does not exist\n", opIdx);
1612  return false;
1613  }
1614  }
1615 
1616  bool
1618  {
1619  assert(opIdx >= 0);
1620  assert(opIdx < getNumOperands());
1621 
1622  switch (opIdx) {
1623  case 0:
1624  // SRC0 may be a scalar or vector register, an
1625  // inline constant, or a special HW register
1626  return isVectorReg(extData.SRC0);
1627  case 1:
1628  if (numSrcRegOperands() > 1) {
1629  // if we have more than 1 source operand then
1630  // op index 1 corresponds to SRC1. SRC1 may be
1631  // a scalar or vector register, an inline
1632  // constant, or a special HW register
1633  return isVectorReg(extData.SRC1);
1634  } else {
1635  // if we only have 1 source operand, opIdx 1
1636  // will be VDST, and VDST is always a vector
1637  // reg
1638  if (instData.VDST == REG_VCC_LO)
1639  return false;
1640  return true;
1641  }
1642  case 2:
1643  if (numSrcRegOperands() > 2) {
1644  // if we have more than 2 source operand then
1645  // op index 2 corresponds to SRC2. SRC2 may be
1646  // a scalar or vector register, an inline
1647  // constant, or a special HW register
1648  return isVectorReg(extData.SRC2);
1649  } else if (numSrcRegOperands() == 2) {
1650  // if we only have 2 source operands, opIdx 2
1651  // will be VDST, and VDST is always a vector
1652  // reg
1653  if (instData.VDST == REG_VCC_LO)
1654  return false;
1655  return true;
1656  } else {
1657  // if this idx doesn't correspond to SRCX or
1658  // VDST then it must be a VCC read or write,
1659  // and VCC is never stored in a VGPR
1660  assert(writesVCC() || readsVCC());
1661  return false;
1662  }
1663  case 3:
1664  if (numSrcRegOperands() == 3) {
1665  // if we have 3 source operands then op
1666  // idx 3 will correspond to VDST, and VDST
1667  // is always a vector reg
1668  if (instData.VDST == REG_VCC_LO)
1669  return false;
1670  return true;
1671  } else {
1672  // if this idx doesn't correspond to VDST
1673  // then it must be a VCC read or write, and
1674  // and VCC is never stored in a VGPR
1675  assert(writesVCC() || readsVCC());
1676  return false;
1677  }
1678  case 4:
1679  // if a VOP3 instruction has more than 4 ops
1680  // it must read from and write to VCC, and
1681  // VCC is never stored in a VGPR
1682  assert(writesVCC() || readsVCC());
1683  return false;
1684  default:
1685  fatal("Operand at idx %i does not exist\n", opIdx);
1686  return false;
1687  }
1688  }
1689 
1690  int
1692  {
1693  assert(opIdx >= 0);
1694  assert(opIdx < getNumOperands());
1695 
1696  switch (opIdx) {
1697  case 0:
1698  // SRC0
1700  gpuDynInst->wavefront()->reservedScalarRegs);
1701  case 1:
1702  if (numSrcRegOperands() > 1) {
1703  // if we have more than 1 source operand then
1704  // op index 1 corresponds to SRC1
1706  gpuDynInst->wavefront()->reservedScalarRegs);
1707  } else {
1708  // if we only have 1 source operand, opIdx 1
1709  // will be VDST
1710  return instData.VDST;
1711  }
1712  case 2:
1713  if (numSrcRegOperands() > 2) {
1714  // if we have more than 2 source operand then
1715  // op index 2 corresponds to SRC2
1717  gpuDynInst->wavefront()->reservedScalarRegs);
1718  } else if (numSrcRegOperands() == 2) {
1719  // if we only have 2 source operands, opIdx 2
1720  // will be VDST
1721  return instData.VDST;
1722  } else {
1723  // if this idx doesn't correspond to SRCX or
1724  // VDST then it must be a VCC read or write
1725  assert(writesVCC() || readsVCC());
1727  gpuDynInst->wavefront()->reservedScalarRegs);
1728  }
1729  case 3:
1730  if (numSrcRegOperands() == 3) {
1731  // if we have 3 source operands then op
1732  // idx 3 will correspond to VDST
1733  return instData.VDST;
1734  } else {
1735  // if this idx doesn't correspond to VDST
1736  // then it must be a VCC read or write
1737  assert(writesVCC() || readsVCC());
1739  gpuDynInst->wavefront()->reservedScalarRegs);
1740  }
1741  case 4:
1742  // if a VOP3 instruction has more than 4 ops
1743  // it must read from and write to VCC
1744  assert(writesVCC() || readsVCC());
1746  gpuDynInst->wavefront()->reservedScalarRegs);
1747  default:
1748  fatal("Operand at idx %i does not exist\n", opIdx);
1749  return -1;
1750  }
1751  }
1752 
1753  // --- Inst_DS base class methods ---
1754 
1755  Inst_DS::Inst_DS(InFmt_DS *iFmt, const std::string &opcode)
1756  : GCN3GPUStaticInst(opcode)
1757  {
1758  setFlag(GroupSegment);
1759 
1760  // copy first instruction DWORD
1761  instData = iFmt[0];
1762  // copy second instruction DWORD
1763  extData = ((InFmt_DS_1 *)iFmt)[1];
1764  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1765  } // Inst_DS
1766 
1768  {
1769  } // ~Inst_DS
1770 
1771  int
1773  {
1774  return 8;
1775  } // instSize
1776 
1777  void
1779  {
1780  std::stringstream dis_stream;
1781  dis_stream << _opcode << " ";
1782 
1783  if (numDstRegOperands())
1784  dis_stream << "v" << extData.VDST << ", ";
1785 
1786  dis_stream << "v" << extData.ADDR;
1787 
1788  if (numSrcRegOperands() > 1)
1789  dis_stream << ", v" << extData.DATA0;
1790 
1791  if (numSrcRegOperands() > 2)
1792  dis_stream << ", v" << extData.DATA1;
1793 
1794  uint16_t offset = 0;
1795 
1796  if (instData.OFFSET1) {
1797  offset += instData.OFFSET1;
1798  offset <<= 8;
1799  }
1800 
1801  if (instData.OFFSET0)
1802  offset += instData.OFFSET0;
1803 
1804  if (offset)
1805  dis_stream << " offset:" << offset;
1806 
1807  disassembly = dis_stream.str();
1808  }
1809 
1810  bool
1812  {
1813  assert(opIdx >= 0);
1814  assert(opIdx < getNumOperands());
1815 
1816  // DS instructions cannot access SGPRs
1817  return false;
1818  }
1819 
1820  bool
1822  {
1823  assert(opIdx >= 0);
1824  assert(opIdx < getNumOperands());
1825 
1826  // DS instructions only access VGPRs
1827  return true;
1828  }
1829 
1830  int
1832  {
1833  assert(opIdx >= 0);
1834  assert(opIdx < getNumOperands());
1835 
1836  switch (opIdx) {
1837  case 0:
1838  return extData.ADDR;
1839  case 1:
1840  if (numSrcRegOperands() > 1) {
1841  return extData.DATA0;
1842  } else if (numDstRegOperands()) {
1843  return extData.VDST;
1844  }
1845  case 2:
1846  if (numSrcRegOperands() > 2) {
1847  return extData.DATA1;
1848  } else if (numDstRegOperands()) {
1849  return extData.VDST;
1850  }
1851  case 3:
1852  assert(numDstRegOperands());
1853  return extData.VDST;
1854  default:
1855  fatal("Operand at idx %i does not exist\n", opIdx);
1856  return -1;
1857  }
1858  }
1859 
1860  // --- Inst_MUBUF base class methods ---
1861 
1862  Inst_MUBUF::Inst_MUBUF(InFmt_MUBUF *iFmt, const std::string &opcode)
1863  : GCN3GPUStaticInst(opcode)
1864  {
1865  // copy first instruction DWORD
1866  instData = iFmt[0];
1867  // copy second instruction DWORD
1868  extData = ((InFmt_MUBUF_1 *)iFmt)[1];
1869  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1870 
1871  if (instData.GLC)
1872  setFlag(GloballyCoherent);
1873 
1874  if (instData.SLC)
1875  setFlag(SystemCoherent);
1876  } // Inst_MUBUF
1877 
1879  {
1880  } // ~Inst_MUBUF
1881 
1882  int
1884  {
1885  return 8;
1886  } // instSize
1887 
1888  void
1890  {
1891  // SRSRC is always in units of 4 SGPRs
1892  int srsrc_val = extData.SRSRC * 4;
1893  std::stringstream dis_stream;
1894  dis_stream << _opcode << " ";
1895  dis_stream << "v" << extData.VDATA << ", v" << extData.VADDR << ", ";
1896  dis_stream << "s[" << srsrc_val << ":"
1897  << srsrc_val + 3 << "], ";
1898  dis_stream << "s" << extData.SOFFSET;
1899 
1900  if (instData.OFFSET)
1901  dis_stream << ", offset:" << instData.OFFSET;
1902 
1903  disassembly = dis_stream.str();
1904  }
1905 
1906  bool
1908  {
1909  assert(opIdx >= 0);
1910  assert(opIdx < getNumOperands());
1911 
1912  switch (opIdx) {
1913  case 0:
1914  return false;
1915  case 1:
1916  return true;
1917  case 2:
1918  return true;
1919  case 3:
1920  return false;
1921  default:
1922  fatal("Operand at idx %i does not exist\n", opIdx);
1923  return false;
1924  }
1925  }
1926 
1927  bool
1929  {
1930  assert(opIdx >= 0);
1931  assert(opIdx < getNumOperands());
1932 
1933  switch (opIdx) {
1934  case 0:
1935  return true;
1936  case 1:
1937  return false;
1938  case 2:
1939  return false;
1940  case 3:
1941  return true;
1942  default:
1943  fatal("Operand at idx %i does not exist\n", opIdx);
1944  return false;
1945  }
1946  }
1947 
1948  int
1950  {
1951  assert(opIdx >= 0);
1952  assert(opIdx < getNumOperands());
1953 
1954  switch (opIdx) {
1955  case 0:
1956  return extData.VADDR;
1957  case 1:
1958  // SRSRC is always in units of 4 SGPRs
1959  return extData.SRSRC * 4;
1960  case 2:
1961  return extData.SOFFSET;
1962  case 3:
1963  return extData.VDATA;
1964  default:
1965  fatal("Operand at idx %i does not exist\n", opIdx);
1966  return -1;
1967  }
1968  }
1969 
1970  // --- Inst_MTBUF base class methods ---
1971 
1972  Inst_MTBUF::Inst_MTBUF(InFmt_MTBUF *iFmt, const std::string &opcode)
1973  : GCN3GPUStaticInst(opcode)
1974  {
1975  // copy first instruction DWORD
1976  instData = iFmt[0];
1977  // copy second instruction DWORD
1978  extData = ((InFmt_MTBUF_1 *)iFmt)[1];
1979  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
1980 
1981  if (instData.GLC)
1982  setFlag(GloballyCoherent);
1983 
1984  if (extData.SLC)
1985  setFlag(SystemCoherent);
1986 
1987  } // Inst_MTBUF
1988 
1990  {
1991  } // ~Inst_MTBUF
1992 
1993  int
1995  {
1996  return 8;
1997  } // instSize
1998 
1999  // --- Inst_MIMG base class methods ---
2000 
2001  Inst_MIMG::Inst_MIMG(InFmt_MIMG *iFmt, const std::string &opcode)
2002  : GCN3GPUStaticInst(opcode)
2003  {
2004  // copy first instruction DWORD
2005  instData = iFmt[0];
2006  // copy second instruction DWORD
2007  extData = ((InFmt_MIMG_1 *)iFmt)[1];
2008  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
2009 
2010  if (instData.GLC)
2011  setFlag(GloballyCoherent);
2012 
2013  if (instData.SLC)
2014  setFlag(SystemCoherent);
2015  } // Inst_MIMG
2016 
2018  {
2019  } // ~Inst_MIMG
2020 
2021  int
2023  {
2024  return 8;
2025  } // instSize
2026 
2027  // --- Inst_EXP base class methods ---
2028 
2029  Inst_EXP::Inst_EXP(InFmt_EXP *iFmt, const std::string &opcode)
2030  : GCN3GPUStaticInst(opcode)
2031  {
2032  // copy first instruction DWORD
2033  instData = iFmt[0];
2034  // copy second instruction DWORD
2035  extData = ((InFmt_EXP_1 *)iFmt)[1];
2036  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
2037  } // Inst_EXP
2038 
2040  {
2041  } // ~Inst_EXP
2042 
2043  int
2045  {
2046  return 8;
2047  } // instSize
2048 
2049  // --- Inst_FLAT base class methods ---
2050 
2051  Inst_FLAT::Inst_FLAT(InFmt_FLAT *iFmt, const std::string &opcode)
2052  : GCN3GPUStaticInst(opcode)
2053  {
2054  setFlag(Flat);
2055  // copy first instruction DWORD
2056  instData = iFmt[0];
2057  // copy second instruction DWORD
2058  extData = ((InFmt_FLAT_1 *)iFmt)[1];
2059  _srcLiteral = *reinterpret_cast<uint32_t*>(&iFmt[1]);
2060 
2061  if (instData.GLC)
2062  setFlag(GloballyCoherent);
2063 
2064  if (instData.SLC)
2065  setFlag(SystemCoherent);
2066  } // Inst_FLAT
2067 
2069  {
2070  } // ~Inst_FLAT
2071 
2072  int
2074  {
2075  return 8;
2076  } // instSize
2077 
2078  void
2080  {
2081  std::stringstream dis_stream;
2082  dis_stream << _opcode << " ";
2083 
2084  if (isLoad())
2085  dis_stream << "v" << extData.VDST << ", ";
2086 
2087  dis_stream << "v[" << extData.ADDR << ":" << extData.ADDR + 1 << "]";
2088 
2089  if (isStore())
2090  dis_stream << ", v" << extData.DATA;
2091 
2092  disassembly = dis_stream.str();
2093  }
2094 
2095  bool
2097  {
2098  assert(opIdx >= 0);
2099  assert(opIdx < getNumOperands());
2100 
2101  // if a FLAT instruction has more than two
2102  // operands it must be an atomic
2103  if (opIdx == 2)
2104  assert(isAtomic());
2105 
2106  // FLAT instructions cannot access SGPRs
2107  return false;
2108  }
2109 
2110  bool
2112  {
2113  assert(opIdx >= 0);
2114  assert(opIdx < getNumOperands());
2115 
2116  // if a FLAT instruction has more than two
2117  // operands it must be an atomic
2118  if (opIdx == 2)
2119  assert(isAtomic());
2120 
2121  // FLAT instructions only access VGPRs
2122  return true;
2123  }
2124 
2125  int
2127  {
2128  assert(opIdx >= 0);
2129  assert(opIdx < getNumOperands());
2130 
2131  switch (opIdx) {
2132  case 0:
2133  return extData.ADDR;
2134  case 1:
2135  if (isStore()) {
2136  return extData.DATA;
2137  } else if (isLoad()) {
2138  return extData.VDST;
2139  } else if (isAtomic()) {
2140  // For flat_atomic instructions,
2141  // the DATA VGPR gives the source
2142  return extData.DATA;
2143  } else {
2144  fatal("Unsupported flat instr type\n");
2145  }
2146  case 2:
2147  // if a FLAT instruction has more than two
2148  // operands it must be an atomic
2149  assert(isAtomic());
2150  return extData.VDST;
2151  default:
2152  fatal("Operand at idx %i does not exist\n", opIdx);
2153  return -1;
2154  }
2155  }
2156 } // namespace Gcn3ISA
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
bool hasSecondDword(InFmt_SOP2 *)
Definition: op_encodings.cc:68
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
bool isScalarRegister(int opIdx) override
unsigned int OFFSET1
std::string disassembly
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
bool isVectorRegister(int opIdx) override
int instSize() const override
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:171
bool isScalarRegister(int opIdx) override
Inst_SOP1(InFmt_SOP1 *, const std::string &opcode)
bool isScalarRegister(int opIdx) override
int instSize() const override
Definition: op_encodings.cc:62
bool isScalarReg(int opIdx)
Definition: registers.cc:190
bool isVectorRegister(int opIdx) override
int instSize() const override
InFmt_MUBUF_1 extData
bool isScalarRegister(int opIdx) override
void setFlag(Flags flag)
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
InFmt_SMEM_1 extData
int instSize() const override
void generateDisassembly() override
Definition: op_encodings.cc:80
bool isVectorRegister(int opIdx) override
Inst_VOP1(InFmt_VOP1 *, const std::string &opcode)
InFmt_VINTRP instData
const std::string opcode
void generateDisassembly() override
InstFormat extData
Definition: op_encodings.hh:65
int instSize() const override
Inst_EXP(InFmt_EXP *, const std::string &opcode)
unsigned int SSRC1
Bitfield< 23, 0 > offset
Definition: types.hh:152
void generateDisassembly() override
Inst_SOPK(InFmt_SOPK *, const std::string &opcode)
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
unsigned int SSRC0
int instSize() const override
InFmt_MTBUF_1 extData
bool isScalarRegister(int opIdx) override
void generateDisassembly() override
void generateDisassembly() override
InFmt_MIMG_1 extData
int instSize() const override
Inst_VINTRP(InFmt_VINTRP *, const std::string &opcode)
bool isVectorRegister(int opIdx) override
bool isScalarRegister(int opIdx) override
unsigned int SSRC1
InFmt_EXP_1 extData
bool isLoad() const
int instSize() const override
Inst_VOPC(InFmt_VOPC *, const std::string &opcode)
bool isVectorReg(int opIdx)
Definition: registers.cc:203
bool isVectorRegister(int opIdx) override
std::shared_ptr< GPUDynInst > GPUDynInstPtr
Definition: misc.hh:46
void generateDisassembly() override
Inst_DS(InFmt_DS *, const std::string &opcode)
InFmt_VOP3_SDST_ENC instData
unsigned int SIMM16
virtual int numDstRegOperands()=0
void generateDisassembly() override
Inst_VOP2(InFmt_VOP2 *, const std::string &opcode)
bool isVectorRegister(int opIdx) override
int instSize() const override
bool isVectorRegister(int opIdx) override
bool isVectorRegister(int opIdx) override
InFmt_SOPK instData
Definition: op_encodings.hh:87
classes that represnt vector/scalar operands in GCN3 ISA.
Definition: decoder.cc:44
bool isScalarRegister(int opIdx) override
void generateDisassembly() override
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
Inst_SMEM(InFmt_SMEM *, const std::string &opcode)
Inst_SOP2(InFmt_SOP2 *, const std::string &opcode)
Definition: op_encodings.cc:44
bool hasSecondDword(InFmt_SOP1 *)
InFmt_MTBUF instData
unsigned int SSRC0
int instSize() const override
int instSize() const override
int opSelectorToRegIdx(int idx, int numScalarRegs)
Definition: registers.cc:123
Inst_VOP3(InFmt_VOP3 *, const std::string &opcode, bool sgpr_dst)
bool writesVCC() const
void generateDisassembly() override
bool hasSecondDword(InFmt_SOPC *)
InFmt_VOP3_1 extData
bool isAtomic() const
unsigned int OFFSET0
bool isVectorRegister(int opIdx) override
const bool sgprDst
the v_cmp and readlane instructions in the VOP3 encoding are unique because they are the only instruc...
Inst_MTBUF(InFmt_MTBUF *, const std::string &opcode)
bool isScalarRegister(int opIdx) override
Inst_MUBUF(InFmt_MUBUF *, const std::string &opcode)
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
unsigned int SBASE
bool isVectorRegister(int opIdx) override
bool isScalarRegister(int opIdx) override
bool readsVCC() const
InFmt_DS_1 extData
void generateDisassembly() override
bool isVectorRegister(int opIdx) override
int instSize() const override
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
InFmt_FLAT_1 extData
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
Inst_SOPP(InFmt_SOPP *, const std::string &opcode)
void generateDisassembly() override
virtual int getNumOperands()=0
unsigned int VSRC1
bool isScalarRegister(int opIdx) override
void generateDisassembly() override
bool isScalarRegister(int opIdx) override
unsigned int SSRC0
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
ScalarRegU32 _srcLiteral
if the instruction has a src literal - an immediate value that is part of the instruction stream - we...
std::string opSelectorToRegSym(int idx, int numRegs)
Definition: registers.cc:41
int instSize() const override
InFmt_MUBUF instData
Bitfield< 24, 21 > opcode
Definition: types.hh:100
int getOperandSize(int opIdx) override
int instSize() const override
bool hasSecondDword(InFmt_VOP1 *)
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
Inst_FLAT(InFmt_FLAT *, const std::string &opcode)
unsigned int DATA0
bool isVectorRegister(int opIdx) override
virtual int numSrcRegOperands()=0
bool isVectorRegister(int opIdx) override
unsigned int VSRC1
bool hasSecondDword(InFmt_VOPC *)
unsigned int SDATA
int instSize() const override
bool hasSecondDword(InFmt_VOP2 *)
int instSize() const override
int instSize() const override
bool isScalarRegister(int opIdx) override
int instSize() const override
unsigned int SIMM16
Inst_MIMG(InFmt_MIMG *, const std::string &opcode)
Inst_VOP3_SDST_ENC(InFmt_VOP3_SDST_ENC *, const std::string &opcode)
Inst_SOPC(InFmt_SOPC *, const std::string &opcode)
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
bool isStore() const
int getRegisterIndex(int opIdx, GPUDynInstPtr gpuDynInst) override
void generateDisassembly() override
bool isScalarRegister(int opIdx) override
InstFormat * MachInst
used to represent the encoding of a GCN3 inst.
Definition: gpu_types.hh:62
unsigned int DATA1
bool isVectorRegister(int opIdx) override
bool isScalarRegister(int opIdx) override
void generateDisassembly() override
InFmt_SOP2 instData
Definition: op_encodings.hh:63

Generated on Mon Jun 8 2020 15:45:06 for gem5 by doxygen 1.8.13