1 //===-- Opcode.h ------------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef lldb_Opcode_h 11 #define lldb_Opcode_h 12 13 // C Includes 14 #include <string.h> 15 16 // C++ Includes 17 // Other libraries and framework includes 18 #include "llvm/Support/MathExtras.h" 19 // Project includes 20 #include "lldb/Host/Endian.h" 21 #include "lldb/lldb-public.h" 22 23 namespace lldb 24 { 25 class SBInstruction; 26 } 27 28 namespace lldb_private { 29 30 class Opcode 31 { 32 public: 33 enum Type 34 { 35 eTypeInvalid, 36 eType8, 37 eType16, 38 eType16_2, // a 32-bit Thumb instruction, made up of two words 39 eType32, 40 eType64, 41 eTypeBytes 42 }; 43 Opcode()44 Opcode () : m_byte_order (lldb::eByteOrderInvalid), m_type (eTypeInvalid) 45 { 46 } 47 Opcode(uint8_t inst,lldb::ByteOrder order)48 Opcode (uint8_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType8) 49 { 50 m_data.inst8 = inst; 51 } 52 Opcode(uint16_t inst,lldb::ByteOrder order)53 Opcode (uint16_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType16) 54 { 55 m_data.inst16 = inst; 56 } 57 Opcode(uint32_t inst,lldb::ByteOrder order)58 Opcode (uint32_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType32) 59 { 60 m_data.inst32 = inst; 61 } 62 Opcode(uint64_t inst,lldb::ByteOrder order)63 Opcode (uint64_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType64) 64 { 65 m_data.inst64 = inst; 66 } 67 Opcode(uint8_t * bytes,size_t length)68 Opcode (uint8_t *bytes, size_t length) : m_byte_order (lldb::eByteOrderInvalid) 69 { 70 SetOpcodeBytes (bytes, length); 71 } 72 73 void Clear()74 Clear() 75 { 76 m_byte_order = lldb::eByteOrderInvalid; 77 m_type = Opcode::eTypeInvalid; 78 } 79 Opcode::Type GetType()80 GetType () const 81 { 82 return m_type; 83 } 84 85 uint8_t 86 GetOpcode8 (uint8_t invalid_opcode = UINT8_MAX) const 87 { 88 switch (m_type) 89 { 90 case Opcode::eTypeInvalid: break; 91 case Opcode::eType8: return m_data.inst8; 92 case Opcode::eType16: break; 93 case Opcode::eType16_2: break; 94 case Opcode::eType32: break; 95 case Opcode::eType64: break; 96 case Opcode::eTypeBytes: break; 97 } 98 return invalid_opcode; 99 } 100 101 uint16_t 102 GetOpcode16 (uint16_t invalid_opcode = UINT16_MAX) const 103 { 104 switch (m_type) 105 { 106 case Opcode::eTypeInvalid: break; 107 case Opcode::eType8: return m_data.inst8; 108 case Opcode::eType16: return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; 109 case Opcode::eType16_2: break; 110 case Opcode::eType32: break; 111 case Opcode::eType64: break; 112 case Opcode::eTypeBytes: break; 113 } 114 return invalid_opcode; 115 } 116 117 uint32_t 118 GetOpcode32 (uint32_t invalid_opcode = UINT32_MAX) const 119 { 120 switch (m_type) 121 { 122 case Opcode::eTypeInvalid: break; 123 case Opcode::eType8: return m_data.inst8; 124 case Opcode::eType16: return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; 125 case Opcode::eType16_2: // passthrough 126 case Opcode::eType32: return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; 127 case Opcode::eType64: break; 128 case Opcode::eTypeBytes: break; 129 } 130 return invalid_opcode; 131 } 132 133 uint64_t 134 GetOpcode64 (uint64_t invalid_opcode = UINT64_MAX) const 135 { 136 switch (m_type) 137 { 138 case Opcode::eTypeInvalid: break; 139 case Opcode::eType8: return m_data.inst8; 140 case Opcode::eType16: return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; 141 case Opcode::eType16_2: // passthrough 142 case Opcode::eType32: return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; 143 case Opcode::eType64: return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64; 144 case Opcode::eTypeBytes: break; 145 } 146 return invalid_opcode; 147 } 148 149 void SetOpcode8(uint8_t inst,lldb::ByteOrder order)150 SetOpcode8 (uint8_t inst, lldb::ByteOrder order) 151 { 152 m_type = eType8; 153 m_data.inst8 = inst; 154 m_byte_order = order; 155 } 156 157 void SetOpcode16(uint16_t inst,lldb::ByteOrder order)158 SetOpcode16 (uint16_t inst, lldb::ByteOrder order) 159 { 160 m_type = eType16; 161 m_data.inst16 = inst; 162 m_byte_order = order; 163 } 164 165 void SetOpcode16_2(uint32_t inst,lldb::ByteOrder order)166 SetOpcode16_2 (uint32_t inst, lldb::ByteOrder order) 167 { 168 m_type = eType16_2; 169 m_data.inst32 = inst; 170 m_byte_order = order; 171 } 172 173 void SetOpcode32(uint32_t inst,lldb::ByteOrder order)174 SetOpcode32 (uint32_t inst, lldb::ByteOrder order) 175 { 176 m_type = eType32; 177 m_data.inst32 = inst; 178 m_byte_order = order; 179 } 180 181 void SetOpcode64(uint64_t inst,lldb::ByteOrder order)182 SetOpcode64 (uint64_t inst, lldb::ByteOrder order) 183 { 184 m_type = eType64; 185 m_data.inst64 = inst; 186 m_byte_order = order; 187 } 188 189 void SetOpcodeBytes(const void * bytes,size_t length)190 SetOpcodeBytes (const void *bytes, size_t length) 191 { 192 if (bytes && length > 0) 193 { 194 m_type = eTypeBytes; 195 m_data.inst.length = length; 196 assert (length < sizeof (m_data.inst.bytes)); 197 memcpy (m_data.inst.bytes, bytes, length); 198 m_byte_order = lldb::eByteOrderInvalid; 199 } 200 else 201 { 202 m_type = eTypeInvalid; 203 m_data.inst.length = 0; 204 } 205 } 206 207 int 208 Dump (Stream *s, uint32_t min_byte_width); 209 210 const void * GetOpcodeBytes()211 GetOpcodeBytes () const 212 { 213 if (m_type == Opcode::eTypeBytes) 214 return m_data.inst.bytes; 215 return NULL; 216 } 217 218 uint32_t GetByteSize()219 GetByteSize () const 220 { 221 switch (m_type) 222 { 223 case Opcode::eTypeInvalid: break; 224 case Opcode::eType8: return sizeof(m_data.inst8); 225 case Opcode::eType16: return sizeof(m_data.inst16); 226 case Opcode::eType16_2: // passthrough 227 case Opcode::eType32: return sizeof(m_data.inst32); 228 case Opcode::eType64: return sizeof(m_data.inst64); 229 case Opcode::eTypeBytes: return m_data.inst.length; 230 } 231 return 0; 232 } 233 234 // Get the opcode exactly as it would be laid out in memory. 235 uint32_t 236 GetData (DataExtractor &data) const; 237 238 protected: 239 240 friend class lldb::SBInstruction; 241 242 const void * GetOpcodeDataBytes()243 GetOpcodeDataBytes () const 244 { 245 switch (m_type) 246 { 247 case Opcode::eTypeInvalid: break; 248 case Opcode::eType8: return &m_data.inst8; 249 case Opcode::eType16: return &m_data.inst16; 250 case Opcode::eType16_2: // passthrough 251 case Opcode::eType32: return &m_data.inst32; 252 case Opcode::eType64: return &m_data.inst64; 253 case Opcode::eTypeBytes: return m_data.inst.bytes; 254 } 255 return NULL; 256 } 257 258 lldb::ByteOrder 259 GetDataByteOrder () const; 260 261 bool GetEndianSwap()262 GetEndianSwap() const 263 { 264 return (m_byte_order == lldb::eByteOrderBig && lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) || 265 (m_byte_order == lldb::eByteOrderLittle && lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig); 266 } 267 268 lldb::ByteOrder m_byte_order; 269 270 Opcode::Type m_type; 271 union 272 { 273 uint8_t inst8; 274 uint16_t inst16; 275 uint32_t inst32; 276 uint64_t inst64; 277 struct 278 { 279 uint8_t bytes[16]; // This must be big enough to handle any opcode for any supported target. 280 uint8_t length; 281 } inst; 282 } m_data; 283 }; 284 285 } // namespace lldb_private 286 287 #endif // lldb_Opcode_h 288