Opcode.h revision 269024
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 23namespace lldb 24{ 25 class SBInstruction; 26} 27 28namespace 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 44 Opcode () : m_byte_order (lldb::eByteOrderInvalid), m_type (eTypeInvalid) 45 { 46 } 47 48 Opcode (uint8_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType8) 49 { 50 m_data.inst8 = inst; 51 } 52 53 Opcode (uint16_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType16) 54 { 55 m_data.inst16 = inst; 56 } 57 58 Opcode (uint32_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType32) 59 { 60 m_data.inst32 = inst; 61 } 62 63 Opcode (uint64_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType64) 64 { 65 m_data.inst64 = inst; 66 } 67 68 Opcode (uint8_t *bytes, size_t length) : m_byte_order (lldb::eByteOrderInvalid) 69 { 70 SetOpcodeBytes (bytes, length); 71 } 72 73 void 74 Clear() 75 { 76 m_byte_order = lldb::eByteOrderInvalid; 77 m_type = Opcode::eTypeInvalid; 78 } 79 Opcode::Type 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 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 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 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 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 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 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 * 211 GetOpcodeBytes () const 212 { 213 if (m_type == Opcode::eTypeBytes) 214 return m_data.inst.bytes; 215 return NULL; 216 } 217 218 uint32_t 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 * 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 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