1 //===-- ABISysV_msp430.cpp --------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "ABISysV_msp430.h" 11 12 #include "lldb/Core/Module.h" 13 #include "lldb/Core/PluginManager.h" 14 #include "lldb/Core/Value.h" 15 #include "lldb/Core/ValueObjectConstResult.h" 16 #include "lldb/Core/ValueObjectMemory.h" 17 #include "lldb/Core/ValueObjectRegister.h" 18 #include "lldb/Symbol/UnwindPlan.h" 19 #include "lldb/Target/Process.h" 20 #include "lldb/Target/RegisterContext.h" 21 #include "lldb/Target/StackFrame.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Target/Thread.h" 24 #include "lldb/Utility/ConstString.h" 25 #include "lldb/Utility/DataExtractor.h" 26 #include "lldb/Utility/Log.h" 27 #include "lldb/Utility/RegisterValue.h" 28 29 #include "llvm/IR/DerivedTypes.h" 30 #include "llvm/TargetParser/Triple.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 LLDB_PLUGIN_DEFINE_ADV(ABISysV_msp430, ABIMSP430) 36 37 enum dwarf_regnums { 38 dwarf_pc = 0, 39 dwarf_sp, 40 dwarf_r2, 41 dwarf_r3, 42 dwarf_fp, 43 dwarf_r5, 44 dwarf_r6, 45 dwarf_r7, 46 dwarf_r8, 47 dwarf_r9, 48 dwarf_r10, 49 dwarf_r11, 50 dwarf_r12, 51 dwarf_r13, 52 dwarf_r14, 53 dwarf_r15, 54 }; 55 56 static const RegisterInfo g_register_infos[] = { 57 {"r0", 58 "pc", 59 2, 60 0, 61 eEncodingUint, 62 eFormatHex, 63 {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, 64 LLDB_INVALID_REGNUM}, 65 nullptr, 66 nullptr, 67 nullptr, 68 }, 69 {"r1", 70 "sp", 71 2, 72 0, 73 eEncodingUint, 74 eFormatHex, 75 {dwarf_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, 76 LLDB_INVALID_REGNUM}, 77 nullptr, 78 nullptr, 79 nullptr, 80 }, 81 {"r2", 82 "", 83 2, 84 0, 85 eEncodingUint, 86 eFormatHex, 87 {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 88 LLDB_INVALID_REGNUM}, 89 nullptr, 90 nullptr, 91 nullptr, 92 }, 93 {"r3", 94 "", 95 2, 96 0, 97 eEncodingUint, 98 eFormatHex, 99 {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 100 LLDB_INVALID_REGNUM}, 101 nullptr, 102 nullptr, 103 nullptr, 104 }, 105 {"r4", 106 "fp", 107 2, 108 0, 109 eEncodingUint, 110 eFormatHex, 111 {dwarf_fp, dwarf_fp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, 112 LLDB_INVALID_REGNUM}, 113 nullptr, 114 nullptr, 115 nullptr, 116 }, 117 {"r5", 118 "", 119 2, 120 0, 121 eEncodingUint, 122 eFormatHex, 123 {dwarf_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 124 LLDB_INVALID_REGNUM}, 125 nullptr, 126 nullptr, 127 nullptr, 128 }, 129 {"r6", 130 "", 131 2, 132 0, 133 eEncodingUint, 134 eFormatHex, 135 {dwarf_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 136 LLDB_INVALID_REGNUM}, 137 nullptr, 138 nullptr, 139 nullptr, 140 }, 141 {"r7", 142 "", 143 2, 144 0, 145 eEncodingUint, 146 eFormatHex, 147 {dwarf_r7, dwarf_r7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 148 LLDB_INVALID_REGNUM}, 149 nullptr, 150 nullptr, 151 nullptr, 152 }, 153 {"r8", 154 "", 155 2, 156 0, 157 eEncodingUint, 158 eFormatHex, 159 {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 160 LLDB_INVALID_REGNUM}, 161 nullptr, 162 nullptr, 163 nullptr, 164 }, 165 {"r9", 166 "", 167 2, 168 0, 169 eEncodingUint, 170 eFormatHex, 171 {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 172 LLDB_INVALID_REGNUM}, 173 nullptr, 174 nullptr, 175 nullptr, 176 }, 177 {"r10", 178 "", 179 2, 180 0, 181 eEncodingUint, 182 eFormatHex, 183 {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 184 LLDB_INVALID_REGNUM}, 185 nullptr, 186 nullptr, 187 nullptr, 188 }, 189 {"r11", 190 "", 191 2, 192 0, 193 eEncodingUint, 194 eFormatHex, 195 {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 196 LLDB_INVALID_REGNUM}, 197 nullptr, 198 nullptr, 199 nullptr, 200 }, 201 {"r12", 202 "", 203 2, 204 0, 205 eEncodingUint, 206 eFormatHex, 207 {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 208 LLDB_INVALID_REGNUM}, 209 nullptr, 210 nullptr, 211 nullptr, 212 }, 213 {"r13", 214 "", 215 2, 216 0, 217 eEncodingUint, 218 eFormatHex, 219 {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 220 LLDB_INVALID_REGNUM}, 221 nullptr, 222 nullptr, 223 nullptr, 224 }, 225 {"r14", 226 "", 227 2, 228 0, 229 eEncodingUint, 230 eFormatHex, 231 {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 232 LLDB_INVALID_REGNUM}, 233 nullptr, 234 nullptr, 235 nullptr, 236 }, 237 {"r15", 238 "", 239 2, 240 0, 241 eEncodingUint, 242 eFormatHex, 243 {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 244 LLDB_INVALID_REGNUM}, 245 nullptr, 246 nullptr, 247 nullptr, 248 }}; 249 250 static const uint32_t k_num_register_infos = 251 sizeof(g_register_infos) / sizeof(RegisterInfo); 252 253 const lldb_private::RegisterInfo * 254 ABISysV_msp430::GetRegisterInfoArray(uint32_t &count) { 255 // Make the C-string names and alt_names for the register infos into const 256 // C-string values by having the ConstString unique the names in the global 257 // constant C-string pool. 258 count = k_num_register_infos; 259 return g_register_infos; 260 } 261 262 size_t ABISysV_msp430::GetRedZoneSize() const { return 0; } 263 264 //------------------------------------------------------------------ 265 // Static Functions 266 //------------------------------------------------------------------ 267 268 ABISP 269 ABISysV_msp430::CreateInstance(lldb::ProcessSP process_sp, 270 const ArchSpec &arch) { 271 if (arch.GetTriple().getArch() == llvm::Triple::msp430) { 272 return ABISP( 273 new ABISysV_msp430(std::move(process_sp), MakeMCRegisterInfo(arch))); 274 } 275 return ABISP(); 276 } 277 278 bool ABISysV_msp430::PrepareTrivialCall(Thread &thread, lldb::addr_t sp, 279 lldb::addr_t pc, lldb::addr_t ra, 280 llvm::ArrayRef<addr_t> args) const { 281 // we don't use the traditional trivial call specialized for jit 282 return false; 283 } 284 285 bool ABISysV_msp430::GetArgumentValues(Thread &thread, 286 ValueList &values) const { 287 return false; 288 } 289 290 Status ABISysV_msp430::SetReturnValueObject(lldb::StackFrameSP &frame_sp, 291 lldb::ValueObjectSP &new_value_sp) { 292 return Status(); 293 } 294 295 ValueObjectSP ABISysV_msp430::GetReturnValueObjectSimple( 296 Thread &thread, CompilerType &return_compiler_type) const { 297 ValueObjectSP return_valobj_sp; 298 return return_valobj_sp; 299 } 300 301 ValueObjectSP ABISysV_msp430::GetReturnValueObjectImpl( 302 Thread &thread, CompilerType &return_compiler_type) const { 303 ValueObjectSP return_valobj_sp; 304 return return_valobj_sp; 305 } 306 307 // called when we are on the first instruction of a new function 308 bool ABISysV_msp430::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { 309 unwind_plan.Clear(); 310 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 311 312 uint32_t sp_reg_num = dwarf_sp; 313 uint32_t pc_reg_num = dwarf_pc; 314 315 UnwindPlan::RowSP row(new UnwindPlan::Row); 316 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 2); 317 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -2, true); 318 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 319 320 unwind_plan.AppendRow(row); 321 unwind_plan.SetSourceName("msp430 at-func-entry default"); 322 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 323 return true; 324 } 325 326 bool ABISysV_msp430::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { 327 unwind_plan.Clear(); 328 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 329 330 uint32_t fp_reg_num = dwarf_fp; 331 uint32_t sp_reg_num = dwarf_sp; 332 uint32_t pc_reg_num = dwarf_pc; 333 334 UnwindPlan::RowSP row(new UnwindPlan::Row); 335 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 2); 336 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -2, true); 337 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 338 row->SetRegisterLocationToUnspecified(fp_reg_num, true); 339 340 unwind_plan.AppendRow(row); 341 unwind_plan.SetSourceName("msp430 default unwind plan"); 342 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 343 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 344 return true; 345 } 346 347 bool ABISysV_msp430::RegisterIsVolatile(const RegisterInfo *reg_info) { 348 return !RegisterIsCalleeSaved(reg_info); 349 } 350 351 bool ABISysV_msp430::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { 352 int reg = ((reg_info->byte_offset) / 2); 353 354 bool save = (reg >= 4) && (reg <= 10); 355 return save; 356 } 357 358 void ABISysV_msp430::Initialize(void) { 359 PluginManager::RegisterPlugin( 360 GetPluginNameStatic(), "System V ABI for msp430 targets", CreateInstance); 361 } 362 363 void ABISysV_msp430::Terminate(void) { 364 PluginManager::UnregisterPlugin(CreateInstance); 365 } 366