1 //===-- Opcode.h ------------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
12 #include "lldb/Utility/Endian.h"
13 #include "lldb/lldb-enumerations.h"
15 #include "llvm/Support/MathExtras.h"
25 namespace lldb_private {
35 eType16_2, // a 32-bit Thumb instruction, made up of two words
41 Opcode() : m_byte_order(lldb::eByteOrderInvalid), m_type(eTypeInvalid) {}
43 Opcode(uint8_t inst, lldb::ByteOrder order)
44 : m_byte_order(order), m_type(eType8) {
48 Opcode(uint16_t inst, lldb::ByteOrder order)
49 : m_byte_order(order), m_type(eType16) {
53 Opcode(uint32_t inst, lldb::ByteOrder order)
54 : m_byte_order(order), m_type(eType32) {
58 Opcode(uint64_t inst, lldb::ByteOrder order)
59 : m_byte_order(order), m_type(eType64) {
63 Opcode(uint8_t *bytes, size_t length)
64 : m_byte_order(lldb::eByteOrderInvalid) {
65 SetOpcodeBytes(bytes, length);
69 m_byte_order = lldb::eByteOrderInvalid;
70 m_type = Opcode::eTypeInvalid;
73 Opcode::Type GetType() const { return m_type; }
75 uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const {
77 case Opcode::eTypeInvalid:
83 case Opcode::eType16_2:
89 case Opcode::eTypeBytes:
92 return invalid_opcode;
95 uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const {
97 case Opcode::eTypeInvalid:
101 case Opcode::eType16:
102 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
103 case Opcode::eType16_2:
105 case Opcode::eType32:
107 case Opcode::eType64:
109 case Opcode::eTypeBytes:
112 return invalid_opcode;
115 uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const {
117 case Opcode::eTypeInvalid:
121 case Opcode::eType16:
122 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
123 case Opcode::eType16_2: // passthrough
124 case Opcode::eType32:
125 return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
126 case Opcode::eType64:
128 case Opcode::eTypeBytes:
131 return invalid_opcode;
134 uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const {
136 case Opcode::eTypeInvalid:
140 case Opcode::eType16:
141 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
142 case Opcode::eType16_2: // passthrough
143 case Opcode::eType32:
144 return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
145 case Opcode::eType64:
146 return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64;
147 case Opcode::eTypeBytes:
150 return invalid_opcode;
153 void SetOpcode8(uint8_t inst, lldb::ByteOrder order) {
156 m_byte_order = order;
159 void SetOpcode16(uint16_t inst, lldb::ByteOrder order) {
161 m_data.inst16 = inst;
162 m_byte_order = order;
165 void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) {
167 m_data.inst32 = inst;
168 m_byte_order = order;
171 void SetOpcode32(uint32_t inst, lldb::ByteOrder order) {
173 m_data.inst32 = inst;
174 m_byte_order = order;
177 void SetOpcode64(uint64_t inst, lldb::ByteOrder order) {
179 m_data.inst64 = inst;
180 m_byte_order = order;
183 void SetOpcodeBytes(const void *bytes, size_t length) {
184 if (bytes != nullptr && length > 0) {
186 m_data.inst.length = length;
187 assert(length < sizeof(m_data.inst.bytes));
188 memcpy(m_data.inst.bytes, bytes, length);
189 m_byte_order = lldb::eByteOrderInvalid;
191 m_type = eTypeInvalid;
192 m_data.inst.length = 0;
196 int Dump(Stream *s, uint32_t min_byte_width);
198 const void *GetOpcodeBytes() const {
199 return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr);
202 uint32_t GetByteSize() const {
204 case Opcode::eTypeInvalid:
207 return sizeof(m_data.inst8);
208 case Opcode::eType16:
209 return sizeof(m_data.inst16);
210 case Opcode::eType16_2: // passthrough
211 case Opcode::eType32:
212 return sizeof(m_data.inst32);
213 case Opcode::eType64:
214 return sizeof(m_data.inst64);
215 case Opcode::eTypeBytes:
216 return m_data.inst.length;
221 // Get the opcode exactly as it would be laid out in memory.
222 uint32_t GetData(DataExtractor &data) const;
225 friend class lldb::SBInstruction;
227 const void *GetOpcodeDataBytes() const {
229 case Opcode::eTypeInvalid:
232 return &m_data.inst8;
233 case Opcode::eType16:
234 return &m_data.inst16;
235 case Opcode::eType16_2: // passthrough
236 case Opcode::eType32:
237 return &m_data.inst32;
238 case Opcode::eType64:
239 return &m_data.inst64;
240 case Opcode::eTypeBytes:
241 return m_data.inst.bytes;
246 lldb::ByteOrder GetDataByteOrder() const;
248 bool GetEndianSwap() const {
249 return (m_byte_order == lldb::eByteOrderBig &&
250 endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
251 (m_byte_order == lldb::eByteOrderLittle &&
252 endian::InlHostByteOrder() == lldb::eByteOrderBig);
255 lldb::ByteOrder m_byte_order;
264 uint8_t bytes[16]; // This must be big enough to handle any opcode for any
271 } // namespace lldb_private
273 #endif // lldb_Opcode_h