Home | History | Annotate | Download | only in Core
      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 
     42         Opcode () : m_type (eTypeInvalid)
     43         {
     44         }
     45 
     46         Opcode (uint8_t inst) : m_type (eType8)
     47         {
     48             m_data.inst8 = inst;
     49         }
     50 
     51         Opcode (uint16_t inst) : m_type (eType16)
     52         {
     53             m_data.inst16 = inst;
     54         }
     55 
     56         Opcode (uint32_t inst) : m_type (eType32)
     57         {
     58             m_data.inst32 = inst;
     59         }
     60 
     61         Opcode (uint64_t inst) : m_type (eType64)
     62         {
     63             m_data.inst64 = inst;
     64         }
     65 
     66         Opcode (uint8_t *bytes, size_t length)
     67         {
     68             SetOpcodeBytes (bytes, length);
     69         }
     70 
     71         void
     72         Clear()
     73         {
     74             m_type = Opcode::eTypeInvalid;
     75         }
     76         Opcode::Type
     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
    148         SetOpcode8 (uint8_t inst)
    149         {
    150             m_type = eType8;
    151             m_data.inst8 = inst;
    152         }
    153 
    154         void
    155         SetOpcode16 (uint16_t inst)
    156         {
    157             m_type = eType16;
    158             m_data.inst16 = inst;
    159         }
    160 
    161         void
    162         SetOpcode16_2 (uint32_t inst)
    163         {
    164             m_type = eType16_2;
    165             m_data.inst32 = inst;
    166         }
    167 
    168         void
    169         SetOpcode32 (uint32_t inst)
    170         {
    171             m_type = eType32;
    172             m_data.inst32 = inst;
    173         }
    174 
    175         void
    176         SetOpcode64 (uint64_t inst)
    177         {
    178             m_type = eType64;
    179             m_data.inst64 = inst;
    180         }
    181 
    182         void
    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 *
    203         GetOpcodeBytes () const
    204         {
    205             if (m_type == Opcode::eTypeBytes)
    206                 return m_data.inst.bytes;
    207             return NULL;
    208         }
    209 
    210         uint32_t
    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 *
    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