1ba812f42SGreg Clayton //===-- Opcode.cpp ----------------------------------------------*- C++ -*-===// 20ae96273SGreg Clayton // 30ae96273SGreg Clayton // The LLVM Compiler Infrastructure 40ae96273SGreg Clayton // 50ae96273SGreg Clayton // This file is distributed under the University of Illinois Open Source 60ae96273SGreg Clayton // License. See LICENSE.TXT for details. 70ae96273SGreg Clayton // 80ae96273SGreg Clayton //===----------------------------------------------------------------------===// 90ae96273SGreg Clayton 100ae96273SGreg Clayton #include "lldb/Core/Opcode.h" 110ae96273SGreg Clayton 120ae96273SGreg Clayton // C Includes 130ae96273SGreg Clayton // C++ Includes 140ae96273SGreg Clayton // Other libraries and framework includes 15ba812f42SGreg Clayton #include "llvm/ADT/Triple.h" 168918372dSEugene Zelenko 170ae96273SGreg Clayton // Project includes 18ba812f42SGreg Clayton #include "lldb/Core/ArchSpec.h" 19*666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h" 20*666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h" 2101c3243fSZachary Turner #include "lldb/Utility/Endian.h" 22bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 230ae96273SGreg Clayton 240ae96273SGreg Clayton using namespace lldb; 250ae96273SGreg Clayton using namespace lldb_private; 261080edbcSGreg Clayton 27b9c1b51eSKate Stone int Opcode::Dump(Stream *s, uint32_t min_byte_width) { 281080edbcSGreg Clayton int bytes_written = 0; 29b9c1b51eSKate Stone switch (m_type) { 301080edbcSGreg Clayton case Opcode::eTypeInvalid: 311080edbcSGreg Clayton bytes_written = s->PutCString("<invalid>"); 321080edbcSGreg Clayton break; 331080edbcSGreg Clayton case Opcode::eType8: 341080edbcSGreg Clayton bytes_written = s->Printf("0x%2.2x", m_data.inst8); 351080edbcSGreg Clayton break; 361080edbcSGreg Clayton case Opcode::eType16: 371080edbcSGreg Clayton bytes_written = s->Printf("0x%4.4x", m_data.inst16); 381080edbcSGreg Clayton break; 395c97c2f7SSean Callanan case Opcode::eType16_2: 401080edbcSGreg Clayton case Opcode::eType32: 411080edbcSGreg Clayton bytes_written = s->Printf("0x%8.8x", m_data.inst32); 421080edbcSGreg Clayton break; 431080edbcSGreg Clayton 441080edbcSGreg Clayton case Opcode::eType64: 45d01b2953SDaniel Malea bytes_written = s->Printf("0x%16.16" PRIx64, m_data.inst64); 461080edbcSGreg Clayton break; 471080edbcSGreg Clayton 481080edbcSGreg Clayton case Opcode::eTypeBytes: 49b9c1b51eSKate Stone for (uint32_t i = 0; i < m_data.inst.length; ++i) { 501080edbcSGreg Clayton if (i > 0) 51357132ebSGreg Clayton bytes_written += s->PutChar(' '); 521080edbcSGreg Clayton bytes_written += s->Printf("%2.2x", m_data.inst.bytes[i]); 531080edbcSGreg Clayton } 541080edbcSGreg Clayton break; 551080edbcSGreg Clayton } 561080edbcSGreg Clayton 571080edbcSGreg Clayton // Add spaces to make sure bytes dispay comes out even in case opcodes 581080edbcSGreg Clayton // aren't all the same size 593985c8c6SSaleem Abdulrasool if (static_cast<uint32_t>(bytes_written) < min_byte_width) 601080edbcSGreg Clayton bytes_written = s->Printf("%*s", min_byte_width - bytes_written, ""); 611080edbcSGreg Clayton return bytes_written; 621080edbcSGreg Clayton } 631080edbcSGreg Clayton 64b9c1b51eSKate Stone lldb::ByteOrder Opcode::GetDataByteOrder() const { 65b9c1b51eSKate Stone if (m_byte_order != eByteOrderInvalid) { 6690359963SEd Maste return m_byte_order; 6790359963SEd Maste } 68b9c1b51eSKate Stone switch (m_type) { 69b9c1b51eSKate Stone case Opcode::eTypeInvalid: 70b9c1b51eSKate Stone break; 718f7180b1SGreg Clayton case Opcode::eType8: 728f7180b1SGreg Clayton case Opcode::eType16: 735c97c2f7SSean Callanan case Opcode::eType16_2: 748f7180b1SGreg Clayton case Opcode::eType32: 75b9c1b51eSKate Stone case Opcode::eType64: 76b9c1b51eSKate Stone return endian::InlHostByteOrder(); 778f7180b1SGreg Clayton case Opcode::eTypeBytes: 788f7180b1SGreg Clayton break; 798f7180b1SGreg Clayton } 808f7180b1SGreg Clayton return eByteOrderInvalid; 818f7180b1SGreg Clayton } 828f7180b1SGreg Clayton 83b9c1b51eSKate Stone uint32_t Opcode::GetData(DataExtractor &data) const { 84d1411e1aSGreg Clayton uint32_t byte_size = GetByteSize(); 8590359963SEd Maste uint8_t swap_buf[8]; 868918372dSEugene Zelenko const void *buf = nullptr; 87ba812f42SGreg Clayton 88b9c1b51eSKate Stone if (byte_size > 0) { 89b9c1b51eSKate Stone if (!GetEndianSwap()) { 90b9c1b51eSKate Stone if (m_type == Opcode::eType16_2) { 9190359963SEd Maste // 32 bit thumb instruction, we need to sizzle this a bit 9290359963SEd Maste swap_buf[0] = m_data.inst.bytes[2]; 9390359963SEd Maste swap_buf[1] = m_data.inst.bytes[3]; 9490359963SEd Maste swap_buf[2] = m_data.inst.bytes[0]; 9590359963SEd Maste swap_buf[3] = m_data.inst.bytes[1]; 9690359963SEd Maste buf = swap_buf; 97b9c1b51eSKate Stone } else { 9890359963SEd Maste buf = GetOpcodeDataBytes(); 9990359963SEd Maste } 100b9c1b51eSKate Stone } else { 101b9c1b51eSKate Stone switch (m_type) { 102d1411e1aSGreg Clayton case Opcode::eTypeInvalid: 103d1411e1aSGreg Clayton break; 10490359963SEd Maste case Opcode::eType8: 10590359963SEd Maste buf = GetOpcodeDataBytes(); 10690359963SEd Maste break; 10790359963SEd Maste case Opcode::eType16: 10890359963SEd Maste *(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16); 10990359963SEd Maste buf = swap_buf; 11090359963SEd Maste break; 11179101b5cSGreg Clayton case Opcode::eType16_2: 11290359963SEd Maste swap_buf[0] = m_data.inst.bytes[1]; 11390359963SEd Maste swap_buf[1] = m_data.inst.bytes[0]; 11490359963SEd Maste swap_buf[2] = m_data.inst.bytes[3]; 11590359963SEd Maste swap_buf[3] = m_data.inst.bytes[2]; 11690359963SEd Maste buf = swap_buf; 117cd4ae1abSSean Callanan break; 118cd4ae1abSSean Callanan case Opcode::eType32: 11990359963SEd Maste *(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32); 12090359963SEd Maste buf = swap_buf; 12179101b5cSGreg Clayton break; 12290359963SEd Maste case Opcode::eType64: 12390359963SEd Maste *(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64); 12490359963SEd Maste buf = swap_buf; 12590359963SEd Maste break; 12690359963SEd Maste case Opcode::eTypeBytes: 12790359963SEd Maste buf = GetOpcodeDataBytes(); 128d1411e1aSGreg Clayton break; 129d1411e1aSGreg Clayton } 130d1411e1aSGreg Clayton } 13190359963SEd Maste } 132b9c1b51eSKate Stone if (buf != nullptr) { 13390359963SEd Maste DataBufferSP buffer_sp; 13490359963SEd Maste 13590359963SEd Maste buffer_sp.reset(new DataBufferHeap(buf, byte_size)); 136d1411e1aSGreg Clayton data.SetByteOrder(GetDataByteOrder()); 137d1411e1aSGreg Clayton data.SetData(buffer_sp); 138d1411e1aSGreg Clayton return byte_size; 139d1411e1aSGreg Clayton } 140d1411e1aSGreg Clayton data.Clear(); 141d1411e1aSGreg Clayton return 0; 142d1411e1aSGreg Clayton } 143