xref: /freebsd-src/contrib/llvm-project/lldb/source/Core/Opcode.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- Opcode.cpp --------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/Opcode.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
120b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
130b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
140b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
150b57cec5SDimitry Andric #include "lldb/lldb-forward.h"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include <memory>
180b57cec5SDimitry Andric 
19fe6060f1SDimitry Andric #include <cinttypes>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace lldb;
220b57cec5SDimitry Andric using namespace lldb_private;
230b57cec5SDimitry Andric 
Dump(Stream * s,uint32_t min_byte_width)240b57cec5SDimitry Andric int Opcode::Dump(Stream *s, uint32_t min_byte_width) {
250b57cec5SDimitry Andric   const uint32_t previous_bytes = s->GetWrittenBytes();
260b57cec5SDimitry Andric   switch (m_type) {
270b57cec5SDimitry Andric   case Opcode::eTypeInvalid:
280b57cec5SDimitry Andric     s->PutCString("<invalid>");
290b57cec5SDimitry Andric     break;
300b57cec5SDimitry Andric   case Opcode::eType8:
310b57cec5SDimitry Andric     s->Printf("0x%2.2x", m_data.inst8);
320b57cec5SDimitry Andric     break;
330b57cec5SDimitry Andric   case Opcode::eType16:
340b57cec5SDimitry Andric     s->Printf("0x%4.4x", m_data.inst16);
350b57cec5SDimitry Andric     break;
360b57cec5SDimitry Andric   case Opcode::eType16_2:
370b57cec5SDimitry Andric   case Opcode::eType32:
380b57cec5SDimitry Andric     s->Printf("0x%8.8x", m_data.inst32);
390b57cec5SDimitry Andric     break;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   case Opcode::eType64:
420b57cec5SDimitry Andric     s->Printf("0x%16.16" PRIx64, m_data.inst64);
430b57cec5SDimitry Andric     break;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   case Opcode::eTypeBytes:
460b57cec5SDimitry Andric     for (uint32_t i = 0; i < m_data.inst.length; ++i) {
470b57cec5SDimitry Andric       if (i > 0)
480b57cec5SDimitry Andric         s->PutChar(' ');
490b57cec5SDimitry Andric       s->Printf("%2.2x", m_data.inst.bytes[i]);
500b57cec5SDimitry Andric     }
510b57cec5SDimitry Andric     break;
520b57cec5SDimitry Andric   }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   uint32_t bytes_written_so_far = s->GetWrittenBytes() - previous_bytes;
550b57cec5SDimitry Andric   // Add spaces to make sure bytes display comes out even in case opcodes aren't
560b57cec5SDimitry Andric   // all the same size.
570b57cec5SDimitry Andric   if (bytes_written_so_far < min_byte_width)
580b57cec5SDimitry Andric     s->Printf("%*s", min_byte_width - bytes_written_so_far, "");
590b57cec5SDimitry Andric   return s->GetWrittenBytes() - previous_bytes;
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
GetDataByteOrder() const620b57cec5SDimitry Andric lldb::ByteOrder Opcode::GetDataByteOrder() const {
630b57cec5SDimitry Andric   if (m_byte_order != eByteOrderInvalid) {
640b57cec5SDimitry Andric     return m_byte_order;
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric   switch (m_type) {
670b57cec5SDimitry Andric   case Opcode::eTypeInvalid:
680b57cec5SDimitry Andric     break;
690b57cec5SDimitry Andric   case Opcode::eType8:
700b57cec5SDimitry Andric   case Opcode::eType16:
710b57cec5SDimitry Andric   case Opcode::eType16_2:
720b57cec5SDimitry Andric   case Opcode::eType32:
730b57cec5SDimitry Andric   case Opcode::eType64:
740b57cec5SDimitry Andric     return endian::InlHostByteOrder();
750b57cec5SDimitry Andric   case Opcode::eTypeBytes:
760b57cec5SDimitry Andric     break;
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric   return eByteOrderInvalid;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
GetData(DataExtractor & data) const810b57cec5SDimitry Andric uint32_t Opcode::GetData(DataExtractor &data) const {
820b57cec5SDimitry Andric   uint32_t byte_size = GetByteSize();
830b57cec5SDimitry Andric   uint8_t swap_buf[8];
840b57cec5SDimitry Andric   const void *buf = nullptr;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   if (byte_size > 0) {
870b57cec5SDimitry Andric     if (!GetEndianSwap()) {
880b57cec5SDimitry Andric       if (m_type == Opcode::eType16_2) {
890b57cec5SDimitry Andric         // 32 bit thumb instruction, we need to sizzle this a bit
900b57cec5SDimitry Andric         swap_buf[0] = m_data.inst.bytes[2];
910b57cec5SDimitry Andric         swap_buf[1] = m_data.inst.bytes[3];
920b57cec5SDimitry Andric         swap_buf[2] = m_data.inst.bytes[0];
930b57cec5SDimitry Andric         swap_buf[3] = m_data.inst.bytes[1];
940b57cec5SDimitry Andric         buf = swap_buf;
950b57cec5SDimitry Andric       } else {
960b57cec5SDimitry Andric         buf = GetOpcodeDataBytes();
970b57cec5SDimitry Andric       }
980b57cec5SDimitry Andric     } else {
990b57cec5SDimitry Andric       switch (m_type) {
1000b57cec5SDimitry Andric       case Opcode::eTypeInvalid:
1010b57cec5SDimitry Andric         break;
1020b57cec5SDimitry Andric       case Opcode::eType8:
1030b57cec5SDimitry Andric         buf = GetOpcodeDataBytes();
1040b57cec5SDimitry Andric         break;
1050b57cec5SDimitry Andric       case Opcode::eType16:
106*06c3fb27SDimitry Andric         *(uint16_t *)swap_buf = llvm::byteswap<uint16_t>(m_data.inst16);
1070b57cec5SDimitry Andric         buf = swap_buf;
1080b57cec5SDimitry Andric         break;
1090b57cec5SDimitry Andric       case Opcode::eType16_2:
1100b57cec5SDimitry Andric         swap_buf[0] = m_data.inst.bytes[1];
1110b57cec5SDimitry Andric         swap_buf[1] = m_data.inst.bytes[0];
1120b57cec5SDimitry Andric         swap_buf[2] = m_data.inst.bytes[3];
1130b57cec5SDimitry Andric         swap_buf[3] = m_data.inst.bytes[2];
1140b57cec5SDimitry Andric         buf = swap_buf;
1150b57cec5SDimitry Andric         break;
1160b57cec5SDimitry Andric       case Opcode::eType32:
117*06c3fb27SDimitry Andric         *(uint32_t *)swap_buf = llvm::byteswap<uint32_t>(m_data.inst32);
1180b57cec5SDimitry Andric         buf = swap_buf;
1190b57cec5SDimitry Andric         break;
1200b57cec5SDimitry Andric       case Opcode::eType64:
121*06c3fb27SDimitry Andric         *(uint32_t *)swap_buf = llvm::byteswap<uint64_t>(m_data.inst64);
1220b57cec5SDimitry Andric         buf = swap_buf;
1230b57cec5SDimitry Andric         break;
1240b57cec5SDimitry Andric       case Opcode::eTypeBytes:
1250b57cec5SDimitry Andric         buf = GetOpcodeDataBytes();
1260b57cec5SDimitry Andric         break;
1270b57cec5SDimitry Andric       }
1280b57cec5SDimitry Andric     }
1290b57cec5SDimitry Andric   }
1300b57cec5SDimitry Andric   if (buf != nullptr) {
1310b57cec5SDimitry Andric     DataBufferSP buffer_sp;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric     buffer_sp = std::make_shared<DataBufferHeap>(buf, byte_size);
1340b57cec5SDimitry Andric     data.SetByteOrder(GetDataByteOrder());
1350b57cec5SDimitry Andric     data.SetData(buffer_sp);
1360b57cec5SDimitry Andric     return byte_size;
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric   data.Clear();
1390b57cec5SDimitry Andric   return 0;
1400b57cec5SDimitry Andric }
141