xref: /freebsd/contrib/llvm-project/lldb/source/Core/Opcode.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1 //===-- Opcode.cpp --------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Core/Opcode.h"
10 
11 #include "lldb/Utility/DataBufferHeap.h"
12 #include "lldb/Utility/DataExtractor.h"
13 #include "lldb/Utility/Endian.h"
14 #include "lldb/Utility/Stream.h"
15 #include "lldb/lldb-forward.h"
16 
17 #include <memory>
18 
19 #include <cinttypes>
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
Dump(Stream * s,uint32_t min_byte_width)24 int Opcode::Dump(Stream *s, uint32_t min_byte_width) {
25   const uint32_t previous_bytes = s->GetWrittenBytes();
26   switch (m_type) {
27   case Opcode::eTypeInvalid:
28     s->PutCString("<invalid>");
29     break;
30   case Opcode::eType8:
31     s->Printf("0x%2.2x", m_data.inst8);
32     break;
33   case Opcode::eType16:
34     s->Printf("0x%4.4x", m_data.inst16);
35     break;
36   case Opcode::eType16_2:
37   case Opcode::eType32:
38     s->Printf("0x%8.8x", m_data.inst32);
39     break;
40 
41   case Opcode::eType64:
42     s->Printf("0x%16.16" PRIx64, m_data.inst64);
43     break;
44 
45   case Opcode::eTypeBytes:
46     for (uint32_t i = 0; i < m_data.inst.length; ++i) {
47       if (i > 0)
48         s->PutChar(' ');
49       s->Printf("%2.2x", m_data.inst.bytes[i]);
50     }
51     break;
52   }
53 
54   uint32_t bytes_written_so_far = s->GetWrittenBytes() - previous_bytes;
55   // Add spaces to make sure bytes display comes out even in case opcodes aren't
56   // all the same size.
57   if (bytes_written_so_far < min_byte_width)
58     s->Printf("%*s", min_byte_width - bytes_written_so_far, "");
59   return s->GetWrittenBytes() - previous_bytes;
60 }
61 
GetDataByteOrder() const62 lldb::ByteOrder Opcode::GetDataByteOrder() const {
63   if (m_byte_order != eByteOrderInvalid) {
64     return m_byte_order;
65   }
66   switch (m_type) {
67   case Opcode::eTypeInvalid:
68     break;
69   case Opcode::eType8:
70   case Opcode::eType16:
71   case Opcode::eType16_2:
72   case Opcode::eType32:
73   case Opcode::eType64:
74     return endian::InlHostByteOrder();
75   case Opcode::eTypeBytes:
76     break;
77   }
78   return eByteOrderInvalid;
79 }
80 
GetData(DataExtractor & data) const81 uint32_t Opcode::GetData(DataExtractor &data) const {
82   uint32_t byte_size = GetByteSize();
83   uint8_t swap_buf[8];
84   const void *buf = nullptr;
85 
86   if (byte_size > 0) {
87     if (!GetEndianSwap()) {
88       if (m_type == Opcode::eType16_2) {
89         // 32 bit thumb instruction, we need to sizzle this a bit
90         swap_buf[0] = m_data.inst.bytes[2];
91         swap_buf[1] = m_data.inst.bytes[3];
92         swap_buf[2] = m_data.inst.bytes[0];
93         swap_buf[3] = m_data.inst.bytes[1];
94         buf = swap_buf;
95       } else {
96         buf = GetOpcodeDataBytes();
97       }
98     } else {
99       switch (m_type) {
100       case Opcode::eTypeInvalid:
101         break;
102       case Opcode::eType8:
103         buf = GetOpcodeDataBytes();
104         break;
105       case Opcode::eType16:
106         *(uint16_t *)swap_buf = llvm::byteswap<uint16_t>(m_data.inst16);
107         buf = swap_buf;
108         break;
109       case Opcode::eType16_2:
110         swap_buf[0] = m_data.inst.bytes[1];
111         swap_buf[1] = m_data.inst.bytes[0];
112         swap_buf[2] = m_data.inst.bytes[3];
113         swap_buf[3] = m_data.inst.bytes[2];
114         buf = swap_buf;
115         break;
116       case Opcode::eType32:
117         *(uint32_t *)swap_buf = llvm::byteswap<uint32_t>(m_data.inst32);
118         buf = swap_buf;
119         break;
120       case Opcode::eType64:
121         *(uint32_t *)swap_buf = llvm::byteswap<uint64_t>(m_data.inst64);
122         buf = swap_buf;
123         break;
124       case Opcode::eTypeBytes:
125         buf = GetOpcodeDataBytes();
126         break;
127       }
128     }
129   }
130   if (buf != nullptr) {
131     DataBufferSP buffer_sp;
132 
133     buffer_sp = std::make_shared<DataBufferHeap>(buf, byte_size);
134     data.SetByteOrder(GetDataByteOrder());
135     data.SetData(buffer_sp);
136     return byte_size;
137   }
138   data.Clear();
139   return 0;
140 }
141