| //===-- ABISysV_msp430.cpp --------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "ABISysV_msp430.h" |
| |
| #include "lldb/Core/Module.h" |
| #include "lldb/Core/PluginManager.h" |
| #include "lldb/Core/Value.h" |
| #include "lldb/Symbol/UnwindPlan.h" |
| #include "lldb/Target/Process.h" |
| #include "lldb/Target/RegisterContext.h" |
| #include "lldb/Target/StackFrame.h" |
| #include "lldb/Target/Target.h" |
| #include "lldb/Target/Thread.h" |
| #include "lldb/Utility/ConstString.h" |
| #include "lldb/Utility/DataExtractor.h" |
| #include "lldb/Utility/Log.h" |
| #include "lldb/Utility/RegisterValue.h" |
| #include "lldb/ValueObject/ValueObjectConstResult.h" |
| #include "lldb/ValueObject/ValueObjectMemory.h" |
| #include "lldb/ValueObject/ValueObjectRegister.h" |
| |
| #include "llvm/IR/DerivedTypes.h" |
| #include "llvm/TargetParser/Triple.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| LLDB_PLUGIN_DEFINE_ADV(ABISysV_msp430, ABIMSP430) |
| |
| enum dwarf_regnums { |
| dwarf_pc = 0, |
| dwarf_sp, |
| dwarf_r2, |
| dwarf_r3, |
| dwarf_fp, |
| dwarf_r5, |
| dwarf_r6, |
| dwarf_r7, |
| dwarf_r8, |
| dwarf_r9, |
| dwarf_r10, |
| dwarf_r11, |
| dwarf_r12, |
| dwarf_r13, |
| dwarf_r14, |
| dwarf_r15, |
| }; |
| |
| static const RegisterInfo g_register_infos[] = { |
| {"r0", |
| "pc", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r1", |
| "sp", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r2", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r3", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r4", |
| "fp", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_fp, dwarf_fp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r5", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r6", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r7", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r7, dwarf_r7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r8", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r9", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r10", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r11", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r12", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r13", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r14", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }, |
| {"r15", |
| "", |
| 2, |
| 0, |
| eEncodingUint, |
| eFormatHex, |
| {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, |
| LLDB_INVALID_REGNUM}, |
| nullptr, |
| nullptr, |
| nullptr, |
| }}; |
| |
| static const uint32_t k_num_register_infos = |
| sizeof(g_register_infos) / sizeof(RegisterInfo); |
| |
| const lldb_private::RegisterInfo * |
| ABISysV_msp430::GetRegisterInfoArray(uint32_t &count) { |
| // Make the C-string names and alt_names for the register infos into const |
| // C-string values by having the ConstString unique the names in the global |
| // constant C-string pool. |
| count = k_num_register_infos; |
| return g_register_infos; |
| } |
| |
| size_t ABISysV_msp430::GetRedZoneSize() const { return 0; } |
| |
| //------------------------------------------------------------------ |
| // Static Functions |
| //------------------------------------------------------------------ |
| |
| ABISP |
| ABISysV_msp430::CreateInstance(lldb::ProcessSP process_sp, |
| const ArchSpec &arch) { |
| if (arch.GetTriple().getArch() == llvm::Triple::msp430) { |
| return ABISP( |
| new ABISysV_msp430(std::move(process_sp), MakeMCRegisterInfo(arch))); |
| } |
| return ABISP(); |
| } |
| |
| bool ABISysV_msp430::PrepareTrivialCall(Thread &thread, lldb::addr_t sp, |
| lldb::addr_t pc, lldb::addr_t ra, |
| llvm::ArrayRef<addr_t> args) const { |
| // we don't use the traditional trivial call specialized for jit |
| return false; |
| } |
| |
| bool ABISysV_msp430::GetArgumentValues(Thread &thread, |
| ValueList &values) const { |
| return false; |
| } |
| |
| Status ABISysV_msp430::SetReturnValueObject(lldb::StackFrameSP &frame_sp, |
| lldb::ValueObjectSP &new_value_sp) { |
| return Status(); |
| } |
| |
| ValueObjectSP ABISysV_msp430::GetReturnValueObjectSimple( |
| Thread &thread, CompilerType &return_compiler_type) const { |
| ValueObjectSP return_valobj_sp; |
| return return_valobj_sp; |
| } |
| |
| ValueObjectSP ABISysV_msp430::GetReturnValueObjectImpl( |
| Thread &thread, CompilerType &return_compiler_type) const { |
| ValueObjectSP return_valobj_sp; |
| return return_valobj_sp; |
| } |
| |
| // called when we are on the first instruction of a new function |
| UnwindPlanSP ABISysV_msp430::CreateFunctionEntryUnwindPlan() { |
| uint32_t sp_reg_num = dwarf_sp; |
| uint32_t pc_reg_num = dwarf_pc; |
| |
| UnwindPlan::Row row; |
| row.GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 2); |
| row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -2, true); |
| row.SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); |
| |
| auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF); |
| plan_sp->AppendRow(std::move(row)); |
| plan_sp->SetSourceName("msp430 at-func-entry default"); |
| plan_sp->SetSourcedFromCompiler(eLazyBoolNo); |
| return plan_sp; |
| } |
| |
| UnwindPlanSP ABISysV_msp430::CreateDefaultUnwindPlan() { |
| uint32_t fp_reg_num = dwarf_fp; |
| uint32_t sp_reg_num = dwarf_sp; |
| uint32_t pc_reg_num = dwarf_pc; |
| |
| UnwindPlan::Row row; |
| row.GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 2); |
| row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -2, true); |
| row.SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); |
| row.SetRegisterLocationToUnspecified(fp_reg_num, true); |
| |
| auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF); |
| plan_sp->AppendRow(std::move(row)); |
| plan_sp->SetSourceName("msp430 default unwind plan"); |
| plan_sp->SetSourcedFromCompiler(eLazyBoolNo); |
| plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); |
| return plan_sp; |
| } |
| |
| bool ABISysV_msp430::RegisterIsVolatile(const RegisterInfo *reg_info) { |
| return !RegisterIsCalleeSaved(reg_info); |
| } |
| |
| bool ABISysV_msp430::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { |
| int reg = ((reg_info->byte_offset) / 2); |
| |
| bool save = (reg >= 4) && (reg <= 10); |
| return save; |
| } |
| |
| void ABISysV_msp430::Initialize(void) { |
| PluginManager::RegisterPlugin( |
| GetPluginNameStatic(), "System V ABI for msp430 targets", CreateInstance); |
| } |
| |
| void ABISysV_msp430::Terminate(void) { |
| PluginManager::UnregisterPlugin(CreateInstance); |
| } |