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