HPCToolkit
ISA.hpp
Go to the documentation of this file.
1 // -*-Mode: C++;-*-
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 //***************************************************************************
48 //
49 // File:
50 // ISA.h
51 //
52 // Purpose:
53 // [The purpose of this file]
54 //
55 // Description:
56 // [The set of functions, macros, etc. defined in the file]
57 //
58 //***************************************************************************
59 
60 #ifndef isa_ISA_hpp
61 #define isa_ISA_hpp
62 
63 //************************* System Include Files ****************************
64 
65 #include <iostream>
66 
67 //*************************** User Include Files ****************************
68 
69 
70 #include <include/gcc-attr.h>
71 #include <include/uint.h>
72 #include <include/gnu_dis-asm.h>
73 
74 #include "ISATypes.hpp"
75 
76 //*************************** Forward Declarations ***************************
77 
78 // A one-element decoding cache. Used to reduce the slowness
79 // of multiple calls to the disassemblers (especially the GNU ones).
81 public:
83  { tag = NULL; insnSize = 0; }
84 
85  // Cache `tag' (Currently, this is just the MachInsn*. Later,
86  // we may need secondary tags, such as opIndex).
88 
89  // Cached data.
90  // Note, Non-GNU decoders may need more data members (the previous
91  // `disassemble_info' struct is used as an implicit cache for the GNU
92  // decoders).
94 };
95 
96 //*************************** Forward Declarations ***************************
97 
98 
99 //***************************************************************************
100 // ISA
101 //***************************************************************************
102 
103 // 'ISA': An abstract base class for an Instruction Set Architecture.
104 // It can classify and return certain information about the actual
105 // bits of a machine instruction.
106 class ISA {
107 
108  // ------------------------------------------------------------------------
109 
110 
111 public:
112 
113  // ------------------------------------------------------------------------
114 
115  // InsnDesc: Describes an instruction's class in various levels.
116  // Note: This should not have virtual functions so that objects can be
117  // passed around by value.
118  class InsnDesc {
119  public:
120 
121  // Used to implement InsnDesc. These are mutually exclusive
122  // instruction classes. They are not intended for general use!
123  enum IType {
124  // Note: only the Alpha ISA can reliably uses all categories.
125  // The other ISAs -- with the exception of MIPS -- only classify
126  // branches and do not distinguish between FP/int branches.
127 
128  MEM_LOAD, // Memory load (integer and FP)
129  MEM_STORE, // Memory store (integer and FP)
130  MEM_OTHER, // Other memory insn
131 
132  INT_BR_COND_REL, // PC-relative conditional branch (int compare)
133  INT_BR_COND_IND, // Register/Indirect conditional branch
134  FP_BR_COND_REL, // PC-relative conditional branch (FP compare)
135  FP_BR_COND_IND, // Register/Indirect conditional branch
136 
137  BR_UN_COND_REL, // PC-relative unconditional branch
138  BR_UN_COND_IND, // Register/Indirect unconditional branch
139 
140  SUBR_REL, // Relative subroutine call
141  SUBR_IND, // Register/Indirect subroutine call
142  SUBR_RET, // Subroutine return
143 
144  // ----------------
145  // The Alpha ISA classifies OTHER instructions into the
146  // following subdivisions.
147  INT_ADD, // Integer operations
155 
156  FP_ADD, // FP operation
165 
166  // OTHER: a non-integer, non-fp instruction
167  // ----------------
168 
169  SYS_CALL, // System call
170  OTHER, // Any other valid instruction
171  INVALID // An invalid instruction
172  };
173 
174  public:
175  // A 'InsnDesc' can be created using the bit definitions above.
176  InsnDesc(IType t = INVALID)
177  : ty(t)
178  { }
179 
181  { }
182 
183  InsnDesc(const InsnDesc& x)
184  { *this = x; }
185 
186  InsnDesc&
187  operator=(const InsnDesc& x)
188  {
189  ty = x.ty;
190  return *this;
191  }
192 
193  // -----------------------------------------------------
194 
195  // IsValid: A valid instruction
196  bool
197  isValid() const
198  { return ty != INVALID; }
199 
200  // An invalid instruction
201  bool
202  isInvalid() const
203  { return ty == INVALID; }
204 
205  // -----------------------------------------------------
206 
207  // Memory load
208  bool
209  isMemLoad() const
210  { return ty == MEM_LOAD; }
211 
212  // Memory store
213  bool
214  isMemStore() const
215  { return ty == MEM_STORE; }
216 
217  // Memory ref not categorized as load or store
218  bool
219  isMemOther() const
220  { return ty == MEM_OTHER; }
221 
222  // Any memory operation
223  bool
225  { return isMemLoad() || isMemStore() || isMemOther(); }
226 
227  // -----------------------------------------------------
228 
229  // Some sort of branch
230  bool
231  isBr() const
232  { return isBrRel() || isBrInd(); }
233 
234  // Some sort of PC-relative branch
235  bool
236  isBrRel() const
237  { return isBrCondRel() || isBrUnCondRel(); }
238 
239  // Some sort of Register/Indirect branch
240  bool
241  isBrInd() const
242  { return isBrCondInd() || isBrUnCondInd(); }
243 
244  // PC-relative conditional branch
245  bool
246  isBrCondRel() const
247  { return ty == INT_BR_COND_REL || ty == FP_BR_COND_REL; }
248 
249  // Register/Indirect conditional branch
250  bool
251  isBrCondInd() const
252  { return ty == INT_BR_COND_IND || ty == FP_BR_COND_IND; }
253 
254  // PC-relative unconditional branch
255  bool
257  { return ty == BR_UN_COND_REL; }
258 
259  // Register/Indirect unconditional branch
260  bool
262  { return ty == BR_UN_COND_IND; }
263 
264  // A branch with floating point comparison
265  bool
266  isFPBr() const
267  { return ty == FP_BR_COND_REL || ty == FP_BR_COND_IND; }
268 
269  // -----------------------------------------------------
270 
271  // Some subroutine call (but not a system call)
272  bool
273  isSubr() const
274  { return isSubrRel() || isSubrInd(); }
275 
276  // Relative subroutine call
277  bool
278  isSubrRel() const
279  { return ty == SUBR_REL; }
280 
281  // Register/Indirect subroutine call
282  bool
283  isSubrInd() const
284  { return ty == SUBR_IND; }
285 
286  // Subroutine return
287  bool
288  isSubrRet() const
289  { return ty == SUBR_RET; }
290 
291  // -----------------------------------------------------
292 
293  // A floating point instruction
294  bool
295  isFP() const
296  { return isFPBr() || isFPArith() || isFPOther(); }
297 
298  // A floating point arithmetic instruction (excludes fp branches,
299  // moves, other)
300  bool
301  isFPArith() const
302  {
303  return (ty == FP_ADD || ty == FP_ADD || ty == FP_SUB || ty == FP_MUL
304  || ty == FP_DIV || ty == FP_CMP || ty == FP_CVT
305  || ty == FP_SQRT);
306  }
307 
308  // Any other floating point instruction
309  bool
310  isFPOther() const
311  { return ty == FP_MOV || ty == FP_OTHER; }
312 
313  // -----------------------------------------------------
314 
315  // An integer arithmetic instruction (excludes branches, moves, other)
316  bool
317  isIntArith() const
318  {
319  return (ty == INT_ADD || ty == INT_SUB || ty == INT_MUL
320  || ty == INT_CMP || ty == INT_LOGIC || ty == INT_SHIFT);
321  }
322 
323  // Any other integer instruction
324  bool
325  isIntOther() const
326  { return ty == INT_MOV || ty == INT_OTHER; }
327 
328  // Any integer instruction
329  bool
330  isIntOp() const
331  { return isIntArith() || isIntOther(); }
332 
333  // -----------------------------------------------------
334 
335  // System call
336  bool
337  isSysCall() const
338  { return ty == SYS_CALL; }
339 
340  // Any other valid instruction
341  bool
342  isOther() const
343  { return ty == OTHER; }
344 
345  // -----------------------------------------------------
346 
347  void
348  set(IType t)
349  { ty = t; }
350 
351  const char*
352  toString() const;
353 
354  void
355  dump(std::ostream& o = std::cerr);
356 
357  void
358  ddump();
359 
360  private:
362  };
363 
364  // ------------------------------------------------------------------------
365 
366 public:
367 
368  ISA();
369  virtual ~ISA();
370 
371  // --------------------------------------------------------
372  // Reference Counting:
373  // --------------------------------------------------------
374 
375  // Because the only real member data an ISA has is a decoding cache,
376  // one typically does not really want to make copies of an ISA
377  // object. However, there are times when it may be convenient to
378  // hand out several pointers to an ISA, creating a memory management
379  // nightmare in which ownership is not clearly demarcated. We
380  // therefore provide an optional basic reference counting mechanism,
381  // a slightly less ghoulish solution.
382 
383  void
385  { ++refcount; }
386 
387  void
389  {
390  if (--refcount == 0) {
391  delete this;
392  }
393  }
394 
395  // --------------------------------------------------------
396  // Instructions:
397  // --------------------------------------------------------
398 
399  // Notes:
400  // - Functions with an 'opIndex' parameter: Since instructions are
401  // viewed as a potential VLIW packet, 'opIndex' identifies which
402  // operation we are currently interested in (0-based). For
403  // non-VLIW instructions, this argument should typically be 0.
404  // - Functions with an optional 'sz' parameter: If already available,
405  // 'sz' should be supplied to save an extra call to 'getInsnSize'.
406 
407 
408  // Returns the size (in bytes) of the instruction. In the case of
409  // VLIW instructions, returns the size not of the individual
410  // operation but the whole "packet". For CISC ISAs, if the return
411  // value is 0, 'mi' is not a valid instruction.
412  virtual ushort
413  getInsnSize(MachInsn* mi) = 0;
414 
415  // Viewing this instruction as a VLIW packet, return the maximum
416  // number of operations within the packet. For non-VLIW
417  // instructions, the return value will typically be 1. A return
418  // value of 0 indicates the 'packet' contains data.
419  virtual ushort
420  getInsnNumOps(MachInsn* mi) = 0;
421 
422  // Returns an instruction descriptor which provides a high level
423  // classifications of the operation performed
424  virtual InsnDesc
425  getInsnDesc(MachInsn* mi, ushort opIndex, ushort sz = 0) = 0;
426 
427  // Given a jump or branch instruction 'mi', return the target address.
428  // If a target cannot be computed, return 0. Note that a target is
429  // not computed when it depends on values in registers
430  // (e.g. indirect jumps). 'vma' is used only to calculate
431  // PC-relative targets.
432  virtual VMA
433  getInsnTargetVMA(MachInsn* mi, VMA vma, ushort opIndex, ushort sz = 0) = 0;
434 
435  // Returns the number of delay slots that must be observed by
436  // schedulers before the effect of instruction 'mi' can be
437  // assumed to be fully obtained (e.g., RISC braches).
438  virtual ushort
439  getInsnNumDelaySlots(MachInsn* mi, ushort opIndex, ushort sz = 0) = 0;
440 
441  // Returns whether or not the instruction 'mi1' "explicitly"
442  // executes in parallel with its successor 'mi2' (successor in the
443  // sequential sense). IOW, this has special reference to
444  // "explicitly parallel" architecture, not superscalar design.
445  virtual bool
446  isParallelWithSuccessor(MachInsn* mi1, ushort opIndex1,
447  ushort sz1,
448  MachInsn* mi2, ushort opIndex2,
449  ushort sz2) const = 0;
450 
451  // decode:
452  virtual void
453  decode(std::ostream& os, MachInsn* mi, VMA vma, ushort opIndex) = 0;
454 
455  // convertVMAToOpVMA: Given a vma at the beginning of an instruction
456  // and an opIndex, returns one value -- an 'operation vma' --
457  // representing both.
458  //
459  // convertOpVMAToVMA: Given an 'operation vma', returns the individual
460  // vma and opIndex components. (The latter is returned as a
461  // pass-by-reference parameter.) N.B.: The 'operation vma' must
462  // follow the convetions of 'convertVMAToOpVMA'.
463  //
464  // Sometimes users need to pretend that the individual operations in
465  // VLIW instructions are addressable. This is, of course not true,
466  // but 'operation vmas' are useful for [vma->xxx] maps (e.g. debugging
467  // information is stored in this manner).
468  //
469  // The default function assumes non-VLIW architecture
470  virtual VMA
472  { return vma; }
473 
474  virtual VMA
475  convertOpVMAToVMA(VMA opvma, ushort& opIndex) const
476  { opIndex = 0; return opvma; }
477 
478 private:
479  // Should not be used
481  { }
482 
483  ISA&
485  { return *this; }
486 
487 protected:
490  {
491  if (cmi == _cache->tag) {
492  return _cache;
493  }
494  else {
495  _cache->tag = NULL;
496  return NULL;
497  }
498  }
499 
500  void
502  { _cache->tag = cmi; _cache->insnSize = size; }
503 
504 private:
506  unsigned int refcount;
507 };
508 
509 
510 //***************************************************************************
511 // binutils helpers
512 //***************************************************************************
513 
515 public:
516  MachInsn* insn_addr; // memory address of insn
517  VMA insn_vma; // vma of insn
518 };
519 
520 
521 extern "C" {
522 
523  int
524  GNUbu_fprintf(void* stream, const char* format, ...);
525 
526  int
527  GNUbu_fprintf_stub(void* stream, const char* format, ...);
528 
529  void
530  GNUbu_print_addr_stub(bfd_vma di_vma, struct disassemble_info* di);
531 
532  int
533  GNUbu_read_memory(bfd_vma vma, bfd_byte* myaddr, unsigned int len,
534  struct disassemble_info* di);
535 
536 } // extern "C"
537 
538 
539 //****************************************************************************
540 
541 
542 
543 #endif // isa_ISA_hpp
void detach()
Definition: ISA.hpp:388
DecodingCache * _cache
Definition: ISA.hpp:505
ushort insnSize
Definition: ISA.hpp:93
virtual VMA convertVMAToOpVMA(VMA vma, ushort GCC_ATTR_UNUSED opIndex) const
Definition: ISA.hpp:471
bool isFPBr() const
Definition: ISA.hpp:266
IType ty
Definition: ISA.hpp:361
bool isSubrRel() const
Definition: ISA.hpp:278
bfd_vma VMA
Definition: ISATypes.hpp:79
InsnDesc(const InsnDesc &x)
Definition: ISA.hpp:183
void GNUbu_print_addr_stub(bfd_vma di_vma, struct disassemble_info *di)
bool isSubr() const
Definition: ISA.hpp:273
bool isBrRel() const
Definition: ISA.hpp:236
bool isMemLoad() const
Definition: ISA.hpp:209
DecodingCache * cacheLookup(MachInsn *cmi)
Definition: ISA.hpp:489
bool isFPOther() const
Definition: ISA.hpp:310
bool isSubrRet() const
Definition: ISA.hpp:288
void attach()
Definition: ISA.hpp:384
bool isFPArith() const
Definition: ISA.hpp:301
InsnDesc(IType t=INVALID)
Definition: ISA.hpp:176
bool isIntOp() const
Definition: ISA.hpp:330
int GNUbu_read_memory(bfd_vma vma, bfd_byte *myaddr, unsigned int len, struct disassemble_info *di)
bool isSysCall() const
Definition: ISA.hpp:337
bool isMemOp()
Definition: ISA.hpp:224
unsigned short int ushort
Definition: uint.h:120
bool isIntArith() const
Definition: ISA.hpp:317
bool isBrCondInd() const
Definition: ISA.hpp:251
bool isBrUnCondRel() const
Definition: ISA.hpp:256
bool isIntOther() const
Definition: ISA.hpp:325
bool isBr() const
Definition: ISA.hpp:231
bool isOther() const
Definition: ISA.hpp:342
bool isValid() const
Definition: ISA.hpp:197
bool isSubrInd() const
Definition: ISA.hpp:283
Definition: ISA.hpp:106
void cacheSet(MachInsn *cmi, ushort size)
Definition: ISA.hpp:501
MachInsn * insn_addr
Definition: ISA.hpp:516
MachInsn * tag
Definition: ISA.hpp:87
bool isBrUnCondInd() const
Definition: ISA.hpp:261
VMA insn_vma
Definition: ISA.hpp:517
int GNUbu_fprintf_stub(void *stream, const char *format,...)
bool isInvalid() const
Definition: ISA.hpp:202
void MachInsn
Definition: ISATypes.hpp:87
bool isBrCondRel() const
Definition: ISA.hpp:246
bool isFP() const
Definition: ISA.hpp:295
#define NULL
Definition: ElfHelper.cpp:85
bool isMemStore() const
Definition: ISA.hpp:214
virtual VMA convertOpVMAToVMA(VMA opvma, ushort &opIndex) const
Definition: ISA.hpp:475
ISA & operator=(const ISA &GCC_ATTR_UNUSED i)
Definition: ISA.hpp:484
#define GCC_ATTR_UNUSED
Definition: gcc-attr.h:80
int GNUbu_fprintf(void *stream, const char *format,...)
Definition: ISA.cpp:173
unsigned int refcount
Definition: ISA.hpp:506
static MachInsn * mi
Definition: x86ISAXed.cpp:91
InsnDesc & operator=(const InsnDesc &x)
Definition: ISA.hpp:187
bool isMemOther() const
Definition: ISA.hpp:219
DecodingCache()
Definition: ISA.hpp:82
bool isBrInd() const
Definition: ISA.hpp:241
ISA(const ISA &GCC_ATTR_UNUSED i)
Definition: ISA.hpp:480