summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core/Opcode.cpp
diff options
context:
space:
mode:
authorEd Maste <emaste@freebsd.org>2013-12-09 19:45:33 +0000
committerEd Maste <emaste@freebsd.org>2013-12-09 19:45:33 +0000
commit90359963ab28ed454d933e33511aa05808444f33 (patch)
tree5a9b481289e60ebbd6ccf37088b4e52b86131df2 /lldb/source/Core/Opcode.cpp
parente2a1418e68d3ed091d6c902e82c8504a8dea1503 (diff)
downloadbcm5719-llvm-90359963ab28ed454d933e33511aa05808444f33.tar.gz
bcm5719-llvm-90359963ab28ed454d933e33511aa05808444f33.zip
Handle endianness in the Opcode class
Previously, an opcode set via SetOpcode32 (for example) was later extracted via GetData() as a byte sequence in host order rather than target order. Review: http://llvm-reviews.chandlerc.com/D1838 llvm-svn: 196808
Diffstat (limited to 'lldb/source/Core/Opcode.cpp')
-rw-r--r--lldb/source/Core/Opcode.cpp83
1 files changed, 57 insertions, 26 deletions
diff --git a/lldb/source/Core/Opcode.cpp b/lldb/source/Core/Opcode.cpp
index 978a110150f..2bf7f5eae9b 100644
--- a/lldb/source/Core/Opcode.cpp
+++ b/lldb/source/Core/Opcode.cpp
@@ -71,6 +71,10 @@ Opcode::Dump (Stream *s, uint32_t min_byte_width)
lldb::ByteOrder
Opcode::GetDataByteOrder () const
{
+ if (m_byte_order != eByteOrderInvalid)
+ {
+ return m_byte_order;
+ }
switch (m_type)
{
case Opcode::eTypeInvalid: break;
@@ -89,39 +93,66 @@ uint32_t
Opcode::GetData (DataExtractor &data) const
{
uint32_t byte_size = GetByteSize ();
+ uint8_t swap_buf[8];
+ const void *buf = NULL;
- DataBufferSP buffer_sp;
if (byte_size > 0)
{
- switch (m_type)
+ if (!GetEndianSwap())
+ {
+ if (m_type == Opcode::eType16_2)
+ {
+ // 32 bit thumb instruction, we need to sizzle this a bit
+ swap_buf[0] = m_data.inst.bytes[2];
+ swap_buf[1] = m_data.inst.bytes[3];
+ swap_buf[2] = m_data.inst.bytes[0];
+ swap_buf[3] = m_data.inst.bytes[1];
+ buf = swap_buf;
+ }
+ else
+ {
+ buf = GetOpcodeDataBytes();
+ }
+ }
+ else
{
- 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;
+ switch (m_type)
+ {
+ case Opcode::eTypeInvalid:
+ break;
+ case Opcode::eType8:
+ buf = GetOpcodeDataBytes();
+ break;
+ case Opcode::eType16:
+ *(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16);
+ buf = swap_buf;
+ break;
+ case Opcode::eType16_2:
+ swap_buf[0] = m_data.inst.bytes[1];
+ swap_buf[1] = m_data.inst.bytes[0];
+ swap_buf[2] = m_data.inst.bytes[3];
+ swap_buf[3] = m_data.inst.bytes[2];
+ buf = swap_buf;
+ break;
+ case Opcode::eType32:
+ *(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32);
+ buf = swap_buf;
+ break;
+ case Opcode::eType64:
+ *(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64);
+ buf = swap_buf;
+ break;
+ case Opcode::eTypeBytes:
+ buf = GetOpcodeDataBytes();
+ break;
+ }
}
}
-
- if (buffer_sp)
+ if (buf)
{
+ DataBufferSP buffer_sp;
+
+ buffer_sp.reset (new DataBufferHeap (buf, byte_size));
data.SetByteOrder(GetDataByteOrder());
data.SetData (buffer_sp);
return byte_size;
OpenPOWER on IntegriCloud