1254721Semaste//===-- Opcode.cpp ----------------------------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9254721Semaste#include "lldb/Core/Opcode.h" 10254721Semaste 11321369Sdim#include "lldb/Utility/DataBufferHeap.h" 12321369Sdim#include "lldb/Utility/DataExtractor.h" 13321369Sdim#include "lldb/Utility/Endian.h" 14321369Sdim#include "lldb/Utility/Stream.h" 15344779Sdim#include "lldb/lldb-forward.h" 16309124Sdim 17344779Sdim#include <memory> 18254721Semaste 19344779Sdim#include <inttypes.h> 20321369Sdim 21254721Semasteusing namespace lldb; 22254721Semasteusing namespace lldb_private; 23254721Semaste 24314564Sdimint Opcode::Dump(Stream *s, uint32_t min_byte_width) { 25344779Sdim const uint32_t previous_bytes = s->GetWrittenBytes(); 26314564Sdim switch (m_type) { 27314564Sdim case Opcode::eTypeInvalid: 28344779Sdim s->PutCString("<invalid>"); 29314564Sdim break; 30314564Sdim case Opcode::eType8: 31344779Sdim s->Printf("0x%2.2x", m_data.inst8); 32314564Sdim break; 33314564Sdim case Opcode::eType16: 34344779Sdim s->Printf("0x%4.4x", m_data.inst16); 35314564Sdim break; 36314564Sdim case Opcode::eType16_2: 37314564Sdim case Opcode::eType32: 38344779Sdim s->Printf("0x%8.8x", m_data.inst32); 39314564Sdim break; 40254721Semaste 41314564Sdim case Opcode::eType64: 42344779Sdim s->Printf("0x%16.16" PRIx64, m_data.inst64); 43314564Sdim break; 44254721Semaste 45314564Sdim case Opcode::eTypeBytes: 46314564Sdim for (uint32_t i = 0; i < m_data.inst.length; ++i) { 47314564Sdim if (i > 0) 48344779Sdim s->PutChar(' '); 49344779Sdim s->Printf("%2.2x", m_data.inst.bytes[i]); 50254721Semaste } 51314564Sdim break; 52314564Sdim } 53258054Semaste 54344779Sdim uint32_t bytes_written_so_far = s->GetWrittenBytes() - previous_bytes; 55344779Sdim // Add spaces to make sure bytes display comes out even in case opcodes aren't 56344779Sdim // all the same size. 57344779Sdim if (bytes_written_so_far < min_byte_width) 58344779Sdim s->Printf("%*s", min_byte_width - bytes_written_so_far, ""); 59344779Sdim return s->GetWrittenBytes() - previous_bytes; 60254721Semaste} 61254721Semaste 62314564Sdimlldb::ByteOrder Opcode::GetDataByteOrder() const { 63314564Sdim if (m_byte_order != eByteOrderInvalid) { 64314564Sdim return m_byte_order; 65314564Sdim } 66314564Sdim switch (m_type) { 67314564Sdim case Opcode::eTypeInvalid: 68314564Sdim break; 69314564Sdim case Opcode::eType8: 70314564Sdim case Opcode::eType16: 71314564Sdim case Opcode::eType16_2: 72314564Sdim case Opcode::eType32: 73314564Sdim case Opcode::eType64: 74314564Sdim return endian::InlHostByteOrder(); 75314564Sdim case Opcode::eTypeBytes: 76314564Sdim break; 77314564Sdim } 78314564Sdim return eByteOrderInvalid; 79254721Semaste} 80254721Semaste 81314564Sdimuint32_t Opcode::GetData(DataExtractor &data) const { 82314564Sdim uint32_t byte_size = GetByteSize(); 83314564Sdim uint8_t swap_buf[8]; 84314564Sdim const void *buf = nullptr; 85258054Semaste 86314564Sdim if (byte_size > 0) { 87314564Sdim if (!GetEndianSwap()) { 88314564Sdim if (m_type == Opcode::eType16_2) { 89314564Sdim // 32 bit thumb instruction, we need to sizzle this a bit 90314564Sdim swap_buf[0] = m_data.inst.bytes[2]; 91314564Sdim swap_buf[1] = m_data.inst.bytes[3]; 92314564Sdim swap_buf[2] = m_data.inst.bytes[0]; 93314564Sdim swap_buf[3] = m_data.inst.bytes[1]; 94314564Sdim buf = swap_buf; 95314564Sdim } else { 96314564Sdim buf = GetOpcodeDataBytes(); 97314564Sdim } 98314564Sdim } else { 99314564Sdim switch (m_type) { 100314564Sdim case Opcode::eTypeInvalid: 101314564Sdim break; 102314564Sdim case Opcode::eType8: 103314564Sdim buf = GetOpcodeDataBytes(); 104314564Sdim break; 105314564Sdim case Opcode::eType16: 106314564Sdim *(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16); 107314564Sdim buf = swap_buf; 108314564Sdim break; 109314564Sdim case Opcode::eType16_2: 110314564Sdim swap_buf[0] = m_data.inst.bytes[1]; 111314564Sdim swap_buf[1] = m_data.inst.bytes[0]; 112314564Sdim swap_buf[2] = m_data.inst.bytes[3]; 113314564Sdim swap_buf[3] = m_data.inst.bytes[2]; 114314564Sdim buf = swap_buf; 115314564Sdim break; 116314564Sdim case Opcode::eType32: 117314564Sdim *(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32); 118314564Sdim buf = swap_buf; 119314564Sdim break; 120314564Sdim case Opcode::eType64: 121314564Sdim *(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64); 122314564Sdim buf = swap_buf; 123314564Sdim break; 124314564Sdim case Opcode::eTypeBytes: 125314564Sdim buf = GetOpcodeDataBytes(); 126314564Sdim break; 127314564Sdim } 128254721Semaste } 129314564Sdim } 130314564Sdim if (buf != nullptr) { 131314564Sdim DataBufferSP buffer_sp; 132258054Semaste 133321369Sdim buffer_sp = std::make_shared<DataBufferHeap>(buf, byte_size); 134314564Sdim data.SetByteOrder(GetDataByteOrder()); 135314564Sdim data.SetData(buffer_sp); 136314564Sdim return byte_size; 137314564Sdim } 138314564Sdim data.Clear(); 139314564Sdim return 0; 140254721Semaste} 141