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