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 //===----------------------------------------------------------------------===//
13 #include "lldb/Utility/Endian.h"
14 #include "lldb/lldb-enumerations.h"
16 #include "llvm/Support/MathExtras.h"
22 namespace lldb_private {
25 namespace lldb_private {
33 namespace lldb_private {
41 eType16_2, // a 32-bit Thumb instruction, made up of two words
47 Opcode() : m_byte_order(lldb::eByteOrderInvalid), m_type(eTypeInvalid) {}
49 Opcode(uint8_t inst, lldb::ByteOrder order)
50 : m_byte_order(order), m_type(eType8) {
54 Opcode(uint16_t inst, lldb::ByteOrder order)
55 : m_byte_order(order), m_type(eType16) {
59 Opcode(uint32_t inst, lldb::ByteOrder order)
60 : m_byte_order(order), m_type(eType32) {
64 Opcode(uint64_t inst, lldb::ByteOrder order)
65 : m_byte_order(order), m_type(eType64) {
69 Opcode(uint8_t *bytes, size_t length)
70 : m_byte_order(lldb::eByteOrderInvalid) {
71 SetOpcodeBytes(bytes, length);
75 m_byte_order = lldb::eByteOrderInvalid;
76 m_type = Opcode::eTypeInvalid;
79 Opcode::Type GetType() const { return m_type; }
81 uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const {
83 case Opcode::eTypeInvalid:
89 case Opcode::eType16_2:
95 case Opcode::eTypeBytes:
98 return invalid_opcode;
101 uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const {
103 case Opcode::eTypeInvalid:
107 case Opcode::eType16:
108 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
109 case Opcode::eType16_2:
111 case Opcode::eType32:
113 case Opcode::eType64:
115 case Opcode::eTypeBytes:
118 return invalid_opcode;
121 uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const {
123 case Opcode::eTypeInvalid:
127 case Opcode::eType16:
128 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
129 case Opcode::eType16_2: // passthrough
130 case Opcode::eType32:
131 return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
132 case Opcode::eType64:
134 case Opcode::eTypeBytes:
137 return invalid_opcode;
140 uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const {
142 case Opcode::eTypeInvalid:
146 case Opcode::eType16:
147 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
148 case Opcode::eType16_2: // passthrough
149 case Opcode::eType32:
150 return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
151 case Opcode::eType64:
152 return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64;
153 case Opcode::eTypeBytes:
156 return invalid_opcode;
159 void SetOpcode8(uint8_t inst, lldb::ByteOrder order) {
162 m_byte_order = order;
165 void SetOpcode16(uint16_t inst, lldb::ByteOrder order) {
167 m_data.inst16 = inst;
168 m_byte_order = order;
171 void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) {
173 m_data.inst32 = inst;
174 m_byte_order = order;
177 void SetOpcode32(uint32_t inst, lldb::ByteOrder order) {
179 m_data.inst32 = inst;
180 m_byte_order = order;
183 void SetOpcode64(uint64_t inst, lldb::ByteOrder order) {
185 m_data.inst64 = inst;
186 m_byte_order = order;
189 void SetOpcodeBytes(const void *bytes, size_t length) {
190 if (bytes != nullptr && length > 0) {
192 m_data.inst.length = length;
193 assert(length < sizeof(m_data.inst.bytes));
194 memcpy(m_data.inst.bytes, bytes, length);
195 m_byte_order = lldb::eByteOrderInvalid;
197 m_type = eTypeInvalid;
198 m_data.inst.length = 0;
202 int Dump(Stream *s, uint32_t min_byte_width);
204 const void *GetOpcodeBytes() const {
205 return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr);
208 uint32_t GetByteSize() const {
210 case Opcode::eTypeInvalid:
213 return sizeof(m_data.inst8);
214 case Opcode::eType16:
215 return sizeof(m_data.inst16);
216 case Opcode::eType16_2: // passthrough
217 case Opcode::eType32:
218 return sizeof(m_data.inst32);
219 case Opcode::eType64:
220 return sizeof(m_data.inst64);
221 case Opcode::eTypeBytes:
222 return m_data.inst.length;
227 // Get the opcode exactly as it would be laid out in memory.
228 uint32_t GetData(DataExtractor &data) const;
231 friend class lldb::SBInstruction;
233 const void *GetOpcodeDataBytes() const {
235 case Opcode::eTypeInvalid:
238 return &m_data.inst8;
239 case Opcode::eType16:
240 return &m_data.inst16;
241 case Opcode::eType16_2: // passthrough
242 case Opcode::eType32:
243 return &m_data.inst32;
244 case Opcode::eType64:
245 return &m_data.inst64;
246 case Opcode::eTypeBytes:
247 return m_data.inst.bytes;
252 lldb::ByteOrder GetDataByteOrder() const;
254 bool GetEndianSwap() const {
255 return (m_byte_order == lldb::eByteOrderBig &&
256 endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
257 (m_byte_order == lldb::eByteOrderLittle &&
258 endian::InlHostByteOrder() == lldb::eByteOrderBig);
261 lldb::ByteOrder m_byte_order;
270 uint8_t bytes[16]; // This must be big enough to handle any opcode for any
277 } // namespace lldb_private
279 #endif // lldb_Opcode_h