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