1 //===-- Opcode.cpp ----------------------------------------------*- 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 #include "lldb/Core/Opcode.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 #include "llvm/ADT/Triple.h"
16 
17 // Project includes
18 #include "lldb/Core/ArchSpec.h"
19 #include "lldb/Core/DataBufferHeap.h"
20 #include "lldb/Core/DataExtractor.h"
21 #include "lldb/Core/Stream.h"
22 #include "lldb/Host/Endian.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 int
28 Opcode::Dump (Stream *s, uint32_t min_byte_width)
29 {
30     int bytes_written = 0;
31     switch (m_type)
32     {
33     case Opcode::eTypeInvalid:
34         bytes_written = s->PutCString ("<invalid>");
35         break;
36     case Opcode::eType8:
37         bytes_written = s->Printf ("0x%2.2x", m_data.inst8);
38         break;
39     case Opcode::eType16:
40         bytes_written = s->Printf ("0x%4.4x", m_data.inst16);
41         break;
42     case Opcode::eType16_2:
43     case Opcode::eType32:
44         bytes_written = s->Printf ("0x%8.8x", m_data.inst32);
45         break;
46 
47     case Opcode::eType64:
48         bytes_written = s->Printf ("0x%16.16" PRIx64, m_data.inst64);
49         break;
50 
51     case Opcode::eTypeBytes:
52         for (uint32_t i = 0; i < m_data.inst.length; ++i)
53         {
54             if (i > 0)
55                 bytes_written += s->PutChar (' ');
56             bytes_written += s->Printf ("%2.2x", m_data.inst.bytes[i]);
57         }
58         break;
59     }
60 
61     // Add spaces to make sure bytes dispay comes out even in case opcodes
62     // aren't all the same size
63     if (static_cast<uint32_t>(bytes_written) < min_byte_width)
64         bytes_written = s->Printf ("%*s", min_byte_width - bytes_written, "");
65     return bytes_written;
66 }
67 
68 lldb::ByteOrder
69 Opcode::GetDataByteOrder () const
70 {
71     if (m_byte_order != eByteOrderInvalid)
72     {
73         return m_byte_order;
74     }
75     switch (m_type)
76     {
77         case Opcode::eTypeInvalid: break;
78         case Opcode::eType8:
79         case Opcode::eType16:
80         case Opcode::eType16_2:
81         case Opcode::eType32:
82         case Opcode::eType64:    return endian::InlHostByteOrder();
83         case Opcode::eTypeBytes:
84             break;
85     }
86     return eByteOrderInvalid;
87 }
88 
89 uint32_t
90 Opcode::GetData (DataExtractor &data) const
91 {
92     uint32_t byte_size = GetByteSize ();
93     uint8_t swap_buf[8];
94     const void *buf = nullptr;
95 
96     if (byte_size > 0)
97     {
98         if (!GetEndianSwap())
99         {
100             if (m_type == Opcode::eType16_2)
101             {
102                 // 32 bit thumb instruction, we need to sizzle this a bit
103                 swap_buf[0] = m_data.inst.bytes[2];
104                 swap_buf[1] = m_data.inst.bytes[3];
105                 swap_buf[2] = m_data.inst.bytes[0];
106                 swap_buf[3] = m_data.inst.bytes[1];
107                 buf = swap_buf;
108             }
109             else
110             {
111                 buf = GetOpcodeDataBytes();
112             }
113         }
114         else
115         {
116             switch (m_type)
117             {
118                 case Opcode::eTypeInvalid:
119                     break;
120                 case Opcode::eType8:
121                     buf = GetOpcodeDataBytes();
122                     break;
123                 case Opcode::eType16:
124                     *(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16);
125                     buf = swap_buf;
126                     break;
127                 case Opcode::eType16_2:
128                     swap_buf[0] = m_data.inst.bytes[1];
129                     swap_buf[1] = m_data.inst.bytes[0];
130                     swap_buf[2] = m_data.inst.bytes[3];
131                     swap_buf[3] = m_data.inst.bytes[2];
132                     buf = swap_buf;
133                     break;
134                 case Opcode::eType32:
135                     *(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32);
136                     buf = swap_buf;
137                     break;
138                 case Opcode::eType64:
139                     *(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64);
140                     buf = swap_buf;
141                     break;
142                 case Opcode::eTypeBytes:
143                     buf = GetOpcodeDataBytes();
144                     break;
145             }
146         }
147     }
148     if (buf != nullptr)
149     {
150         DataBufferSP buffer_sp;
151 
152         buffer_sp.reset (new DataBufferHeap (buf, byte_size));
153         data.SetByteOrder(GetDataByteOrder());
154         data.SetData (buffer_sp);
155         return byte_size;
156     }
157     data.Clear();
158     return 0;
159 }
160