Add EmulateInstructionARM::EmulateIT() to the g_thumb_opcodes table,
to represent the the 'If Then' instruction which makes up to four following
instructions (the IT block)conditional.

Hook up ITSession utility class as a member variable of EmulateInstructionARM.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@124915 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index af81223..faa1d39 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -76,10 +76,19 @@
     return ITCounter != 0;
 }
 
+// Return true if we're the last instruction inside an IT Block.
+bool ITSession::LastInITBlock()
+{
+    return ITCounter == 1;
+}
+
 // Get condition bits for the current thumb instruction.
 uint32_t ITSession::GetCond()
 {
-    return Bits32(ITState, 7, 4);
+    if (InITBlock())
+        return Bits32(ITState, 7, 4);
+    else
+        return COND_AL;
 }
 
 // ARM constants used during decoding
@@ -1348,6 +1357,25 @@
     return true;
 }
 
+// If Then makes up to four following instructions (the IT block) conditional.
+bool
+EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    EncodingSpecificOperations();
+    ITSTATE.IT<7:0> = firstcond:mask;
+#endif
+
+    bool success = false;
+    const uint32_t opcode = OpcodeAsUnsigned (&success);
+    if (!success)
+        return false;
+
+    m_it_session.InitIT(Bits32(opcode, 7, 0));
+    return true;
+}
+
 EmulateInstructionARM::ARMOpcode*
 EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
 {
@@ -1463,7 +1491,12 @@
         //----------------------------------------------------------------------
         // Supervisor Call (previously Software Interrupt)
         //----------------------------------------------------------------------
-        { 0xffffff00, 0x0000df00, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"}
+        { 0xffffff00, 0x0000df00, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
+
+        //----------------------------------------------------------------------
+        // If Then makes up to four following instructions conditional.
+        //----------------------------------------------------------------------
+        { 0xffffff00, 0x0000bf00, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}
 
     };
 
@@ -1573,7 +1606,7 @@
         return UnsignedBits(m_inst.opcode.inst32, 31, 28);
     
     case eModeThumb:
-        return 0x0000000Eu; // Return always for now, we need to handl IT instructions later
+        return m_it_session.GetCond();
     }
     return UINT32_MAX;  // Return invalid value
 }
@@ -1624,5 +1657,9 @@
 bool
 EmulateInstructionARM::EvaluateInstruction ()
 {
+    // Advance the ITSTATE bits to their values for the next instruction.
+    if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
+        m_it_session.ITAdvance();
+
     return false;
 }
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index dc0cf72..b6ba71e 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -31,6 +31,9 @@
     // InITBlock - Returns true if we're inside an IT Block.
     bool InITBlock();
 
+    // LastInITBlock - Returns true if we're the last instruction inside an IT Block.
+    bool LastInITBlock();
+
     // GetCond - Gets condition bits for the current thumb instruction.
     uint32_t GetCond();
 
@@ -121,7 +124,8 @@
                             write_reg_callback),
         m_arm_isa (0),
         m_inst_mode (eModeInvalid),
-        m_inst_cpsr (0)
+        m_inst_cpsr (0),
+        m_it_session ()
     {
     }
     
@@ -220,9 +224,13 @@
     bool
     EmulateSVC (ARMEncoding encoding);
 
+    bool
+    EmulateIT (ARMEncoding encoding);
+
     uint32_t m_arm_isa;
     Mode m_inst_mode;
     uint32_t m_inst_cpsr;
+    ITSession m_it_session;
 };
 
 }   // namespace lldb_private