Add the infrastructure to test instruction emulations automatically.
The idea is that the instruction to be emulated is actually executed
on the hardware to be emulated, with the before and after state of the
hardware being captured and 'freeze-dried' into .dat files.  The
emulation testing code then loads the before & after state from the
.dat file, emulates the instruction using the before state, and
compares the resulting state to the 'after' state.  If they match, the
emulation is accurate, otherwise there is a problem.

The final format of the .dat files needs a bit more work; the plan is
to generalize them a bit and to convert the plain values to key-value pairs. 
But I wanted to get this first pass committed.

This commit adds arm instruction emulation testing to the testsuite, along with
many initial .dat files.

It also fixes a bug in the llvm disassembler, where 32-bit thumb opcodes
were getting their upper & lower 16-bits reversed.

There is a new Instruction sub-class, that is intended to be loaded
from a .dat file rather than read from an executable.  There is also a
new EmulationStateARM class, for handling the before & after states.
EmulationStates for other architetures can be added later when we
emulate their instructions.




git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@129832 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp
index c422113..2db2d55 100644
--- a/source/Core/Disassembler.cpp
+++ b/source/Core/Disassembler.cpp
@@ -503,6 +503,60 @@
 }
 
 bool
+Instruction::TestEmulation (Stream *out_stream, const char *file_name)
+{
+    if (!out_stream)
+        return false;
+
+    if (!file_name)
+    {
+        out_stream->Printf ("Instruction::TestEmulation:  Missing file_name.\n");
+        return false;
+    }
+        
+    FILE *test_file = fopen (file_name, "r");
+    if (!test_file)
+    {
+        out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.\n");
+        return false;
+    }
+
+    ArchSpec arch;
+    char buffer[256];
+    if (!fgets (buffer,255, test_file)) // Read/skip first line of file, which should be a comment line (description).
+    {
+        out_stream->Printf ("Instruction::TestEmulation: Read comment line failed.\n");
+        fclose (test_file);
+        return false;
+    }
+    SetDescription (buffer);
+            
+    if (fscanf (test_file, "%s", buffer) != 1) // Read the arch or arch-triple from the file
+    {
+        out_stream->Printf ("Instruction::TestEmulation: Read arch failed.\n");
+        fclose (test_file);
+        return false;
+    }
+    
+    const char *cptr = buffer;
+    arch.SetTriple (llvm::Triple (cptr));
+
+    bool success = false;
+    std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
+    if (insn_emulator_ap.get())
+        success = insn_emulator_ap->TestEmulation (out_stream, test_file, arch);
+
+    fclose (test_file);
+    
+    if (success)
+        out_stream->Printf ("Emulation test succeeded.\n");
+    else
+        out_stream->Printf ("Emulation test failed.\n");
+        
+    return success;
+}
+
+bool
 Instruction::Emulate (const ArchSpec &arch,
                       bool auto_advance_pc,
                       void *baton,
@@ -692,3 +746,97 @@
 {
     return m_instruction_list;
 }
+
+//----------------------------------------------------------------------
+// Class PseudoInstruction
+//----------------------------------------------------------------------
+PseudoInstruction::PseudoInstruction () :
+    Instruction (Address(), eAddressClassUnknown),
+    m_description ()
+{
+}
+
+PseudoInstruction::~PseudoInstruction ()
+{
+}
+     
+void
+PseudoInstruction::Dump (lldb_private::Stream *s,
+                        uint32_t max_opcode_byte_size,
+                        bool show_address,
+                        bool show_bytes,
+                        const lldb_private::ExecutionContext* exe_ctx,
+                        bool raw)
+{
+    if (!s)
+        return;
+        
+    if (show_bytes)
+        m_opcode.Dump (s, max_opcode_byte_size);
+    
+    if (m_description.size() > 0)
+        s->Printf ("%s", m_description.c_str());
+    else
+        s->Printf ("<unknown>");
+        
+}
+    
+bool
+PseudoInstruction::DoesBranch () const
+{
+    // This is NOT a valid question for a pseudo instruction.
+    return false;
+}
+    
+size_t
+PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler,
+                           const lldb_private::DataExtractor &data,
+                           uint32_t data_offset)
+{
+    return m_opcode.GetByteSize();
+}
+
+
+void
+PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data)
+{
+    if (!opcode_data)
+        return;
+
+    switch (opcode_size)
+    {
+        case 8:
+        {
+            uint8_t value8 = *((uint8_t *) opcode_data);
+            m_opcode.SetOpcode8 (value8);
+            break;
+         }   
+        case 16:
+        {
+            uint16_t value16 = *((uint16_t *) opcode_data);
+            m_opcode.SetOpcode16 (value16);
+            break;
+         }   
+        case 32:
+        {
+            uint32_t value32 = *((uint32_t *) opcode_data);
+            m_opcode.SetOpcode32 (value32);
+            break;
+         }   
+        case 64:
+        {
+            uint64_t value64 = *((uint64_t *) opcode_data);
+            m_opcode.SetOpcode64 (value64);
+            break;
+         }   
+        default:
+            break;
+    }
+}
+
+void
+PseudoInstruction::SetDescription (const char *description)
+{
+    if (description && strlen (description) > 0)
+        m_description = description;
+}