]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/include/lldb/Core/Opcode.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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 // Project includes
20 #include "lldb/Host/Endian.h"
21 #include "lldb/lldb-public.h"
22
23 namespace lldb
24 {
25     class SBInstruction;
26 }
27
28 namespace lldb_private {
29
30     class Opcode
31     {
32     public:
33         enum Type
34         {
35             eTypeInvalid,
36             eType8,
37             eType16,
38             eType16_2, // a 32-bit Thumb instruction, made up of two words
39             eType32,
40             eType64,
41             eTypeBytes
42         };
43
44         Opcode () : m_byte_order (lldb::eByteOrderInvalid), m_type (eTypeInvalid)
45         {
46         }
47
48         Opcode (uint8_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType8)
49         {
50             m_data.inst8 = inst;
51         }
52
53         Opcode (uint16_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType16)
54         {
55             m_data.inst16 = inst;
56         }
57
58         Opcode (uint32_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType32)
59         {
60             m_data.inst32 = inst;
61         }
62
63         Opcode (uint64_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType64)
64         {
65             m_data.inst64 = inst;
66         }
67
68         Opcode (uint8_t *bytes, size_t length) : m_byte_order (lldb::eByteOrderInvalid)
69         {
70             SetOpcodeBytes (bytes, length);
71         }
72
73         void
74         Clear()
75         {
76             m_byte_order = lldb::eByteOrderInvalid;
77             m_type = Opcode::eTypeInvalid;
78         }
79         Opcode::Type
80         GetType () const
81         {
82             return m_type;
83         }
84
85         uint8_t
86         GetOpcode8 (uint8_t invalid_opcode = UINT8_MAX) const
87         {
88             switch (m_type)
89             {
90             case Opcode::eTypeInvalid:  break;
91             case Opcode::eType8:        return m_data.inst8;
92             case Opcode::eType16:       break;
93             case Opcode::eType16_2:     break;
94             case Opcode::eType32:       break;
95             case Opcode::eType64:       break;
96             case Opcode::eTypeBytes:    break;
97             }
98             return invalid_opcode;
99         }
100
101         uint16_t
102         GetOpcode16 (uint16_t invalid_opcode = UINT16_MAX) const
103         {
104             switch (m_type)
105             {
106             case Opcode::eTypeInvalid:  break;
107             case Opcode::eType8:        return m_data.inst8;
108             case Opcode::eType16:       return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
109             case Opcode::eType16_2:     break;
110             case Opcode::eType32:       break;
111             case Opcode::eType64:       break;
112             case Opcode::eTypeBytes:    break;
113             }
114             return invalid_opcode;
115         }
116
117         uint32_t
118         GetOpcode32 (uint32_t invalid_opcode = UINT32_MAX) const
119         {
120             switch (m_type)
121             {
122             case Opcode::eTypeInvalid:  break;
123             case Opcode::eType8:        return m_data.inst8;
124             case Opcode::eType16:       return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
125             case Opcode::eType16_2:     // passthrough
126             case Opcode::eType32:       return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
127             case Opcode::eType64:       break;
128             case Opcode::eTypeBytes:    break;
129             }
130             return invalid_opcode;
131         }
132
133         uint64_t
134         GetOpcode64 (uint64_t invalid_opcode = UINT64_MAX) const
135         {
136             switch (m_type)
137             {
138             case Opcode::eTypeInvalid:  break;
139             case Opcode::eType8:        return m_data.inst8;
140             case Opcode::eType16:       return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
141             case Opcode::eType16_2:     // passthrough
142             case Opcode::eType32:       return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
143             case Opcode::eType64:       return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64;
144             case Opcode::eTypeBytes:    break;
145             }
146             return invalid_opcode;
147         }
148
149         void
150         SetOpcode8 (uint8_t inst, lldb::ByteOrder order)
151         {
152             m_type = eType8;
153             m_data.inst8 = inst;
154             m_byte_order = order;
155         }
156
157         void
158         SetOpcode16 (uint16_t inst, lldb::ByteOrder order)
159         {
160             m_type = eType16;
161             m_data.inst16 = inst;
162             m_byte_order = order;
163         }
164
165         void
166         SetOpcode16_2 (uint32_t inst, lldb::ByteOrder order)
167         {
168             m_type = eType16_2;
169             m_data.inst32 = inst;
170             m_byte_order = order;
171         }
172
173         void
174         SetOpcode32 (uint32_t inst, lldb::ByteOrder order)
175         {
176             m_type = eType32;
177             m_data.inst32 = inst;
178             m_byte_order = order;
179         }
180
181         void
182         SetOpcode64 (uint64_t inst, lldb::ByteOrder order)
183         {
184             m_type = eType64;
185             m_data.inst64 = inst;
186             m_byte_order = order;
187         }
188
189         void
190         SetOpcodeBytes (const void *bytes, size_t length)
191         {
192             if (bytes && length > 0)
193             {
194                 m_type = eTypeBytes;
195                 m_data.inst.length = length;
196                 assert (length < sizeof (m_data.inst.bytes));
197                 memcpy (m_data.inst.bytes, bytes, length);
198                 m_byte_order = lldb::eByteOrderInvalid;
199             }
200             else
201             {
202                 m_type = eTypeInvalid;
203                 m_data.inst.length = 0;
204             }
205         }
206
207         int
208         Dump (Stream *s, uint32_t min_byte_width);
209
210         const void *
211         GetOpcodeBytes () const
212         {
213             if (m_type == Opcode::eTypeBytes)
214                 return m_data.inst.bytes;
215             return NULL;
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 NULL;
256         }
257
258         lldb::ByteOrder
259         GetDataByteOrder () const;
260
261         bool
262         GetEndianSwap() const
263         {
264             return (m_byte_order == lldb::eByteOrderBig && lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
265                    (m_byte_order == lldb::eByteOrderLittle && lldb::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