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 *
GetRegisterInfoArray(uint32_t & count)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
GetRedZoneSize() const262 size_t ABISysV_msp430::GetRedZoneSize() const { return 0; }
263
264 //------------------------------------------------------------------
265 // Static Functions
266 //------------------------------------------------------------------
267
268 ABISP
CreateInstance(lldb::ProcessSP process_sp,const ArchSpec & arch)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
PrepareTrivialCall(Thread & thread,lldb::addr_t sp,lldb::addr_t pc,lldb::addr_t ra,llvm::ArrayRef<addr_t> args) const278 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
GetArgumentValues(Thread & thread,ValueList & values) const285 bool ABISysV_msp430::GetArgumentValues(Thread &thread,
286 ValueList &values) const {
287 return false;
288 }
289
SetReturnValueObject(lldb::StackFrameSP & frame_sp,lldb::ValueObjectSP & new_value_sp)290 Status ABISysV_msp430::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
291 lldb::ValueObjectSP &new_value_sp) {
292 return Status();
293 }
294
GetReturnValueObjectSimple(Thread & thread,CompilerType & return_compiler_type) const295 ValueObjectSP ABISysV_msp430::GetReturnValueObjectSimple(
296 Thread &thread, CompilerType &return_compiler_type) const {
297 ValueObjectSP return_valobj_sp;
298 return return_valobj_sp;
299 }
300
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const301 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
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)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
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)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
RegisterIsVolatile(const RegisterInfo * reg_info)347 bool ABISysV_msp430::RegisterIsVolatile(const RegisterInfo *reg_info) {
348 return !RegisterIsCalleeSaved(reg_info);
349 }
350
RegisterIsCalleeSaved(const RegisterInfo * reg_info)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
Initialize(void)358 void ABISysV_msp430::Initialize(void) {
359 PluginManager::RegisterPlugin(
360 GetPluginNameStatic(), "System V ABI for msp430 targets", CreateInstance);
361 }
362
Terminate(void)363 void ABISysV_msp430::Terminate(void) {
364 PluginManager::UnregisterPlugin(CreateInstance);
365 }
366