xref: /src/contrib/llvm-project/lldb/source/Core/Opcode.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1cfca06d7SDimitry Andric //===-- Opcode.cpp --------------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/Core/Opcode.h"
10f034231aSEd Maste 
1174a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
1274a628f7SDimitry Andric #include "lldb/Utility/DataExtractor.h"
1374a628f7SDimitry Andric #include "lldb/Utility/Endian.h"
1474a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
1594994d37SDimitry Andric #include "lldb/lldb-forward.h"
16f3fbd1c0SDimitry Andric 
1794994d37SDimitry Andric #include <memory>
1874a628f7SDimitry Andric 
19344a3780SDimitry Andric #include <cinttypes>
20f034231aSEd Maste 
21f034231aSEd Maste using namespace lldb;
22f034231aSEd Maste using namespace lldb_private;
23f034231aSEd Maste 
Dump(Stream * s,uint32_t min_byte_width)2414f1b3e8SDimitry Andric int Opcode::Dump(Stream *s, uint32_t min_byte_width) {
2594994d37SDimitry Andric   const uint32_t previous_bytes = s->GetWrittenBytes();
2614f1b3e8SDimitry Andric   switch (m_type) {
27f034231aSEd Maste   case Opcode::eTypeInvalid:
2894994d37SDimitry Andric     s->PutCString("<invalid>");
29f034231aSEd Maste     break;
30f034231aSEd Maste   case Opcode::eType8:
3194994d37SDimitry Andric     s->Printf("0x%2.2x", m_data.inst8);
32f034231aSEd Maste     break;
33f034231aSEd Maste   case Opcode::eType16:
3494994d37SDimitry Andric     s->Printf("0x%4.4x", m_data.inst16);
35f034231aSEd Maste     break;
36f034231aSEd Maste   case Opcode::eType16_2:
37f034231aSEd Maste   case Opcode::eType32:
3894994d37SDimitry Andric     s->Printf("0x%8.8x", m_data.inst32);
39f034231aSEd Maste     break;
40f034231aSEd Maste 
41f034231aSEd Maste   case Opcode::eType64:
4294994d37SDimitry Andric     s->Printf("0x%16.16" PRIx64, m_data.inst64);
43f034231aSEd Maste     break;
44f034231aSEd Maste 
45f034231aSEd Maste   case Opcode::eTypeBytes:
4614f1b3e8SDimitry Andric     for (uint32_t i = 0; i < m_data.inst.length; ++i) {
47f034231aSEd Maste       if (i > 0)
4894994d37SDimitry Andric         s->PutChar(' ');
4994994d37SDimitry Andric       s->Printf("%2.2x", m_data.inst.bytes[i]);
50f034231aSEd Maste     }
51f034231aSEd Maste     break;
52f034231aSEd Maste   }
53f034231aSEd Maste 
5494994d37SDimitry Andric   uint32_t bytes_written_so_far = s->GetWrittenBytes() - previous_bytes;
5594994d37SDimitry Andric   // Add spaces to make sure bytes display comes out even in case opcodes aren't
5694994d37SDimitry Andric   // all the same size.
5794994d37SDimitry Andric   if (bytes_written_so_far < min_byte_width)
5894994d37SDimitry Andric     s->Printf("%*s", min_byte_width - bytes_written_so_far, "");
5994994d37SDimitry Andric   return s->GetWrittenBytes() - previous_bytes;
60f034231aSEd Maste }
61f034231aSEd Maste 
GetDataByteOrder() const6214f1b3e8SDimitry Andric lldb::ByteOrder Opcode::GetDataByteOrder() const {
6314f1b3e8SDimitry Andric   if (m_byte_order != eByteOrderInvalid) {
64866dcdacSEd Maste     return m_byte_order;
65866dcdacSEd Maste   }
6614f1b3e8SDimitry Andric   switch (m_type) {
6714f1b3e8SDimitry Andric   case Opcode::eTypeInvalid:
6814f1b3e8SDimitry Andric     break;
69f034231aSEd Maste   case Opcode::eType8:
70f034231aSEd Maste   case Opcode::eType16:
71f034231aSEd Maste   case Opcode::eType16_2:
72f034231aSEd Maste   case Opcode::eType32:
7314f1b3e8SDimitry Andric   case Opcode::eType64:
7414f1b3e8SDimitry Andric     return endian::InlHostByteOrder();
75f034231aSEd Maste   case Opcode::eTypeBytes:
76f034231aSEd Maste     break;
77f034231aSEd Maste   }
78f034231aSEd Maste   return eByteOrderInvalid;
79f034231aSEd Maste }
80f034231aSEd Maste 
GetData(DataExtractor & data) const8114f1b3e8SDimitry Andric uint32_t Opcode::GetData(DataExtractor &data) const {
82f034231aSEd Maste   uint32_t byte_size = GetByteSize();
83866dcdacSEd Maste   uint8_t swap_buf[8];
84f3fbd1c0SDimitry Andric   const void *buf = nullptr;
85f034231aSEd Maste 
8614f1b3e8SDimitry Andric   if (byte_size > 0) {
8714f1b3e8SDimitry Andric     if (!GetEndianSwap()) {
8814f1b3e8SDimitry Andric       if (m_type == Opcode::eType16_2) {
89866dcdacSEd Maste         // 32 bit thumb instruction, we need to sizzle this a bit
90866dcdacSEd Maste         swap_buf[0] = m_data.inst.bytes[2];
91866dcdacSEd Maste         swap_buf[1] = m_data.inst.bytes[3];
92866dcdacSEd Maste         swap_buf[2] = m_data.inst.bytes[0];
93866dcdacSEd Maste         swap_buf[3] = m_data.inst.bytes[1];
94866dcdacSEd Maste         buf = swap_buf;
9514f1b3e8SDimitry Andric       } else {
96866dcdacSEd Maste         buf = GetOpcodeDataBytes();
97866dcdacSEd Maste       }
9814f1b3e8SDimitry Andric     } else {
9914f1b3e8SDimitry Andric       switch (m_type) {
100f034231aSEd Maste       case Opcode::eTypeInvalid:
101f034231aSEd Maste         break;
102866dcdacSEd Maste       case Opcode::eType8:
103866dcdacSEd Maste         buf = GetOpcodeDataBytes();
104866dcdacSEd Maste         break;
105866dcdacSEd Maste       case Opcode::eType16:
1067fa27ce4SDimitry Andric         *(uint16_t *)swap_buf = llvm::byteswap<uint16_t>(m_data.inst16);
107866dcdacSEd Maste         buf = swap_buf;
108866dcdacSEd Maste         break;
109f034231aSEd Maste       case Opcode::eType16_2:
110866dcdacSEd Maste         swap_buf[0] = m_data.inst.bytes[1];
111866dcdacSEd Maste         swap_buf[1] = m_data.inst.bytes[0];
112866dcdacSEd Maste         swap_buf[2] = m_data.inst.bytes[3];
113866dcdacSEd Maste         swap_buf[3] = m_data.inst.bytes[2];
114866dcdacSEd Maste         buf = swap_buf;
115f034231aSEd Maste         break;
116f034231aSEd Maste       case Opcode::eType32:
1177fa27ce4SDimitry Andric         *(uint32_t *)swap_buf = llvm::byteswap<uint32_t>(m_data.inst32);
118866dcdacSEd Maste         buf = swap_buf;
119f034231aSEd Maste         break;
120866dcdacSEd Maste       case Opcode::eType64:
1217fa27ce4SDimitry Andric         *(uint32_t *)swap_buf = llvm::byteswap<uint64_t>(m_data.inst64);
122866dcdacSEd Maste         buf = swap_buf;
123866dcdacSEd Maste         break;
124866dcdacSEd Maste       case Opcode::eTypeBytes:
125866dcdacSEd Maste         buf = GetOpcodeDataBytes();
126f034231aSEd Maste         break;
127f034231aSEd Maste       }
128f034231aSEd Maste     }
129866dcdacSEd Maste   }
13014f1b3e8SDimitry Andric   if (buf != nullptr) {
131866dcdacSEd Maste     DataBufferSP buffer_sp;
132866dcdacSEd Maste 
13374a628f7SDimitry Andric     buffer_sp = std::make_shared<DataBufferHeap>(buf, byte_size);
134f034231aSEd Maste     data.SetByteOrder(GetDataByteOrder());
135f034231aSEd Maste     data.SetData(buffer_sp);
136f034231aSEd Maste     return byte_size;
137f034231aSEd Maste   }
138f034231aSEd Maste   data.Clear();
139f034231aSEd Maste   return 0;
140f034231aSEd Maste }
141