]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - include/lldb/Core/Opcode.h
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / include / lldb / Core / Opcode.h
1 //===-- Opcode.h ------------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef lldb_Opcode_h
11 #define lldb_Opcode_h
12
13 // C Includes
14 #include <string.h>
15
16 // C++ Includes
17 // Other libraries and framework includes
18 #include "llvm/Support/MathExtras.h"
19
20 // Project includes
21 #include "lldb/Host/Endian.h"
22 #include "lldb/lldb-public.h"
23
24 namespace lldb {
25 class SBInstruction;
26 } // namespace lldb
27
28 namespace lldb_private {
29
30 class Opcode {
31 public:
32   enum Type {
33     eTypeInvalid,
34     eType8,
35     eType16,
36     eType16_2, // a 32-bit Thumb instruction, made up of two words
37     eType32,
38     eType64,
39     eTypeBytes
40   };
41
42   Opcode() : m_byte_order(lldb::eByteOrderInvalid), m_type(eTypeInvalid) {}
43
44   Opcode(uint8_t inst, lldb::ByteOrder order)
45       : m_byte_order(order), m_type(eType8) {
46     m_data.inst8 = inst;
47   }
48
49   Opcode(uint16_t inst, lldb::ByteOrder order)
50       : m_byte_order(order), m_type(eType16) {
51     m_data.inst16 = inst;
52   }
53
54   Opcode(uint32_t inst, lldb::ByteOrder order)
55       : m_byte_order(order), m_type(eType32) {
56     m_data.inst32 = inst;
57   }
58
59   Opcode(uint64_t inst, lldb::ByteOrder order)
60       : m_byte_order(order), m_type(eType64) {
61     m_data.inst64 = inst;
62   }
63
64   Opcode(uint8_t *bytes, size_t length)
65       : m_byte_order(lldb::eByteOrderInvalid) {
66     SetOpcodeBytes(bytes, length);
67   }
68
69   void Clear() {
70     m_byte_order = lldb::eByteOrderInvalid;
71     m_type = Opcode::eTypeInvalid;
72   }
73
74   Opcode::Type GetType() const { return m_type; }
75
76   uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const {
77     switch (m_type) {
78     case Opcode::eTypeInvalid:
79       break;
80     case Opcode::eType8:
81       return m_data.inst8;
82     case Opcode::eType16:
83       break;
84     case Opcode::eType16_2:
85       break;
86     case Opcode::eType32:
87       break;
88     case Opcode::eType64:
89       break;
90     case Opcode::eTypeBytes:
91       break;
92     }
93     return invalid_opcode;
94   }
95
96   uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const {
97     switch (m_type) {
98     case Opcode::eTypeInvalid:
99       break;
100     case Opcode::eType8:
101       return m_data.inst8;
102     case Opcode::eType16:
103       return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
104     case Opcode::eType16_2:
105       break;
106     case Opcode::eType32:
107       break;
108     case Opcode::eType64:
109       break;
110     case Opcode::eTypeBytes:
111       break;
112     }
113     return invalid_opcode;
114   }
115
116   uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const {
117     switch (m_type) {
118     case Opcode::eTypeInvalid:
119       break;
120     case Opcode::eType8:
121       return m_data.inst8;
122     case Opcode::eType16:
123       return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
124     case Opcode::eType16_2: // passthrough
125     case Opcode::eType32:
126       return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
127     case Opcode::eType64:
128       break;
129     case Opcode::eTypeBytes:
130       break;
131     }
132     return invalid_opcode;
133   }
134
135   uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const {
136     switch (m_type) {
137     case Opcode::eTypeInvalid:
138       break;
139     case Opcode::eType8:
140       return m_data.inst8;
141     case Opcode::eType16:
142       return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
143     case Opcode::eType16_2: // passthrough
144     case Opcode::eType32:
145       return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
146     case Opcode::eType64:
147       return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64;
148     case Opcode::eTypeBytes:
149       break;
150     }
151     return invalid_opcode;
152   }
153
154   void SetOpcode8(uint8_t inst, lldb::ByteOrder order) {
155     m_type = eType8;
156     m_data.inst8 = inst;
157     m_byte_order = order;
158   }
159
160   void SetOpcode16(uint16_t inst, lldb::ByteOrder order) {
161     m_type = eType16;
162     m_data.inst16 = inst;
163     m_byte_order = order;
164   }
165
166   void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) {
167     m_type = eType16_2;
168     m_data.inst32 = inst;
169     m_byte_order = order;
170   }
171
172   void SetOpcode32(uint32_t inst, lldb::ByteOrder order) {
173     m_type = eType32;
174     m_data.inst32 = inst;
175     m_byte_order = order;
176   }
177
178   void SetOpcode64(uint64_t inst, lldb::ByteOrder order) {
179     m_type = eType64;
180     m_data.inst64 = inst;
181     m_byte_order = order;
182   }
183
184   void SetOpcodeBytes(const void *bytes, size_t length) {
185     if (bytes != nullptr && length > 0) {
186       m_type = eTypeBytes;
187       m_data.inst.length = length;
188       assert(length < sizeof(m_data.inst.bytes));
189       memcpy(m_data.inst.bytes, bytes, length);
190       m_byte_order = lldb::eByteOrderInvalid;
191     } else {
192       m_type = eTypeInvalid;
193       m_data.inst.length = 0;
194     }
195   }
196
197   int Dump(Stream *s, uint32_t min_byte_width);
198
199   const void *GetOpcodeBytes() const {
200     return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr);
201   }
202
203   uint32_t GetByteSize() const {
204     switch (m_type) {
205     case Opcode::eTypeInvalid:
206       break;
207     case Opcode::eType8:
208       return sizeof(m_data.inst8);
209     case Opcode::eType16:
210       return sizeof(m_data.inst16);
211     case Opcode::eType16_2: // passthrough
212     case Opcode::eType32:
213       return sizeof(m_data.inst32);
214     case Opcode::eType64:
215       return sizeof(m_data.inst64);
216     case Opcode::eTypeBytes:
217       return m_data.inst.length;
218     }
219     return 0;
220   }
221
222   // Get the opcode exactly as it would be laid out in memory.
223   uint32_t GetData(DataExtractor &data) const;
224
225 protected:
226   friend class lldb::SBInstruction;
227
228   const void *GetOpcodeDataBytes() const {
229     switch (m_type) {
230     case Opcode::eTypeInvalid:
231       break;
232     case Opcode::eType8:
233       return &m_data.inst8;
234     case Opcode::eType16:
235       return &m_data.inst16;
236     case Opcode::eType16_2: // passthrough
237     case Opcode::eType32:
238       return &m_data.inst32;
239     case Opcode::eType64:
240       return &m_data.inst64;
241     case Opcode::eTypeBytes:
242       return m_data.inst.bytes;
243     }
244     return nullptr;
245   }
246
247   lldb::ByteOrder GetDataByteOrder() const;
248
249   bool GetEndianSwap() const {
250     return (m_byte_order == lldb::eByteOrderBig &&
251             endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
252            (m_byte_order == lldb::eByteOrderLittle &&
253             endian::InlHostByteOrder() == lldb::eByteOrderBig);
254   }
255
256   lldb::ByteOrder m_byte_order;
257
258   Opcode::Type m_type;
259   union {
260     uint8_t inst8;
261     uint16_t inst16;
262     uint32_t inst32;
263     uint64_t inst64;
264     struct {
265       uint8_t bytes[16]; // This must be big enough to handle any opcode for any
266                          // supported target.
267       uint8_t length;
268     } inst;
269   } m_data;
270 };
271
272 } // namespace lldb_private
273
274 #endif // lldb_Opcode_h