Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:45

0001 //===-- Opcode.h ------------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_CORE_OPCODE_H
0010 #define LLDB_CORE_OPCODE_H
0011 
0012 #include "lldb/Utility/Endian.h"
0013 #include "lldb/lldb-enumerations.h"
0014 
0015 #include "llvm/Support/SwapByteOrder.h"
0016 
0017 #include <cassert>
0018 #include <cstdint>
0019 #include <cstring>
0020 
0021 namespace lldb {
0022 class SBInstruction;
0023 }
0024 
0025 namespace lldb_private {
0026 class DataExtractor;
0027 class Stream;
0028 
0029 class Opcode {
0030 public:
0031   enum Type {
0032     eTypeInvalid,
0033     eType8,
0034     eType16,
0035     eType16_2, // a 32-bit Thumb instruction, made up of two words
0036     eType32,
0037     eType64,
0038     eTypeBytes
0039   };
0040 
0041   Opcode() = default;
0042 
0043   Opcode(uint8_t inst, lldb::ByteOrder order)
0044       : m_byte_order(order), m_type(eType8) {
0045     m_data.inst8 = inst;
0046   }
0047 
0048   Opcode(uint16_t inst, lldb::ByteOrder order)
0049       : m_byte_order(order), m_type(eType16) {
0050     m_data.inst16 = inst;
0051   }
0052 
0053   Opcode(uint32_t inst, lldb::ByteOrder order)
0054       : m_byte_order(order), m_type(eType32) {
0055     m_data.inst32 = inst;
0056   }
0057 
0058   Opcode(uint64_t inst, lldb::ByteOrder order)
0059       : m_byte_order(order), m_type(eType64) {
0060     m_data.inst64 = inst;
0061   }
0062 
0063   Opcode(uint8_t *bytes, size_t length)
0064       : m_byte_order(lldb::eByteOrderInvalid) {
0065     SetOpcodeBytes(bytes, length);
0066   }
0067 
0068   void Clear() {
0069     m_byte_order = lldb::eByteOrderInvalid;
0070     m_type = Opcode::eTypeInvalid;
0071   }
0072 
0073   Opcode::Type GetType() const { return m_type; }
0074 
0075   uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const {
0076     switch (m_type) {
0077     case Opcode::eTypeInvalid:
0078       break;
0079     case Opcode::eType8:
0080       return m_data.inst8;
0081     case Opcode::eType16:
0082       break;
0083     case Opcode::eType16_2:
0084       break;
0085     case Opcode::eType32:
0086       break;
0087     case Opcode::eType64:
0088       break;
0089     case Opcode::eTypeBytes:
0090       break;
0091     }
0092     return invalid_opcode;
0093   }
0094 
0095   uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const {
0096     switch (m_type) {
0097     case Opcode::eTypeInvalid:
0098       break;
0099     case Opcode::eType8:
0100       return m_data.inst8;
0101     case Opcode::eType16:
0102       return GetEndianSwap() ? llvm::byteswap<uint16_t>(m_data.inst16)
0103                              : m_data.inst16;
0104     case Opcode::eType16_2:
0105       break;
0106     case Opcode::eType32:
0107       break;
0108     case Opcode::eType64:
0109       break;
0110     case Opcode::eTypeBytes:
0111       break;
0112     }
0113     return invalid_opcode;
0114   }
0115 
0116   uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const {
0117     switch (m_type) {
0118     case Opcode::eTypeInvalid:
0119       break;
0120     case Opcode::eType8:
0121       return m_data.inst8;
0122     case Opcode::eType16:
0123       return GetEndianSwap() ? llvm::byteswap<uint16_t>(m_data.inst16)
0124                              : m_data.inst16;
0125     case Opcode::eType16_2: // passthrough
0126     case Opcode::eType32:
0127       return GetEndianSwap() ? llvm::byteswap<uint32_t>(m_data.inst32)
0128                              : m_data.inst32;
0129     case Opcode::eType64:
0130       break;
0131     case Opcode::eTypeBytes:
0132       break;
0133     }
0134     return invalid_opcode;
0135   }
0136 
0137   uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const {
0138     switch (m_type) {
0139     case Opcode::eTypeInvalid:
0140       break;
0141     case Opcode::eType8:
0142       return m_data.inst8;
0143     case Opcode::eType16:
0144       return GetEndianSwap() ? llvm::byteswap<uint16_t>(m_data.inst16)
0145                              : m_data.inst16;
0146     case Opcode::eType16_2: // passthrough
0147     case Opcode::eType32:
0148       return GetEndianSwap() ? llvm::byteswap<uint32_t>(m_data.inst32)
0149                              : m_data.inst32;
0150     case Opcode::eType64:
0151       return GetEndianSwap() ? llvm::byteswap<uint64_t>(m_data.inst64)
0152                              : m_data.inst64;
0153     case Opcode::eTypeBytes:
0154       break;
0155     }
0156     return invalid_opcode;
0157   }
0158 
0159   void SetOpcode8(uint8_t inst, lldb::ByteOrder order) {
0160     m_type = eType8;
0161     m_data.inst8 = inst;
0162     m_byte_order = order;
0163   }
0164 
0165   void SetOpcode16(uint16_t inst, lldb::ByteOrder order) {
0166     m_type = eType16;
0167     m_data.inst16 = inst;
0168     m_byte_order = order;
0169   }
0170 
0171   void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) {
0172     m_type = eType16_2;
0173     m_data.inst32 = inst;
0174     m_byte_order = order;
0175   }
0176 
0177   void SetOpcode32(uint32_t inst, lldb::ByteOrder order) {
0178     m_type = eType32;
0179     m_data.inst32 = inst;
0180     m_byte_order = order;
0181   }
0182 
0183   void SetOpcode64(uint64_t inst, lldb::ByteOrder order) {
0184     m_type = eType64;
0185     m_data.inst64 = inst;
0186     m_byte_order = order;
0187   }
0188 
0189   void SetOpcodeBytes(const void *bytes, size_t length) {
0190     if (bytes != nullptr && length > 0) {
0191       m_type = eTypeBytes;
0192       m_data.inst.length = length;
0193       assert(length < sizeof(m_data.inst.bytes));
0194       memcpy(m_data.inst.bytes, bytes, length);
0195       m_byte_order = lldb::eByteOrderInvalid;
0196     } else {
0197       m_type = eTypeInvalid;
0198       m_data.inst.length = 0;
0199     }
0200   }
0201 
0202   int Dump(Stream *s, uint32_t min_byte_width);
0203 
0204   const void *GetOpcodeBytes() const {
0205     return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr);
0206   }
0207 
0208   uint32_t GetByteSize() const {
0209     switch (m_type) {
0210     case Opcode::eTypeInvalid:
0211       break;
0212     case Opcode::eType8:
0213       return sizeof(m_data.inst8);
0214     case Opcode::eType16:
0215       return sizeof(m_data.inst16);
0216     case Opcode::eType16_2: // passthrough
0217     case Opcode::eType32:
0218       return sizeof(m_data.inst32);
0219     case Opcode::eType64:
0220       return sizeof(m_data.inst64);
0221     case Opcode::eTypeBytes:
0222       return m_data.inst.length;
0223     }
0224     return 0;
0225   }
0226 
0227   // Get the opcode exactly as it would be laid out in memory.
0228   uint32_t GetData(DataExtractor &data) const;
0229 
0230 protected:
0231   friend class lldb::SBInstruction;
0232 
0233   const void *GetOpcodeDataBytes() const {
0234     switch (m_type) {
0235     case Opcode::eTypeInvalid:
0236       break;
0237     case Opcode::eType8:
0238       return &m_data.inst8;
0239     case Opcode::eType16:
0240       return &m_data.inst16;
0241     case Opcode::eType16_2: // passthrough
0242     case Opcode::eType32:
0243       return &m_data.inst32;
0244     case Opcode::eType64:
0245       return &m_data.inst64;
0246     case Opcode::eTypeBytes:
0247       return m_data.inst.bytes;
0248     }
0249     return nullptr;
0250   }
0251 
0252   lldb::ByteOrder GetDataByteOrder() const;
0253 
0254   bool GetEndianSwap() const {
0255     return (m_byte_order == lldb::eByteOrderBig &&
0256             endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
0257            (m_byte_order == lldb::eByteOrderLittle &&
0258             endian::InlHostByteOrder() == lldb::eByteOrderBig);
0259   }
0260 
0261   lldb::ByteOrder m_byte_order = lldb::eByteOrderInvalid;
0262 
0263   Opcode::Type m_type = eTypeInvalid;
0264   union {
0265     uint8_t inst8;
0266     uint16_t inst16;
0267     uint32_t inst32;
0268     uint64_t inst64;
0269     struct {
0270       uint8_t bytes[16]; // This must be big enough to handle any opcode for any
0271                          // supported target.
0272       uint8_t length;
0273     } inst;
0274   } m_data;
0275 };
0276 
0277 } // namespace lldb_private
0278 
0279 #endif // LLDB_CORE_OPCODE_H