1 //===-- Opcode.h ------------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
17 // Other libraries and framework includes
18 #include "llvm/Support/MathExtras.h"
21 #include "lldb/Host/Endian.h"
22 #include "lldb/lldb-public.h"
28 namespace lldb_private {
36 eType16_2, // a 32-bit Thumb instruction, made up of two words
42 Opcode() : m_byte_order(lldb::eByteOrderInvalid), m_type(eTypeInvalid) {}
44 Opcode(uint8_t inst, lldb::ByteOrder order)
45 : m_byte_order(order), m_type(eType8) {
49 Opcode(uint16_t inst, lldb::ByteOrder order)
50 : m_byte_order(order), m_type(eType16) {
54 Opcode(uint32_t inst, lldb::ByteOrder order)
55 : m_byte_order(order), m_type(eType32) {
59 Opcode(uint64_t inst, lldb::ByteOrder order)
60 : m_byte_order(order), m_type(eType64) {
64 Opcode(uint8_t *bytes, size_t length)
65 : m_byte_order(lldb::eByteOrderInvalid) {
66 SetOpcodeBytes(bytes, length);
70 m_byte_order = lldb::eByteOrderInvalid;
71 m_type = Opcode::eTypeInvalid;
74 Opcode::Type GetType() const { return m_type; }
76 uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const {
78 case Opcode::eTypeInvalid:
84 case Opcode::eType16_2:
90 case Opcode::eTypeBytes:
93 return invalid_opcode;
96 uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const {
98 case Opcode::eTypeInvalid:
102 case Opcode::eType16:
103 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
104 case Opcode::eType16_2:
106 case Opcode::eType32:
108 case Opcode::eType64:
110 case Opcode::eTypeBytes:
113 return invalid_opcode;
116 uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const {
118 case Opcode::eTypeInvalid:
122 case Opcode::eType16:
123 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
124 case Opcode::eType16_2: // passthrough
125 case Opcode::eType32:
126 return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
127 case Opcode::eType64:
129 case Opcode::eTypeBytes:
132 return invalid_opcode;
135 uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const {
137 case Opcode::eTypeInvalid:
141 case Opcode::eType16:
142 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
143 case Opcode::eType16_2: // passthrough
144 case Opcode::eType32:
145 return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
146 case Opcode::eType64:
147 return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64;
148 case Opcode::eTypeBytes:
151 return invalid_opcode;
154 void SetOpcode8(uint8_t inst, lldb::ByteOrder order) {
157 m_byte_order = order;
160 void SetOpcode16(uint16_t inst, lldb::ByteOrder order) {
162 m_data.inst16 = inst;
163 m_byte_order = order;
166 void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) {
168 m_data.inst32 = inst;
169 m_byte_order = order;
172 void SetOpcode32(uint32_t inst, lldb::ByteOrder order) {
174 m_data.inst32 = inst;
175 m_byte_order = order;
178 void SetOpcode64(uint64_t inst, lldb::ByteOrder order) {
180 m_data.inst64 = inst;
181 m_byte_order = order;
184 void SetOpcodeBytes(const void *bytes, size_t length) {
185 if (bytes != nullptr && length > 0) {
187 m_data.inst.length = length;
188 assert(length < sizeof(m_data.inst.bytes));
189 memcpy(m_data.inst.bytes, bytes, length);
190 m_byte_order = lldb::eByteOrderInvalid;
192 m_type = eTypeInvalid;
193 m_data.inst.length = 0;
197 int Dump(Stream *s, uint32_t min_byte_width);
199 const void *GetOpcodeBytes() const {
200 return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr);
203 uint32_t GetByteSize() const {
205 case Opcode::eTypeInvalid:
208 return sizeof(m_data.inst8);
209 case Opcode::eType16:
210 return sizeof(m_data.inst16);
211 case Opcode::eType16_2: // passthrough
212 case Opcode::eType32:
213 return sizeof(m_data.inst32);
214 case Opcode::eType64:
215 return sizeof(m_data.inst64);
216 case Opcode::eTypeBytes:
217 return m_data.inst.length;
222 // Get the opcode exactly as it would be laid out in memory.
223 uint32_t GetData(DataExtractor &data) const;
226 friend class lldb::SBInstruction;
228 const void *GetOpcodeDataBytes() const {
230 case Opcode::eTypeInvalid:
233 return &m_data.inst8;
234 case Opcode::eType16:
235 return &m_data.inst16;
236 case Opcode::eType16_2: // passthrough
237 case Opcode::eType32:
238 return &m_data.inst32;
239 case Opcode::eType64:
240 return &m_data.inst64;
241 case Opcode::eTypeBytes:
242 return m_data.inst.bytes;
247 lldb::ByteOrder GetDataByteOrder() const;
249 bool GetEndianSwap() const {
250 return (m_byte_order == lldb::eByteOrderBig &&
251 endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
252 (m_byte_order == lldb::eByteOrderLittle &&
253 endian::InlHostByteOrder() == lldb::eByteOrderBig);
256 lldb::ByteOrder m_byte_order;
265 uint8_t bytes[16]; // This must be big enough to handle any opcode for any
272 } // namespace lldb_private
274 #endif // lldb_Opcode_h