Add Hexagon packet support to ThreadPlanStepRange
authorTed Woodward <ted.woodward@codeaurora.org>
Mon, 11 May 2015 21:12:33 +0000 (21:12 +0000)
committerTed Woodward <ted.woodward@codeaurora.org>
Mon, 11 May 2015 21:12:33 +0000 (21:12 +0000)
Summary:
Hexagon is a VLIW processor. It can execute multiple instructions at once, called a packet. Breakpoints need to be alone in a packet. This patch will make sure that temporary breakpoints used for stepping are set at the start of a packet, which will put the breakpoint in a packet by itself.

Patch by Deepak Panickal of CodePlay and Ted Woodward of Qualcomm.

Reviewers: deepak2427, clayborg

Reviewed By: clayborg

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D9437

llvm-svn: 237047

lldb/include/lldb/Core/Disassembler.h
lldb/source/Core/Disassembler.cpp
lldb/source/Target/ThreadPlanStepRange.cpp

index 46ac605..e08e2de 100644 (file)
@@ -225,7 +225,7 @@ public:
     GetInstructionAtIndex (size_t idx) const;
     
     uint32_t
-    GetIndexOfNextBranchInstruction(uint32_t start) const;
+    GetIndexOfNextBranchInstruction(uint32_t start, Target &target) const;
     
     uint32_t
     GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target);
index 46d453d..1a698c3 100644 (file)
@@ -1061,12 +1061,13 @@ InstructionList::Append (lldb::InstructionSP &inst_sp)
 }
 
 uint32_t
-InstructionList::GetIndexOfNextBranchInstruction(uint32_t start) const
+InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, Target &target) const
 {
     size_t num_instructions = m_instructions.size();
     
     uint32_t next_branch = UINT32_MAX;
-    for (size_t i = start; i < num_instructions; i++)
+    size_t i;
+    for (i = start; i < num_instructions; i++)
     {
         if (m_instructions[i]->DoesBranch())
         {
@@ -1074,6 +1075,52 @@ InstructionList::GetIndexOfNextBranchInstruction(uint32_t start) const
             break;
         }
     }
+
+    // Hexagon needs the first instruction of the packet with the branch.
+    // Go backwards until we find an instruction marked end-of-packet, or
+    // until we hit start.
+    if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon)
+    {
+        // If we didn't find a branch, find the last packet start.
+        if (next_branch == UINT32_MAX)
+        {
+            i = num_instructions - 1;
+        }
+
+        while (i > start)
+        {
+            --i;
+
+            Error error;
+            uint32_t inst_bytes;
+            bool prefer_file_cache = false; // Read from process if process is running
+            lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+            target.ReadMemory(m_instructions[i]->GetAddress(),
+                              prefer_file_cache,
+                              &inst_bytes,
+                              sizeof(inst_bytes),
+                              error,
+                              &load_addr);
+            // If we have an error reading memory, return start
+            if (!error.Success())
+                return start;
+            // check if this is the last instruction in a packet
+            // bits 15:14 will be 11b or 00b for a duplex
+            if (((inst_bytes & 0xC000) == 0xC000) ||
+                ((inst_bytes & 0xC000) == 0x0000))
+            {
+                // instruction after this should be the start of next packet
+                next_branch = i + 1;
+                break;
+            }
+        }
+
+        if (next_branch == UINT32_MAX)
+        {
+            // We couldn't find the previous packet, so return start
+            next_branch = start;
+        }
+    }
     return next_branch;
 }
 
index 55f2c2b..324f5a7 100644 (file)
@@ -380,8 +380,9 @@ ThreadPlanStepRange::SetNextBranchBreakpoint ()
         return false;
     else
     {
+        Target &target = GetThread().GetProcess()->GetTarget();
         uint32_t branch_index;
-        branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index);
+        branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index, target);
         
         Address run_to_address;