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
32using namespace lldb;
33using namespace lldb_private;
34
35LLDB_PLUGIN_DEFINE_ADV(ABISysV_msp430, ABIMSP430)
36
37enum 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
56static const RegisterInfo g_register_infos[] = {
57 {.name: "r0",
58 .alt_name: "pc",
59 .byte_size: 2,
60 .byte_offset: 0,
61 .encoding: eEncodingUint,
62 .format: eFormatHex,
63 .kinds: {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
64 LLDB_INVALID_REGNUM},
65 .value_regs: nullptr,
66 .invalidate_regs: nullptr,
67 .flags_type: nullptr,
68 },
69 {.name: "r1",
70 .alt_name: "sp",
71 .byte_size: 2,
72 .byte_offset: 0,
73 .encoding: eEncodingUint,
74 .format: eFormatHex,
75 .kinds: {dwarf_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
76 LLDB_INVALID_REGNUM},
77 .value_regs: nullptr,
78 .invalidate_regs: nullptr,
79 .flags_type: nullptr,
80 },
81 {.name: "r2",
82 .alt_name: "",
83 .byte_size: 2,
84 .byte_offset: 0,
85 .encoding: eEncodingUint,
86 .format: eFormatHex,
87 .kinds: {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
88 LLDB_INVALID_REGNUM},
89 .value_regs: nullptr,
90 .invalidate_regs: nullptr,
91 .flags_type: nullptr,
92 },
93 {.name: "r3",
94 .alt_name: "",
95 .byte_size: 2,
96 .byte_offset: 0,
97 .encoding: eEncodingUint,
98 .format: eFormatHex,
99 .kinds: {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
100 LLDB_INVALID_REGNUM},
101 .value_regs: nullptr,
102 .invalidate_regs: nullptr,
103 .flags_type: nullptr,
104 },
105 {.name: "r4",
106 .alt_name: "fp",
107 .byte_size: 2,
108 .byte_offset: 0,
109 .encoding: eEncodingUint,
110 .format: eFormatHex,
111 .kinds: {dwarf_fp, dwarf_fp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
112 LLDB_INVALID_REGNUM},
113 .value_regs: nullptr,
114 .invalidate_regs: nullptr,
115 .flags_type: nullptr,
116 },
117 {.name: "r5",
118 .alt_name: "",
119 .byte_size: 2,
120 .byte_offset: 0,
121 .encoding: eEncodingUint,
122 .format: eFormatHex,
123 .kinds: {dwarf_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
124 LLDB_INVALID_REGNUM},
125 .value_regs: nullptr,
126 .invalidate_regs: nullptr,
127 .flags_type: nullptr,
128 },
129 {.name: "r6",
130 .alt_name: "",
131 .byte_size: 2,
132 .byte_offset: 0,
133 .encoding: eEncodingUint,
134 .format: eFormatHex,
135 .kinds: {dwarf_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
136 LLDB_INVALID_REGNUM},
137 .value_regs: nullptr,
138 .invalidate_regs: nullptr,
139 .flags_type: nullptr,
140 },
141 {.name: "r7",
142 .alt_name: "",
143 .byte_size: 2,
144 .byte_offset: 0,
145 .encoding: eEncodingUint,
146 .format: eFormatHex,
147 .kinds: {dwarf_r7, dwarf_r7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
148 LLDB_INVALID_REGNUM},
149 .value_regs: nullptr,
150 .invalidate_regs: nullptr,
151 .flags_type: nullptr,
152 },
153 {.name: "r8",
154 .alt_name: "",
155 .byte_size: 2,
156 .byte_offset: 0,
157 .encoding: eEncodingUint,
158 .format: eFormatHex,
159 .kinds: {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
160 LLDB_INVALID_REGNUM},
161 .value_regs: nullptr,
162 .invalidate_regs: nullptr,
163 .flags_type: nullptr,
164 },
165 {.name: "r9",
166 .alt_name: "",
167 .byte_size: 2,
168 .byte_offset: 0,
169 .encoding: eEncodingUint,
170 .format: eFormatHex,
171 .kinds: {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
172 LLDB_INVALID_REGNUM},
173 .value_regs: nullptr,
174 .invalidate_regs: nullptr,
175 .flags_type: nullptr,
176 },
177 {.name: "r10",
178 .alt_name: "",
179 .byte_size: 2,
180 .byte_offset: 0,
181 .encoding: eEncodingUint,
182 .format: eFormatHex,
183 .kinds: {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
184 LLDB_INVALID_REGNUM},
185 .value_regs: nullptr,
186 .invalidate_regs: nullptr,
187 .flags_type: nullptr,
188 },
189 {.name: "r11",
190 .alt_name: "",
191 .byte_size: 2,
192 .byte_offset: 0,
193 .encoding: eEncodingUint,
194 .format: eFormatHex,
195 .kinds: {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
196 LLDB_INVALID_REGNUM},
197 .value_regs: nullptr,
198 .invalidate_regs: nullptr,
199 .flags_type: nullptr,
200 },
201 {.name: "r12",
202 .alt_name: "",
203 .byte_size: 2,
204 .byte_offset: 0,
205 .encoding: eEncodingUint,
206 .format: eFormatHex,
207 .kinds: {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
208 LLDB_INVALID_REGNUM},
209 .value_regs: nullptr,
210 .invalidate_regs: nullptr,
211 .flags_type: nullptr,
212 },
213 {.name: "r13",
214 .alt_name: "",
215 .byte_size: 2,
216 .byte_offset: 0,
217 .encoding: eEncodingUint,
218 .format: eFormatHex,
219 .kinds: {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
220 LLDB_INVALID_REGNUM},
221 .value_regs: nullptr,
222 .invalidate_regs: nullptr,
223 .flags_type: nullptr,
224 },
225 {.name: "r14",
226 .alt_name: "",
227 .byte_size: 2,
228 .byte_offset: 0,
229 .encoding: eEncodingUint,
230 .format: eFormatHex,
231 .kinds: {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
232 LLDB_INVALID_REGNUM},
233 .value_regs: nullptr,
234 .invalidate_regs: nullptr,
235 .flags_type: nullptr,
236 },
237 {.name: "r15",
238 .alt_name: "",
239 .byte_size: 2,
240 .byte_offset: 0,
241 .encoding: eEncodingUint,
242 .format: eFormatHex,
243 .kinds: {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
244 LLDB_INVALID_REGNUM},
245 .value_regs: nullptr,
246 .invalidate_regs: nullptr,
247 .flags_type: nullptr,
248 }};
249
250static const uint32_t k_num_register_infos =
251 sizeof(g_register_infos) / sizeof(RegisterInfo);
252
253const lldb_private::RegisterInfo *
254ABISysV_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
262size_t ABISysV_msp430::GetRedZoneSize() const { return 0; }
263
264//------------------------------------------------------------------
265// Static Functions
266//------------------------------------------------------------------
267
268ABISP
269ABISysV_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
278bool 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
285bool ABISysV_msp430::GetArgumentValues(Thread &thread,
286 ValueList &values) const {
287 return false;
288}
289
290Status ABISysV_msp430::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
291 lldb::ValueObjectSP &new_value_sp) {
292 return Status();
293}
294
295ValueObjectSP ABISysV_msp430::GetReturnValueObjectSimple(
296 Thread &thread, CompilerType &return_compiler_type) const {
297 ValueObjectSP return_valobj_sp;
298 return return_valobj_sp;
299}
300
301ValueObjectSP 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
308bool 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(reg_num: sp_reg_num, offset: 2);
317 row->SetRegisterLocationToAtCFAPlusOffset(reg_num: pc_reg_num, offset: -2, can_replace: true);
318 row->SetRegisterLocationToIsCFAPlusOffset(reg_num: sp_reg_num, offset: 0, can_replace: true);
319
320 unwind_plan.AppendRow(row_sp: row);
321 unwind_plan.SetSourceName("msp430 at-func-entry default");
322 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
323 return true;
324}
325
326bool 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(reg_num: sp_reg_num, offset: 2);
336 row->SetRegisterLocationToAtCFAPlusOffset(reg_num: pc_reg_num, offset: -2, can_replace: true);
337 row->SetRegisterLocationToIsCFAPlusOffset(reg_num: sp_reg_num, offset: 0, can_replace: true);
338 row->SetRegisterLocationToUnspecified(reg_num: fp_reg_num, can_replace: true);
339
340 unwind_plan.AppendRow(row_sp: row);
341 unwind_plan.SetSourceName("msp430 default unwind plan");
342 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
343 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
344 return true;
345}
346
347bool ABISysV_msp430::RegisterIsVolatile(const RegisterInfo *reg_info) {
348 return !RegisterIsCalleeSaved(reg_info);
349}
350
351bool 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
358void ABISysV_msp430::Initialize(void) {
359 PluginManager::RegisterPlugin(
360 name: GetPluginNameStatic(), description: "System V ABI for msp430 targets", create_callback: CreateInstance);
361}
362
363void ABISysV_msp430::Terminate(void) {
364 PluginManager::UnregisterPlugin(create_callback: CreateInstance);
365}
366

source code of lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.cpp