diff options
Diffstat (limited to 'source/Core/Opcode.cpp')
-rw-r--r-- | source/Core/Opcode.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/source/Core/Opcode.cpp b/source/Core/Opcode.cpp new file mode 100644 index 0000000..d987865 --- /dev/null +++ b/source/Core/Opcode.cpp @@ -0,0 +1,134 @@ +//===-- Opcode.cpp ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Opcode.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/Triple.h" +// Project includes +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Stream.h" +#include "lldb/Host/Endian.h" + + +using namespace lldb; +using namespace lldb_private; + + +int +Opcode::Dump (Stream *s, uint32_t min_byte_width) +{ + int bytes_written = 0; + switch (m_type) + { + case Opcode::eTypeInvalid: + bytes_written = s->PutCString ("<invalid>"); + break; + case Opcode::eType8: + bytes_written = s->Printf ("0x%2.2x", m_data.inst8); + break; + case Opcode::eType16: + bytes_written = s->Printf ("0x%4.4x", m_data.inst16); + break; + case Opcode::eType16_2: + case Opcode::eType32: + bytes_written = s->Printf ("0x%8.8x", m_data.inst32); + break; + + case Opcode::eType64: + bytes_written = s->Printf ("0x%16.16" PRIx64, m_data.inst64); + break; + + case Opcode::eTypeBytes: + { + for (uint32_t i=0; i<m_data.inst.length; ++i) + { + if (i > 0) + bytes_written += s->PutChar (' '); + bytes_written += s->Printf ("%2.2x", m_data.inst.bytes[i]); + } + } + break; + } + + // Add spaces to make sure bytes dispay comes out even in case opcodes + // aren't all the same size + if (bytes_written < min_byte_width) + bytes_written = s->Printf ("%*s", min_byte_width - bytes_written, ""); + return bytes_written; +} + +lldb::ByteOrder +Opcode::GetDataByteOrder () const +{ + switch (m_type) + { + case Opcode::eTypeInvalid: break; + case Opcode::eType8: + case Opcode::eType16: + case Opcode::eType16_2: + case Opcode::eType32: + case Opcode::eType64: return lldb::endian::InlHostByteOrder(); + case Opcode::eTypeBytes: + break; + } + return eByteOrderInvalid; +} + +uint32_t +Opcode::GetData (DataExtractor &data) const +{ + uint32_t byte_size = GetByteSize (); + + DataBufferSP buffer_sp; + if (byte_size > 0) + { + switch (m_type) + { + case Opcode::eTypeInvalid: + break; + + case Opcode::eType8: buffer_sp.reset (new DataBufferHeap (&m_data.inst8, byte_size)); break; + case Opcode::eType16: buffer_sp.reset (new DataBufferHeap (&m_data.inst16, byte_size)); break; + case Opcode::eType16_2: + { + // 32 bit thumb instruction, we need to sizzle this a bit + uint8_t buf[4]; + buf[0] = m_data.inst.bytes[2]; + buf[1] = m_data.inst.bytes[3]; + buf[2] = m_data.inst.bytes[0]; + buf[3] = m_data.inst.bytes[1]; + buffer_sp.reset (new DataBufferHeap (buf, byte_size)); + } + break; + case Opcode::eType32: + buffer_sp.reset (new DataBufferHeap (&m_data.inst32, byte_size)); + break; + case Opcode::eType64: buffer_sp.reset (new DataBufferHeap (&m_data.inst64, byte_size)); break; + case Opcode::eTypeBytes:buffer_sp.reset (new DataBufferHeap (GetOpcodeBytes(), byte_size)); break; + break; + } + } + + if (buffer_sp) + { + data.SetByteOrder(GetDataByteOrder()); + data.SetData (buffer_sp); + return byte_size; + } + data.Clear(); + return 0; +} + + + |