[Lldb-commits] [lldb] r125059 - in /lldb/trunk/source/Plugins/Instruction/ARM: EmulateInstructionARM.cpp EmulateInstructionARM.h

Johnny Chen johnny.chen at apple.com
Mon Feb 7 16:06:35 PST 2011


Author: johnny
Date: Mon Feb  7 18:06:35 2011
New Revision: 125059

URL: http://llvm.org/viewvc/llvm-project?rev=125059&view=rev
Log:
Add implementation for EmulateInstructionARM::EmulateB() and fixed two typos in g_thumb_opcodes
as pointed out By Caroline.  Refactored a little bit by adding two new helper methods to the
EmulateInstructionARM class:

o BranchWritePC()
o BXWritePC()

Modified:
    lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
    lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h

Modified: lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp?rev=125059&r1=125058&r2=125059&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp (original)
+++ lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp Mon Feb  7 18:06:35 2011
@@ -779,24 +779,24 @@
             uint32_t I2 = !(J2 ^ S);
             uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) + (imm10L << 2);
             imm32 = llvm::SignExtend32<25>(imm25);
-            target = (pc & 0xfffffffc) + 4 + imm32;
-            context.arg1 = eModeARM;   // target instruction set
-            context.arg2 = 4 + imm32;  // signed offset
+            target = ((pc + 4) & 0xfffffffc) + imm32;
+            context.arg1 = 4 + imm32;  // signed offset
+            context.arg2 = eModeARM;   // target instruction set
             break;
             }
         case eEncodingA2:
             lr = pc + 4; // return address
             imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
             target = pc + 8 + imm32;
-            context.arg1 = eModeThumb; // target instruction set
-            context.arg2 = 8 + imm32;  // signed offset
+            context.arg1 = 8 + imm32;  // signed offset
+            context.arg2 = eModeThumb; // target instruction set
             break;
         default:
             return false;
         }
         if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
             return false;
-        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
+        if (!BranchWritePC(context, target))
             return false;
     }
     return true;
@@ -858,19 +858,11 @@
         default:
             return false;
         }
-        bool toThumb;
-        if (BitIsSet(target, 0))
-            toThumb = true;
-        else if (BitIsClear(target, 1))
-            toThumb = false;
-        else
-            return false; // address<1:0> == ‘10’ => UNPREDICTABLE
         context.arg0 = eRegisterKindDWARF;
         context.arg1 = dwarf_r0 + Rm;
-        context.arg2 = toThumb ? eModeThumb : eModeARM;
         if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
             return false;
-        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
+        if (!BXWritePC(context, target))
             return false;
     }
     return true;
@@ -1394,7 +1386,72 @@
     if (!success)
         return false;
 
-    return false;
+    if (ConditionPassed())
+    {
+        EmulateInstruction::Context context = { EmulateInstruction::eContextRelativeBranchImmediate, 0, 0, 0};
+        const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
+        addr_t target; // target address
+        if (!success)
+            return false;
+        int32_t imm32; // PC-relative offset
+        switch (encoding) {
+        case eEncodingT1:
+            // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
+            imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
+            target = pc + 4 + imm32;
+            context.arg1 = 4 + imm32;  // signed offset
+            context.arg2 = eModeThumb; // target instruction set
+            break;
+        case eEncodingT2:
+            imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
+            target = pc + 4 + imm32;
+            context.arg1 = 4 + imm32;  // signed offset
+            context.arg2 = eModeThumb; // target instruction set
+            break;
+        case eEncodingT3:
+            // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
+            {
+            uint32_t S = Bits32(opcode, 26, 26);
+            uint32_t imm6 = Bits32(opcode, 21, 16);
+            uint32_t J1 = Bits32(opcode, 13, 13);
+            uint32_t J2 = Bits32(opcode, 11, 11);
+            uint32_t imm11 = Bits32(opcode, 10, 0);
+            uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) + (imm11 << 1);
+            imm32 = llvm::SignExtend32<21>(imm21);
+            target = pc + 4 + imm32;
+            context.arg1 = eModeThumb; // target instruction set
+            context.arg2 = 4 + imm32;  // signed offset
+            break;
+            }
+        case eEncodingT4:
+            {
+            uint32_t S = Bits32(opcode, 26, 26);
+            uint32_t imm10 = Bits32(opcode, 25, 16);
+            uint32_t J1 = Bits32(opcode, 13, 13);
+            uint32_t J2 = Bits32(opcode, 11, 11);
+            uint32_t imm11 = Bits32(opcode, 10, 0);
+            uint32_t I1 = !(J1 ^ S);
+            uint32_t I2 = !(J2 ^ S);
+            uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) + (imm11 << 1);
+            imm32 = llvm::SignExtend32<25>(imm25);
+            target = pc + 4 + imm32;
+            context.arg1 = eModeThumb; // target instruction set
+            context.arg2 = 4 + imm32;  // signed offset
+            break;
+            }
+        case eEncodingA1:
+            imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
+            target = pc + 8 + imm32;
+            context.arg1 = eModeARM; // target instruction set
+            context.arg2 = 8 + imm32;  // signed offset
+            break;
+        default:
+            return false;
+        }
+        if (!BranchWritePC(context, target))
+            return false;
+    }
+    return true;
 }
 
 EmulateInstructionARM::ARMOpcode*
@@ -1530,8 +1587,8 @@
         // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
         { 0xfffff000, 0x0000d000, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
         { 0xffff8000, 0x0000e000, ARMvAll,       eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
-        { 0xf800d000, 0x00008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
-        { 0xf800d000, 0x00009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"}
+        { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
+        { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"}
 
     };
 
@@ -1628,40 +1685,6 @@
     return success;
 }
 
-uint32_t
-EmulateInstructionARM::CurrentCond ()
-{
-    switch (m_inst_mode)
-    {
-    default:
-    case eModeInvalid:
-        break;
-
-    case eModeARM:
-        return UnsignedBits(m_inst.opcode.inst32, 31, 28);
-    
-    case eModeThumb:
-        // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
-        // 'cond' field of the encoding.
-        if (m_inst.opcode_type == eOpcode16 &&
-            Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
-            Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
-        {
-            return Bits32(m_inst.opcode.inst16, 11, 7);
-        }
-        else if (m_inst.opcode_type == eOpcode32 &&
-                 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
-                 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
-                 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
-                 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
-        {
-            return Bits32(m_inst.opcode.inst32, 25, 22);
-        }
-        
-        return m_it_session.GetCond();
-    }
-    return UINT32_MAX;  // Return invalid value
-}
 bool
 EmulateInstructionARM::ConditionPassed ()
 {
@@ -1705,6 +1728,88 @@
     return result;
 }
 
+uint32_t
+EmulateInstructionARM::CurrentCond ()
+{
+    switch (m_inst_mode)
+    {
+    default:
+    case eModeInvalid:
+        break;
+
+    case eModeARM:
+        return UnsignedBits(m_inst.opcode.inst32, 31, 28);
+    
+    case eModeThumb:
+        // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
+        // 'cond' field of the encoding.
+        if (m_inst.opcode_type == eOpcode16 &&
+            Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
+            Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
+        {
+            return Bits32(m_inst.opcode.inst16, 11, 7);
+        }
+        else if (m_inst.opcode_type == eOpcode32 &&
+                 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
+                 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
+                 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
+                 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
+        {
+            return Bits32(m_inst.opcode.inst32, 25, 22);
+        }
+        
+        return m_it_session.GetCond();
+    }
+    return UINT32_MAX;  // Return invalid value
+}
+
+// API client must pass in a context whose arg2 field contains the target instruction set.
+bool
+EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
+{
+    addr_t target;
+
+    // Chech the target instruction set.
+    switch (context.arg2)
+    {
+    default:
+        assert(0 && "BranchWritePC expects context.arg1 with either eModeARM or eModeThumb");
+        return false;
+    case eModeARM:
+        target = addr & 0xfffffffc;
+        break;
+    case eModeThumb:
+        target = addr & 0xfffffffe;
+        break;
+    }
+    if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
+        return false;    
+    return false;
+}
+
+// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
+bool
+EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
+{
+    addr_t target;
+
+    if (BitIsSet(addr, 0))
+    {
+        target = addr & 0xfffffffe;
+        context.arg2 = eModeThumb;
+    }
+    else if (BitIsClear(addr, 1))
+    {
+        target = addr & 0xfffffffc;
+        context.arg2 = eModeARM;
+    }
+    else
+        return false; // address<1:0> == '10' => UNPREDICTABLE
+
+    if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
+        return false;    
+    return false;
+}
 
 bool
 EmulateInstructionARM::EvaluateInstruction ()

Modified: lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h?rev=125059&r1=125058&r2=125059&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h (original)
+++ lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h Mon Feb  7 18:06:35 2011
@@ -145,6 +145,12 @@
     uint32_t
     CurrentCond ();
 
+    bool
+    BranchWritePC(const Context &context, uint32_t addr);
+
+    bool
+    BXWritePC(Context &context, uint32_t addr);
+
 protected:
 
     // Typedef for the callback function used during the emulation.





More information about the lldb-commits mailing list