HPCToolkit
PowerISA.cpp
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 // $HeadURL$
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 //************************* System Include Files ****************************
61 
62 #include <iostream>
63 using std::ostream;
64 
65 #include <cstdarg>
66 #include <cstring> // for 'memcpy'
67 
68 //*************************** User Include Files ****************************
69 
70 #include <include/gnu_dis-asm.h>
71 
72 #include "PowerISA.hpp"
73 
75 
76 //*************************** Forward Declarations ***************************
77 
78 static VMA
79 GNUvma2vma(bfd_vma di_vma, MachInsn* insn_addr, VMA insn_vma)
80 {
81  // N.B.: The GNU decoders assume that the address of 'insn_addr' is
82  // the actual the VMA in order to calculate VMA-relative targets.
83  VMA x = (di_vma - PTR_TO_BFDVMA(insn_addr)) + insn_vma;
84  return x;
85 }
86 
87 
88 static void
89 GNUbu_print_addr(bfd_vma di_vma, struct disassemble_info* di)
90 {
91  GNUbu_disdata* data = (GNUbu_disdata*)di->application_data;
92 
93  VMA x = GNUvma2vma(di_vma, data->insn_addr, data->insn_vma);
94  ostream* os = (ostream*)di->stream;
95  *os << std::showbase << std::hex << x << std::dec;
96 }
97 
98 
99 //****************************************************************************
100 // PowerISA
101 //****************************************************************************
102 
103 // Summary of interesting instructions:
104 //
105 // [Relevant formats]
106 // BD-form: conditional branches
107 // I-form: unconditional branches
108 // XL-form: indirect branches, among other things
109 //
110 // unconditional branch:
111 // - relative [I] {b: branch}
112 // - absolute [I] {ba: branch, absolute}
113 // - indirect {bctr ~[bcctr]: branch to count reg}
114 //
115 // conditional branch:
116 // - relative [BD] {bc = b__: branch cond}
117 // - absolute [BD] {bca = b__a: branch cond, absolute}
118 // - indirect [XL] {bcctr = b_ctr: branch cond to count reg}
119 //
120 // subroutine call:
121 // - relative [I] {bl: branch and link}
122 // - absolute [I] {bla: branch and link/absolute}
123 // - indirect {bctrl ~[bcctrl]: branch to count reg and link}
124 //
125 // subroutine call, conditional:
126 // - relative [BD] {bcl = b__l: branch cond and link}
127 // - absolute [BD] {bcla = b__la: branch cond and link/absolute}
128 // - indirect [XL] {bcctrl = b_ctrl = bccl: branch cond to count reg & link}
129 //
130 // return:
131 // - uncond [XL] {blr = br ~[bclr]: branch to link reg}
132 // - cond [XL] {bclr = b__lr = bcr: branch cond to link reg}
133 // - CRAZY! [XL] {blrl = brl ~[bclrl]: branch to link reg and link}
134 // - CRAZY! [XL] {bclrl = b__lrl = bcrl: branch cond to link reg and link}
135 
137  : m_di(NULL), m_di_dis(NULL)
138 {
139  // See 'dis-asm.h'
140  m_di = new disassemble_info;
141  init_disassemble_info(m_di, stdout, GNUbu_fprintf_stub);
142  m_di->arch = bfd_arch_powerpc; // bfd_get_arch(abfd);
143  m_di->mach = bfd_mach_ppc64; // bfd_get_mach(abfd)
144  m_di->endian = BFD_ENDIAN_BIG;
145  m_di->read_memory_func = GNUbu_read_memory; // vs. 'buffer_read_memory'
146  m_di->print_address_func = GNUbu_print_addr_stub; // vs. 'generic_print_addr'
147 
148  m_di_dis = new disassemble_info;
149  init_disassemble_info(m_di_dis, stdout, GNUbu_fprintf);
150  m_di_dis->application_data = (void*)&m_dis_data;
151  m_di_dis->arch = m_di->arch;
152  m_di_dis->mach = m_di->mach;
153  m_di_dis->endian = m_di->endian;
154  m_di_dis->read_memory_func = GNUbu_read_memory;
155  m_di_dis->print_address_func = GNUbu_print_addr;
156 }
157 
158 
160 {
161  delete m_di;
162  delete m_di_dis;
163 }
164 
165 
169 {
170  ISA::InsnDesc d;
171 
172  if (cacheLookup(mi) == NULL) {
173  int size = print_insn_big_powerpc(PTR_TO_BFDVMA(mi), m_di);
174  cacheSet(mi, (ushort)size);
175  }
176 
177  // NOTE:
178  // m_di->target is set for relative branch/subroutine targets
179  // m_di->target2 is set for absolute branch/subroutine targets
180  bool isIndirect = (m_di->target == 0) && (m_di->target2 == 0);
181 
182  switch (m_di->insn_type) {
183  case dis_noninsn:
185  break;
186  case dis_branch:
187  if (isIndirect) {
189  }
190  else {
192  }
193  break;
194  case dis_condbranch:
195  if (isIndirect) {
196  d.set(InsnDesc::INT_BR_COND_IND); // arbitrarily choose int
197  }
198  else {
199  d.set(InsnDesc::INT_BR_COND_REL); // arbitrarily choose int
200  }
201  break;
202  case dis_jsr:
203  if (isIndirect) {
205  }
206  else {
208  }
209  break;
210  case dis_condjsr:
211  d.set(InsnDesc::OTHER);
212  break;
213 #if defined(HAVE_HPC_GNUBINUTILS)
214  case dis_return:
216  break;
217 #endif
218  case dis_dref:
219  case dis_dref2:
221  break;
222  default:
223  d.set(InsnDesc::OTHER);
224  break;
225  }
226  return d;
227 }
228 
229 
230 VMA
232 {
233  // N.B.: The GNU decoders assume that the address of 'mi' is
234  // actually the VMA in order to calculate VMA-relative targets.
235 
236  if (cacheLookup(mi) == NULL) {
237  int size = print_insn_big_powerpc(PTR_TO_BFDVMA(mi), m_di);
238  cacheSet(mi, (ushort)size);
239  }
240 
241  ISA::InsnDesc d = getInsnDesc(mi, opIndex, sz);
242  if (d.isBrRel() || d.isSubrRel()) {
243  // NOTE:
244  // m_di->target is set to the displacement for relative targets
245  // m_di->target2 is set to the absolute value for absolute targets
246  if (m_di->target != 0) {
247  return vma + m_di->target;
248  }
249  else {
250  return m_di->target2;
251  }
252  }
253  else {
254  return 0;
255  }
256 }
257 
258 
259 ushort
261  ushort GCC_ATTR_UNUSED opIndex,
263 {
264  // POWER does not have an architectural delay slot
265  return 0;
266 }
267 
268 
269 void
270 PowerISA::decode(ostream& os, MachInsn* mi, VMA vma,
271  ushort GCC_ATTR_UNUSED opIndex)
272 {
274  m_dis_data.insn_vma = vma;
275 
276  m_di_dis->stream = (void*)&os;
277  print_insn_big_powerpc(PTR_TO_BFDVMA(mi), m_di_dis);
278 }
279 
280 
281 //****************************************************************************
struct disassemble_info * m_di_dis
Definition: PowerISA.hpp:134
bool isSubrRel() const
Definition: ISA.hpp:278
bfd_vma VMA
Definition: ISATypes.hpp:79
bool isBrRel() const
Definition: ISA.hpp:236
#define PTR_TO_BFDVMA(x)
Definition: ISATypes.hpp:94
int GNUbu_fprintf(void *stream, const char *format,...)
Definition: ISA.cpp:173
int GNUbu_fprintf_stub(void *GCC_ATTR_UNUSED stream, const char *GCC_ATTR_UNUSED format,...)
Definition: ISA.cpp:191
DecodingCache * cacheLookup(MachInsn *cmi)
Definition: ISA.hpp:489
#define dis_return
Definition: gnu_dis-asm.h:79
static void GNUbu_print_addr(bfd_vma di_vma, struct disassemble_info *di)
Definition: PowerISA.cpp:89
virtual ~PowerISA()
Definition: PowerISA.cpp:159
static VMA GNUvma2vma(bfd_vma di_vma, MachInsn *insn_addr, VMA insn_vma)
Definition: PowerISA.cpp:79
virtual void decode(std::ostream &os, MachInsn *mi, VMA vma, ushort opIndex)
Definition: PowerISA.cpp:270
unsigned short int ushort
Definition: uint.h:120
void set(IType t)
Definition: ISA.hpp:348
virtual VMA getInsnTargetVMA(MachInsn *mi, VMA pc, ushort opIndex, ushort sz=0)
Definition: PowerISA.cpp:231
int GNUbu_read_memory(bfd_vma vma, bfd_byte *myaddr, unsigned int len, struct disassemble_info *GCC_ATTR_UNUSED di)
Definition: ISA.cpp:206
void cacheSet(MachInsn *cmi, ushort size)
Definition: ISA.hpp:501
MachInsn * insn_addr
Definition: ISA.hpp:516
void GNUbu_print_addr_stub(bfd_vma GCC_ATTR_UNUSED di_vma, struct disassemble_info *GCC_ATTR_UNUSED di)
Definition: ISA.cpp:199
virtual InsnDesc getInsnDesc(MachInsn *mi, ushort opIndex, ushort sz=0)
Definition: PowerISA.cpp:167
VMA insn_vma
Definition: ISA.hpp:517
struct disassemble_info * m_di
Definition: PowerISA.hpp:133
void MachInsn
Definition: ISATypes.hpp:87
#define NULL
Definition: ElfHelper.cpp:85
virtual ushort getInsnNumDelaySlots(MachInsn *mi, ushort opIndex, ushort sz=0)
Definition: PowerISA.cpp:260
GNUbu_disdata m_dis_data
Definition: PowerISA.hpp:135
#define GCC_ATTR_UNUSED
Definition: gcc-attr.h:80
static MachInsn * mi
Definition: x86ISAXed.cpp:91