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