summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/ArchSpec.h16
-rw-r--r--lldb/source/Core/ArchSpec.cpp36
-rw-r--r--lldb/source/Core/Disassembler.cpp5
-rw-r--r--lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp14
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp20
5 files changed, 65 insertions, 26 deletions
diff --git a/lldb/include/lldb/Core/ArchSpec.h b/lldb/include/lldb/Core/ArchSpec.h
index 70ac9548a7f..0b2ee900915 100644
--- a/lldb/include/lldb/Core/ArchSpec.h
+++ b/lldb/include/lldb/Core/ArchSpec.h
@@ -622,6 +622,22 @@ public:
bool &os_version_different,
bool &env_different);
+ //------------------------------------------------------------------
+ /// Detect whether this architecture uses thumb code exclusively
+ ///
+ /// Some embedded ARM chips (e.g. the ARM Cortex M0-7 line) can
+ /// only execute the Thumb instructions, never Arm. We should normally
+ /// pick up arm/thumbness from their the processor status bits (cpsr/xpsr)
+ /// or hints on each function - but when doing bare-boards low level
+ /// debugging (especially common with these embedded processors), we may
+ /// not have those things easily accessible.
+ ///
+ /// @return true if this is an arm ArchSpec which can only execute Thumb
+ /// instructions
+ //------------------------------------------------------------------
+ bool
+ IsAlwaysThumbInstructions () const;
+
uint32_t
GetFlags () const
{
diff --git a/lldb/source/Core/ArchSpec.cpp b/lldb/source/Core/ArchSpec.cpp
index 0852a49c3d3..ecbd884ec52 100644
--- a/lldb/source/Core/ArchSpec.cpp
+++ b/lldb/source/Core/ArchSpec.cpp
@@ -898,6 +898,17 @@ ArchSpec::MergeFrom(const ArchSpec &other)
if (other.TripleVendorWasSpecified())
GetTriple().setEnvironment(other.GetTriple().getEnvironment());
}
+ // If this and other are both arm ArchSpecs and this ArchSpec is a generic "some kind of arm"
+ // spec but the other ArchSpec is a specific arm core, adopt the specific arm core.
+ if (GetTriple().getArch() == llvm::Triple::arm
+ && other.GetTriple().getArch() == llvm::Triple::arm
+ && IsCompatibleMatch (other)
+ && GetCore() == ArchSpec::eCore_arm_generic
+ && other.GetCore() != ArchSpec::eCore_arm_generic)
+ {
+ m_core = other.GetCore();
+ CoreUpdated (true);
+ }
}
bool
@@ -1522,6 +1533,31 @@ ArchSpec::PiecewiseTripleCompare (const ArchSpec &other,
env_different = (me.getEnvironment() != them.getEnvironment());
}
+bool
+ArchSpec::IsAlwaysThumbInstructions () const
+{
+ std::string Error;
+ if (GetTriple().getArch() == llvm::Triple::arm || GetTriple().getArch() == llvm::Triple::thumb)
+ {
+ // v. https://en.wikipedia.org/wiki/ARM_Cortex-M
+ //
+ // Cortex-M0 through Cortex-M7 are ARM processor cores which can only
+ // execute thumb instructions. We map the cores to arch names like this:
+ //
+ // Cortex-M0, Cortex-M0+, Cortex-M1: armv6m
+ // Cortex-M3: armv7m
+ // Cortex-M4, Cortex-M7: armv7em
+
+ if (GetCore() == ArchSpec::Core::eCore_arm_armv7m
+ || GetCore() == ArchSpec::Core::eCore_arm_armv7em
+ || GetCore() == ArchSpec::Core::eCore_arm_armv6m)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
void
ArchSpec::DumpTriple(Stream &s) const
{
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index 39843a0f028..9ef716d3f3f 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -1236,10 +1236,7 @@ Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) :
// If this is an arm variant that can only include thumb (T16, T32)
// instructions, force the arch triple to be "thumbv.." instead of
// "armv..."
- if ((arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb)
- && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
- || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
- || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
+ if (arch.IsAlwaysThumbInstructions())
{
std::string thumb_arch_name (arch.GetTriple().getArchName().str());
// Replace "arm" with "thumb" so we get all thumb variants correct
diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index 5bc782c19db..ed858c1675b 100644
--- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -647,18 +647,8 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
const char *triple_str = triple.getTriple().c_str();
- // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
- //
- // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions,
- // so hardcode the primary disassembler to thumb mode. Same for Cortex-M4 (armv7em).
- //
- // Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32
- // instructions defined in ARMv7-A.
-
- if ((triple.getArch() == llvm::Triple::arm || triple.getArch() == llvm::Triple::thumb)
- && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
- || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
- || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
+ // ARM Cortex M0-M7 devices only execute thumb instructions
+ if (arch.IsAlwaysThumbInstructions ())
{
triple_str = thumb_arch.GetTriple().getTriple().c_str();
}
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index c9e942e6ba6..8b0863e2913 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -13004,7 +13004,7 @@ EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address
{
if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
{
- if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
+ if (m_arch.GetTriple().getArch() == llvm::Triple::thumb || m_arch.IsAlwaysThumbInstructions ())
m_opcode_mode = eModeThumb;
else
{
@@ -13017,7 +13017,7 @@ EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address
else
return false;
}
- if (m_opcode_mode == eModeThumb)
+ if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions ())
m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
else
m_opcode_cpsr = CPSR_MODE_USR;
@@ -13040,7 +13040,7 @@ EmulateInstructionARM::ReadInstruction ()
read_inst_context.type = eContextReadOpcode;
read_inst_context.SetNoArgs ();
- if (m_opcode_cpsr & MASK_CPSR_T)
+ if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions ())
{
m_opcode_mode = eModeThumb;
uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
@@ -13678,19 +13678,19 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option
}
test_opcode = value_sp->GetUInt64Value ();
- if (arch.GetTriple().getArch() == llvm::Triple::arm)
- {
- m_opcode_mode = eModeARM;
- m_opcode.SetOpcode32 (test_opcode, GetByteOrder());
- }
- else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
+
+ if (arch.GetTriple().getArch() == llvm::Triple::thumb || arch.IsAlwaysThumbInstructions ())
{
m_opcode_mode = eModeThumb;
if (test_opcode < 0x10000)
m_opcode.SetOpcode16 (test_opcode, GetByteOrder());
else
m_opcode.SetOpcode32 (test_opcode, GetByteOrder());
-
+ }
+ else if (arch.GetTriple().getArch() == llvm::Triple::arm)
+ {
+ m_opcode_mode = eModeARM;
+ m_opcode.SetOpcode32 (test_opcode, GetByteOrder());
}
else
{
OpenPOWER on IntegriCloud