1bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===-- Opcode.h ------------------------------------------------*- C++ -*-===//
2bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
3f5256e16dfc425c1d466f6308d4026d529ce9e0bHoward Hinnant//                     The LLVM Compiler Infrastructure
4bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// This file is distributed under the University of Illinois Open Source
6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// License. See LICENSE.TXT for details.
7bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
8bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===----------------------------------------------------------------------===//
9bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
10bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#ifndef lldb_Opcode_h
11bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#define lldb_Opcode_h
12bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
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
21namespace lldb
22{
23    class SBInstruction;
24}
25
26namespace 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
42        Opcode () : m_type (eTypeInvalid)
43        {
44        }
45
46        Opcode (uint8_t inst) : m_type (eType8)
47        {
48            m_data.inst8 = inst;
49        }
50
51        Opcode (uint16_t inst) : m_type (eType16)
52        {
53            m_data.inst16 = inst;
54        }
55
56        Opcode (uint32_t inst) : m_type (eType32)
57        {
58            m_data.inst32 = inst;
59        }
60
61        Opcode (uint64_t inst) : m_type (eType64)
62        {
63            m_data.inst64 = inst;
64        }
65
66        Opcode (uint8_t *bytes, size_t length)
67        {
68            SetOpcodeBytes (bytes, length);
69        }
70
71        void
72        Clear()
73        {
74            m_type = Opcode::eTypeInvalid;
75        }
76        Opcode::Type
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
148        SetOpcode8 (uint8_t inst)
149        {
150            m_type = eType8;
151            m_data.inst8 = inst;
152        }
153
154        void
155        SetOpcode16 (uint16_t inst)
156        {
157            m_type = eType16;
158            m_data.inst16 = inst;
159        }
160
161        void
162        SetOpcode16_2 (uint32_t inst)
163        {
164            m_type = eType16_2;
165            m_data.inst32 = inst;
166        }
167
168        void
169        SetOpcode32 (uint32_t inst)
170        {
171            m_type = eType32;
172            m_data.inst32 = inst;
173        }
174
175        void
176        SetOpcode64 (uint64_t inst)
177        {
178            m_type = eType64;
179            m_data.inst64 = inst;
180        }
181
182        void
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 *
203        GetOpcodeBytes () const
204        {
205            if (m_type == Opcode::eTypeBytes)
206                return m_data.inst.bytes;
207            return NULL;
208        }
209
210        uint32_t
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 *
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