1dda28197Spatrick //===-- ABISysV_mips.cpp --------------------------------------------------===//
2dda28197Spatrick //
3dda28197Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4dda28197Spatrick // See https://llvm.org/LICENSE.txt for license information.
5dda28197Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dda28197Spatrick //
7dda28197Spatrick //===----------------------------------------------------------------------===//
8dda28197Spatrick
9dda28197Spatrick #include "ABISysV_mips.h"
10dda28197Spatrick
11dda28197Spatrick #include "llvm/ADT/STLExtras.h"
12dda28197Spatrick #include "llvm/ADT/Triple.h"
13dda28197Spatrick
14dda28197Spatrick #include "lldb/Core/Module.h"
15dda28197Spatrick #include "lldb/Core/PluginManager.h"
16dda28197Spatrick #include "lldb/Core/Value.h"
17dda28197Spatrick #include "lldb/Core/ValueObjectConstResult.h"
18dda28197Spatrick #include "lldb/Core/ValueObjectMemory.h"
19dda28197Spatrick #include "lldb/Core/ValueObjectRegister.h"
20dda28197Spatrick #include "lldb/Symbol/UnwindPlan.h"
21dda28197Spatrick #include "lldb/Target/Process.h"
22dda28197Spatrick #include "lldb/Target/RegisterContext.h"
23dda28197Spatrick #include "lldb/Target/StackFrame.h"
24dda28197Spatrick #include "lldb/Target/Target.h"
25dda28197Spatrick #include "lldb/Target/Thread.h"
26dda28197Spatrick #include "lldb/Utility/ConstString.h"
27dda28197Spatrick #include "lldb/Utility/DataExtractor.h"
28*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
29dda28197Spatrick #include "lldb/Utility/Log.h"
30dda28197Spatrick #include "lldb/Utility/RegisterValue.h"
31dda28197Spatrick #include "lldb/Utility/Status.h"
32*f6aab3d8Srobert #include <optional>
33dda28197Spatrick
34dda28197Spatrick using namespace lldb;
35dda28197Spatrick using namespace lldb_private;
36dda28197Spatrick
37dda28197Spatrick LLDB_PLUGIN_DEFINE(ABISysV_mips)
38dda28197Spatrick
39dda28197Spatrick enum dwarf_regnums {
40dda28197Spatrick dwarf_r0 = 0,
41dda28197Spatrick dwarf_r1,
42dda28197Spatrick dwarf_r2,
43dda28197Spatrick dwarf_r3,
44dda28197Spatrick dwarf_r4,
45dda28197Spatrick dwarf_r5,
46dda28197Spatrick dwarf_r6,
47dda28197Spatrick dwarf_r7,
48dda28197Spatrick dwarf_r8,
49dda28197Spatrick dwarf_r9,
50dda28197Spatrick dwarf_r10,
51dda28197Spatrick dwarf_r11,
52dda28197Spatrick dwarf_r12,
53dda28197Spatrick dwarf_r13,
54dda28197Spatrick dwarf_r14,
55dda28197Spatrick dwarf_r15,
56dda28197Spatrick dwarf_r16,
57dda28197Spatrick dwarf_r17,
58dda28197Spatrick dwarf_r18,
59dda28197Spatrick dwarf_r19,
60dda28197Spatrick dwarf_r20,
61dda28197Spatrick dwarf_r21,
62dda28197Spatrick dwarf_r22,
63dda28197Spatrick dwarf_r23,
64dda28197Spatrick dwarf_r24,
65dda28197Spatrick dwarf_r25,
66dda28197Spatrick dwarf_r26,
67dda28197Spatrick dwarf_r27,
68dda28197Spatrick dwarf_r28,
69dda28197Spatrick dwarf_r29,
70dda28197Spatrick dwarf_r30,
71dda28197Spatrick dwarf_r31,
72dda28197Spatrick dwarf_sr,
73dda28197Spatrick dwarf_lo,
74dda28197Spatrick dwarf_hi,
75dda28197Spatrick dwarf_bad,
76dda28197Spatrick dwarf_cause,
77dda28197Spatrick dwarf_pc
78dda28197Spatrick };
79dda28197Spatrick
80dda28197Spatrick static const RegisterInfo g_register_infos[] = {
81dda28197Spatrick // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME
82dda28197Spatrick // DWARF GENERIC PROCESS PLUGINS
83dda28197Spatrick // LLDB NATIVE VALUE REGS INVALIDATE REGS
84dda28197Spatrick // ======== ====== == === ============= =========== ============
85dda28197Spatrick // ============== ============ =================
86dda28197Spatrick // =================== ========== =================
87dda28197Spatrick {"r0",
88dda28197Spatrick "zero",
89dda28197Spatrick 4,
90dda28197Spatrick 0,
91dda28197Spatrick eEncodingUint,
92dda28197Spatrick eFormatHex,
93dda28197Spatrick {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
94dda28197Spatrick LLDB_INVALID_REGNUM},
95dda28197Spatrick nullptr,
96dda28197Spatrick nullptr,
97*f6aab3d8Srobert },
98dda28197Spatrick {"r1",
99dda28197Spatrick "AT",
100dda28197Spatrick 4,
101dda28197Spatrick 0,
102dda28197Spatrick eEncodingUint,
103dda28197Spatrick eFormatHex,
104dda28197Spatrick {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
105dda28197Spatrick LLDB_INVALID_REGNUM},
106dda28197Spatrick nullptr,
107dda28197Spatrick nullptr,
108*f6aab3d8Srobert },
109dda28197Spatrick {"r2",
110dda28197Spatrick "v0",
111dda28197Spatrick 4,
112dda28197Spatrick 0,
113dda28197Spatrick eEncodingUint,
114dda28197Spatrick eFormatHex,
115dda28197Spatrick {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
116dda28197Spatrick LLDB_INVALID_REGNUM},
117dda28197Spatrick nullptr,
118dda28197Spatrick nullptr,
119*f6aab3d8Srobert },
120dda28197Spatrick {"r3",
121dda28197Spatrick "v1",
122dda28197Spatrick 4,
123dda28197Spatrick 0,
124dda28197Spatrick eEncodingUint,
125dda28197Spatrick eFormatHex,
126dda28197Spatrick {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
127dda28197Spatrick LLDB_INVALID_REGNUM},
128dda28197Spatrick nullptr,
129dda28197Spatrick nullptr,
130*f6aab3d8Srobert },
131dda28197Spatrick {"r4",
132*f6aab3d8Srobert nullptr,
133dda28197Spatrick 4,
134dda28197Spatrick 0,
135dda28197Spatrick eEncodingUint,
136dda28197Spatrick eFormatHex,
137dda28197Spatrick {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
138dda28197Spatrick LLDB_INVALID_REGNUM},
139dda28197Spatrick nullptr,
140dda28197Spatrick nullptr,
141*f6aab3d8Srobert },
142dda28197Spatrick {"r5",
143*f6aab3d8Srobert nullptr,
144dda28197Spatrick 4,
145dda28197Spatrick 0,
146dda28197Spatrick eEncodingUint,
147dda28197Spatrick eFormatHex,
148dda28197Spatrick {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
149dda28197Spatrick LLDB_INVALID_REGNUM},
150dda28197Spatrick nullptr,
151dda28197Spatrick nullptr,
152*f6aab3d8Srobert },
153dda28197Spatrick {"r6",
154*f6aab3d8Srobert nullptr,
155dda28197Spatrick 4,
156dda28197Spatrick 0,
157dda28197Spatrick eEncodingUint,
158dda28197Spatrick eFormatHex,
159dda28197Spatrick {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
160dda28197Spatrick LLDB_INVALID_REGNUM},
161dda28197Spatrick nullptr,
162dda28197Spatrick nullptr,
163*f6aab3d8Srobert },
164dda28197Spatrick {"r7",
165*f6aab3d8Srobert nullptr,
166dda28197Spatrick 4,
167dda28197Spatrick 0,
168dda28197Spatrick eEncodingUint,
169dda28197Spatrick eFormatHex,
170dda28197Spatrick {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
171dda28197Spatrick LLDB_INVALID_REGNUM},
172dda28197Spatrick nullptr,
173dda28197Spatrick nullptr,
174*f6aab3d8Srobert },
175dda28197Spatrick {"r8",
176dda28197Spatrick "arg5",
177dda28197Spatrick 4,
178dda28197Spatrick 0,
179dda28197Spatrick eEncodingUint,
180dda28197Spatrick eFormatHex,
181dda28197Spatrick {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
182dda28197Spatrick LLDB_INVALID_REGNUM},
183dda28197Spatrick nullptr,
184dda28197Spatrick nullptr,
185*f6aab3d8Srobert },
186dda28197Spatrick {"r9",
187dda28197Spatrick "arg6",
188dda28197Spatrick 4,
189dda28197Spatrick 0,
190dda28197Spatrick eEncodingUint,
191dda28197Spatrick eFormatHex,
192dda28197Spatrick {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
193dda28197Spatrick LLDB_INVALID_REGNUM},
194dda28197Spatrick nullptr,
195dda28197Spatrick nullptr,
196*f6aab3d8Srobert },
197dda28197Spatrick {"r10",
198dda28197Spatrick "arg7",
199dda28197Spatrick 4,
200dda28197Spatrick 0,
201dda28197Spatrick eEncodingUint,
202dda28197Spatrick eFormatHex,
203dda28197Spatrick {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
204dda28197Spatrick LLDB_INVALID_REGNUM},
205dda28197Spatrick nullptr,
206dda28197Spatrick nullptr,
207*f6aab3d8Srobert },
208dda28197Spatrick {"r11",
209dda28197Spatrick "arg8",
210dda28197Spatrick 4,
211dda28197Spatrick 0,
212dda28197Spatrick eEncodingUint,
213dda28197Spatrick eFormatHex,
214dda28197Spatrick {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
215dda28197Spatrick LLDB_INVALID_REGNUM},
216dda28197Spatrick nullptr,
217dda28197Spatrick nullptr,
218*f6aab3d8Srobert },
219dda28197Spatrick {"r12",
220dda28197Spatrick nullptr,
221dda28197Spatrick 4,
222dda28197Spatrick 0,
223dda28197Spatrick eEncodingUint,
224dda28197Spatrick eFormatHex,
225dda28197Spatrick {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
226dda28197Spatrick LLDB_INVALID_REGNUM},
227dda28197Spatrick nullptr,
228dda28197Spatrick nullptr,
229*f6aab3d8Srobert },
230dda28197Spatrick {"r13",
231dda28197Spatrick nullptr,
232dda28197Spatrick 4,
233dda28197Spatrick 0,
234dda28197Spatrick eEncodingUint,
235dda28197Spatrick eFormatHex,
236dda28197Spatrick {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
237dda28197Spatrick LLDB_INVALID_REGNUM},
238dda28197Spatrick nullptr,
239dda28197Spatrick nullptr,
240*f6aab3d8Srobert },
241dda28197Spatrick {"r14",
242dda28197Spatrick nullptr,
243dda28197Spatrick 4,
244dda28197Spatrick 0,
245dda28197Spatrick eEncodingUint,
246dda28197Spatrick eFormatHex,
247dda28197Spatrick {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
248dda28197Spatrick LLDB_INVALID_REGNUM},
249dda28197Spatrick nullptr,
250dda28197Spatrick nullptr,
251*f6aab3d8Srobert },
252dda28197Spatrick {"r15",
253dda28197Spatrick nullptr,
254dda28197Spatrick 4,
255dda28197Spatrick 0,
256dda28197Spatrick eEncodingUint,
257dda28197Spatrick eFormatHex,
258dda28197Spatrick {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
259dda28197Spatrick LLDB_INVALID_REGNUM},
260dda28197Spatrick nullptr,
261dda28197Spatrick nullptr,
262*f6aab3d8Srobert },
263dda28197Spatrick {"r16",
264dda28197Spatrick nullptr,
265dda28197Spatrick 4,
266dda28197Spatrick 0,
267dda28197Spatrick eEncodingUint,
268dda28197Spatrick eFormatHex,
269dda28197Spatrick {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
270dda28197Spatrick LLDB_INVALID_REGNUM},
271dda28197Spatrick nullptr,
272dda28197Spatrick nullptr,
273*f6aab3d8Srobert },
274dda28197Spatrick {"r17",
275dda28197Spatrick nullptr,
276dda28197Spatrick 4,
277dda28197Spatrick 0,
278dda28197Spatrick eEncodingUint,
279dda28197Spatrick eFormatHex,
280dda28197Spatrick {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
281dda28197Spatrick LLDB_INVALID_REGNUM},
282dda28197Spatrick nullptr,
283dda28197Spatrick nullptr,
284*f6aab3d8Srobert },
285dda28197Spatrick {"r18",
286dda28197Spatrick nullptr,
287dda28197Spatrick 4,
288dda28197Spatrick 0,
289dda28197Spatrick eEncodingUint,
290dda28197Spatrick eFormatHex,
291dda28197Spatrick {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
292dda28197Spatrick LLDB_INVALID_REGNUM},
293dda28197Spatrick nullptr,
294dda28197Spatrick nullptr,
295*f6aab3d8Srobert },
296dda28197Spatrick {"r19",
297dda28197Spatrick nullptr,
298dda28197Spatrick 4,
299dda28197Spatrick 0,
300dda28197Spatrick eEncodingUint,
301dda28197Spatrick eFormatHex,
302dda28197Spatrick {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
303dda28197Spatrick LLDB_INVALID_REGNUM},
304dda28197Spatrick nullptr,
305dda28197Spatrick nullptr,
306*f6aab3d8Srobert },
307dda28197Spatrick {"r20",
308dda28197Spatrick nullptr,
309dda28197Spatrick 4,
310dda28197Spatrick 0,
311dda28197Spatrick eEncodingUint,
312dda28197Spatrick eFormatHex,
313dda28197Spatrick {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
314dda28197Spatrick LLDB_INVALID_REGNUM},
315dda28197Spatrick nullptr,
316dda28197Spatrick nullptr,
317*f6aab3d8Srobert },
318dda28197Spatrick {"r21",
319dda28197Spatrick nullptr,
320dda28197Spatrick 4,
321dda28197Spatrick 0,
322dda28197Spatrick eEncodingUint,
323dda28197Spatrick eFormatHex,
324dda28197Spatrick {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
325dda28197Spatrick LLDB_INVALID_REGNUM},
326dda28197Spatrick nullptr,
327dda28197Spatrick nullptr,
328*f6aab3d8Srobert },
329dda28197Spatrick {"r22",
330dda28197Spatrick nullptr,
331dda28197Spatrick 4,
332dda28197Spatrick 0,
333dda28197Spatrick eEncodingUint,
334dda28197Spatrick eFormatHex,
335dda28197Spatrick {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
336dda28197Spatrick LLDB_INVALID_REGNUM},
337dda28197Spatrick nullptr,
338dda28197Spatrick nullptr,
339*f6aab3d8Srobert },
340dda28197Spatrick {"r23",
341dda28197Spatrick nullptr,
342dda28197Spatrick 4,
343dda28197Spatrick 0,
344dda28197Spatrick eEncodingUint,
345dda28197Spatrick eFormatHex,
346dda28197Spatrick {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
347dda28197Spatrick LLDB_INVALID_REGNUM},
348dda28197Spatrick nullptr,
349dda28197Spatrick nullptr,
350*f6aab3d8Srobert },
351dda28197Spatrick {"r24",
352dda28197Spatrick nullptr,
353dda28197Spatrick 4,
354dda28197Spatrick 0,
355dda28197Spatrick eEncodingUint,
356dda28197Spatrick eFormatHex,
357dda28197Spatrick {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
358dda28197Spatrick LLDB_INVALID_REGNUM},
359dda28197Spatrick nullptr,
360dda28197Spatrick nullptr,
361*f6aab3d8Srobert },
362dda28197Spatrick {"r25",
363dda28197Spatrick nullptr,
364dda28197Spatrick 4,
365dda28197Spatrick 0,
366dda28197Spatrick eEncodingUint,
367dda28197Spatrick eFormatHex,
368dda28197Spatrick {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
369dda28197Spatrick LLDB_INVALID_REGNUM},
370dda28197Spatrick nullptr,
371dda28197Spatrick nullptr,
372*f6aab3d8Srobert },
373dda28197Spatrick {"r26",
374dda28197Spatrick nullptr,
375dda28197Spatrick 4,
376dda28197Spatrick 0,
377dda28197Spatrick eEncodingUint,
378dda28197Spatrick eFormatHex,
379dda28197Spatrick {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
380dda28197Spatrick LLDB_INVALID_REGNUM},
381dda28197Spatrick nullptr,
382dda28197Spatrick nullptr,
383*f6aab3d8Srobert },
384dda28197Spatrick {"r27",
385dda28197Spatrick nullptr,
386dda28197Spatrick 4,
387dda28197Spatrick 0,
388dda28197Spatrick eEncodingUint,
389dda28197Spatrick eFormatHex,
390dda28197Spatrick {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
391dda28197Spatrick LLDB_INVALID_REGNUM},
392dda28197Spatrick nullptr,
393dda28197Spatrick nullptr,
394*f6aab3d8Srobert },
395dda28197Spatrick {"r28",
396dda28197Spatrick "gp",
397dda28197Spatrick 4,
398dda28197Spatrick 0,
399dda28197Spatrick eEncodingUint,
400dda28197Spatrick eFormatHex,
401dda28197Spatrick {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
402dda28197Spatrick LLDB_INVALID_REGNUM},
403dda28197Spatrick nullptr,
404dda28197Spatrick nullptr,
405*f6aab3d8Srobert },
406dda28197Spatrick {"r29",
407*f6aab3d8Srobert nullptr,
408dda28197Spatrick 4,
409dda28197Spatrick 0,
410dda28197Spatrick eEncodingUint,
411dda28197Spatrick eFormatHex,
412dda28197Spatrick {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
413dda28197Spatrick LLDB_INVALID_REGNUM},
414dda28197Spatrick nullptr,
415dda28197Spatrick nullptr,
416*f6aab3d8Srobert },
417dda28197Spatrick {"r30",
418*f6aab3d8Srobert nullptr,
419dda28197Spatrick 4,
420dda28197Spatrick 0,
421dda28197Spatrick eEncodingUint,
422dda28197Spatrick eFormatHex,
423dda28197Spatrick {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
424dda28197Spatrick LLDB_INVALID_REGNUM},
425dda28197Spatrick nullptr,
426dda28197Spatrick nullptr,
427*f6aab3d8Srobert },
428dda28197Spatrick {"r31",
429*f6aab3d8Srobert nullptr,
430dda28197Spatrick 4,
431dda28197Spatrick 0,
432dda28197Spatrick eEncodingUint,
433dda28197Spatrick eFormatHex,
434dda28197Spatrick {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
435dda28197Spatrick LLDB_INVALID_REGNUM},
436dda28197Spatrick nullptr,
437dda28197Spatrick nullptr,
438*f6aab3d8Srobert },
439dda28197Spatrick {"sr",
440dda28197Spatrick nullptr,
441dda28197Spatrick 4,
442dda28197Spatrick 0,
443dda28197Spatrick eEncodingUint,
444dda28197Spatrick eFormatHex,
445dda28197Spatrick {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
446dda28197Spatrick LLDB_INVALID_REGNUM},
447dda28197Spatrick nullptr,
448dda28197Spatrick nullptr,
449*f6aab3d8Srobert },
450dda28197Spatrick {"lo",
451dda28197Spatrick nullptr,
452dda28197Spatrick 4,
453dda28197Spatrick 0,
454dda28197Spatrick eEncodingUint,
455dda28197Spatrick eFormatHex,
456dda28197Spatrick {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
457dda28197Spatrick LLDB_INVALID_REGNUM},
458dda28197Spatrick nullptr,
459dda28197Spatrick nullptr,
460*f6aab3d8Srobert },
461dda28197Spatrick {"hi",
462dda28197Spatrick nullptr,
463dda28197Spatrick 4,
464dda28197Spatrick 0,
465dda28197Spatrick eEncodingUint,
466dda28197Spatrick eFormatHex,
467dda28197Spatrick {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
468dda28197Spatrick LLDB_INVALID_REGNUM},
469dda28197Spatrick nullptr,
470dda28197Spatrick nullptr,
471*f6aab3d8Srobert },
472dda28197Spatrick {"bad",
473dda28197Spatrick nullptr,
474dda28197Spatrick 4,
475dda28197Spatrick 0,
476dda28197Spatrick eEncodingUint,
477dda28197Spatrick eFormatHex,
478dda28197Spatrick {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
479dda28197Spatrick LLDB_INVALID_REGNUM},
480dda28197Spatrick nullptr,
481dda28197Spatrick nullptr,
482*f6aab3d8Srobert },
483dda28197Spatrick {"cause",
484dda28197Spatrick nullptr,
485dda28197Spatrick 4,
486dda28197Spatrick 0,
487dda28197Spatrick eEncodingUint,
488dda28197Spatrick eFormatHex,
489dda28197Spatrick {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
490dda28197Spatrick LLDB_INVALID_REGNUM},
491dda28197Spatrick nullptr,
492dda28197Spatrick nullptr,
493*f6aab3d8Srobert },
494dda28197Spatrick {"pc",
495dda28197Spatrick nullptr,
496dda28197Spatrick 4,
497dda28197Spatrick 0,
498dda28197Spatrick eEncodingUint,
499dda28197Spatrick eFormatHex,
500dda28197Spatrick {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
501dda28197Spatrick LLDB_INVALID_REGNUM},
502dda28197Spatrick nullptr,
503dda28197Spatrick nullptr,
504*f6aab3d8Srobert },
505dda28197Spatrick };
506dda28197Spatrick
507*f6aab3d8Srobert static const uint32_t k_num_register_infos = std::size(g_register_infos);
508dda28197Spatrick
509dda28197Spatrick const lldb_private::RegisterInfo *
GetRegisterInfoArray(uint32_t & count)510dda28197Spatrick ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
511dda28197Spatrick count = k_num_register_infos;
512dda28197Spatrick return g_register_infos;
513dda28197Spatrick }
514dda28197Spatrick
GetRedZoneSize() const515dda28197Spatrick size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
516dda28197Spatrick
517dda28197Spatrick // Static Functions
518dda28197Spatrick
519dda28197Spatrick ABISP
CreateInstance(lldb::ProcessSP process_sp,const ArchSpec & arch)520dda28197Spatrick ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
521dda28197Spatrick const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
522dda28197Spatrick if ((arch_type == llvm::Triple::mips) ||
523dda28197Spatrick (arch_type == llvm::Triple::mipsel)) {
524dda28197Spatrick return ABISP(
525dda28197Spatrick new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch)));
526dda28197Spatrick }
527dda28197Spatrick return ABISP();
528dda28197Spatrick }
529dda28197Spatrick
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,llvm::ArrayRef<addr_t> args) const530dda28197Spatrick bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
531dda28197Spatrick addr_t func_addr, addr_t return_addr,
532dda28197Spatrick llvm::ArrayRef<addr_t> args) const {
533*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Expressions);
534dda28197Spatrick
535dda28197Spatrick if (log) {
536dda28197Spatrick StreamString s;
537dda28197Spatrick s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
538dda28197Spatrick ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
539dda28197Spatrick ", return_addr = 0x%" PRIx64,
540dda28197Spatrick thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
541dda28197Spatrick (uint64_t)return_addr);
542dda28197Spatrick
543dda28197Spatrick for (size_t i = 0; i < args.size(); ++i)
544dda28197Spatrick s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
545dda28197Spatrick s.PutCString(")");
546dda28197Spatrick log->PutString(s.GetString());
547dda28197Spatrick }
548dda28197Spatrick
549dda28197Spatrick RegisterContext *reg_ctx = thread.GetRegisterContext().get();
550dda28197Spatrick if (!reg_ctx)
551dda28197Spatrick return false;
552dda28197Spatrick
553dda28197Spatrick const RegisterInfo *reg_info = nullptr;
554dda28197Spatrick
555dda28197Spatrick RegisterValue reg_value;
556dda28197Spatrick
557dda28197Spatrick // Argument registers
558dda28197Spatrick const char *reg_names[] = {"r4", "r5", "r6", "r7"};
559dda28197Spatrick
560dda28197Spatrick llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
561dda28197Spatrick
562dda28197Spatrick // Write arguments to registers
563*f6aab3d8Srobert for (size_t i = 0; i < std::size(reg_names); ++i) {
564dda28197Spatrick if (ai == ae)
565dda28197Spatrick break;
566dda28197Spatrick
567dda28197Spatrick reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
568dda28197Spatrick LLDB_REGNUM_GENERIC_ARG1 + i);
569dda28197Spatrick LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
570dda28197Spatrick args[i], reg_info->name);
571dda28197Spatrick
572dda28197Spatrick if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
573dda28197Spatrick return false;
574dda28197Spatrick
575dda28197Spatrick ++ai;
576dda28197Spatrick }
577dda28197Spatrick
578dda28197Spatrick // If we have more than 4 arguments --Spill onto the stack
579dda28197Spatrick if (ai != ae) {
580dda28197Spatrick // No of arguments to go on stack
581dda28197Spatrick size_t num_stack_regs = args.size();
582dda28197Spatrick
583dda28197Spatrick // Allocate needed space for args on the stack
584dda28197Spatrick sp -= (num_stack_regs * 4);
585dda28197Spatrick
586dda28197Spatrick // Keep the stack 8 byte aligned
587dda28197Spatrick sp &= ~(8ull - 1ull);
588dda28197Spatrick
589dda28197Spatrick // just using arg1 to get the right size
590dda28197Spatrick const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
591dda28197Spatrick eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
592dda28197Spatrick
593dda28197Spatrick addr_t arg_pos = sp + 16;
594dda28197Spatrick
595dda28197Spatrick size_t i = 4;
596dda28197Spatrick for (; ai != ae; ++ai) {
597dda28197Spatrick reg_value.SetUInt32(*ai);
598dda28197Spatrick LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
599dda28197Spatrick i + 1, args[i], arg_pos);
600dda28197Spatrick
601dda28197Spatrick if (reg_ctx
602dda28197Spatrick ->WriteRegisterValueToMemory(reg_info, arg_pos,
603dda28197Spatrick reg_info->byte_size, reg_value)
604dda28197Spatrick .Fail())
605dda28197Spatrick return false;
606dda28197Spatrick arg_pos += reg_info->byte_size;
607dda28197Spatrick i++;
608dda28197Spatrick }
609dda28197Spatrick }
610dda28197Spatrick
611dda28197Spatrick Status error;
612dda28197Spatrick const RegisterInfo *pc_reg_info =
613dda28197Spatrick reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
614dda28197Spatrick const RegisterInfo *sp_reg_info =
615dda28197Spatrick reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
616dda28197Spatrick const RegisterInfo *ra_reg_info =
617dda28197Spatrick reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
618dda28197Spatrick const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
619dda28197Spatrick const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
620dda28197Spatrick
621dda28197Spatrick LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
622dda28197Spatrick
623dda28197Spatrick /* Write r0 with 0, in case we are stopped in syscall,
624dda28197Spatrick * such setting prevents automatic decrement of the PC.
625dda28197Spatrick * This clears the bug 23659 for MIPS.
626dda28197Spatrick */
627dda28197Spatrick if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
628dda28197Spatrick return false;
629dda28197Spatrick
630dda28197Spatrick LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
631dda28197Spatrick
632dda28197Spatrick // Set "sp" to the requested value
633dda28197Spatrick if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
634dda28197Spatrick return false;
635dda28197Spatrick
636dda28197Spatrick LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
637dda28197Spatrick
638dda28197Spatrick // Set "ra" to the return address
639dda28197Spatrick if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
640dda28197Spatrick return false;
641dda28197Spatrick
642dda28197Spatrick LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
643dda28197Spatrick
644dda28197Spatrick // Set pc to the address of the called function.
645dda28197Spatrick if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
646dda28197Spatrick return false;
647dda28197Spatrick
648dda28197Spatrick LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
649dda28197Spatrick
650dda28197Spatrick // All callers of position independent functions must place the address of
651dda28197Spatrick // the called function in t9 (r25)
652dda28197Spatrick if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
653dda28197Spatrick return false;
654dda28197Spatrick
655dda28197Spatrick return true;
656dda28197Spatrick }
657dda28197Spatrick
GetArgumentValues(Thread & thread,ValueList & values) const658dda28197Spatrick bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
659dda28197Spatrick return false;
660dda28197Spatrick }
661dda28197Spatrick
SetReturnValueObject(lldb::StackFrameSP & frame_sp,lldb::ValueObjectSP & new_value_sp)662dda28197Spatrick Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
663dda28197Spatrick lldb::ValueObjectSP &new_value_sp) {
664dda28197Spatrick Status error;
665dda28197Spatrick if (!new_value_sp) {
666dda28197Spatrick error.SetErrorString("Empty value object for return value.");
667dda28197Spatrick return error;
668dda28197Spatrick }
669dda28197Spatrick
670dda28197Spatrick CompilerType compiler_type = new_value_sp->GetCompilerType();
671dda28197Spatrick if (!compiler_type) {
672dda28197Spatrick error.SetErrorString("Null clang type for return value.");
673dda28197Spatrick return error;
674dda28197Spatrick }
675dda28197Spatrick
676dda28197Spatrick Thread *thread = frame_sp->GetThread().get();
677dda28197Spatrick
678dda28197Spatrick bool is_signed;
679dda28197Spatrick uint32_t count;
680dda28197Spatrick bool is_complex;
681dda28197Spatrick
682dda28197Spatrick RegisterContext *reg_ctx = thread->GetRegisterContext().get();
683dda28197Spatrick
684dda28197Spatrick bool set_it_simple = false;
685dda28197Spatrick if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
686dda28197Spatrick compiler_type.IsPointerType()) {
687dda28197Spatrick DataExtractor data;
688dda28197Spatrick Status data_error;
689dda28197Spatrick size_t num_bytes = new_value_sp->GetData(data, data_error);
690dda28197Spatrick if (data_error.Fail()) {
691dda28197Spatrick error.SetErrorStringWithFormat(
692dda28197Spatrick "Couldn't convert return value to raw data: %s",
693dda28197Spatrick data_error.AsCString());
694dda28197Spatrick return error;
695dda28197Spatrick }
696dda28197Spatrick
697dda28197Spatrick lldb::offset_t offset = 0;
698dda28197Spatrick if (num_bytes <= 8) {
699dda28197Spatrick const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
700dda28197Spatrick if (num_bytes <= 4) {
701dda28197Spatrick uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
702dda28197Spatrick
703dda28197Spatrick if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
704dda28197Spatrick set_it_simple = true;
705dda28197Spatrick } else {
706dda28197Spatrick uint32_t raw_value = data.GetMaxU32(&offset, 4);
707dda28197Spatrick
708dda28197Spatrick if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
709dda28197Spatrick const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
710dda28197Spatrick uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
711dda28197Spatrick
712dda28197Spatrick if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
713dda28197Spatrick set_it_simple = true;
714dda28197Spatrick }
715dda28197Spatrick }
716dda28197Spatrick } else {
717dda28197Spatrick error.SetErrorString("We don't support returning longer than 64 bit "
718dda28197Spatrick "integer values at present.");
719dda28197Spatrick }
720dda28197Spatrick } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
721dda28197Spatrick if (is_complex)
722dda28197Spatrick error.SetErrorString(
723dda28197Spatrick "We don't support returning complex values at present");
724dda28197Spatrick else
725dda28197Spatrick error.SetErrorString(
726dda28197Spatrick "We don't support returning float values at present");
727dda28197Spatrick }
728dda28197Spatrick
729dda28197Spatrick if (!set_it_simple)
730dda28197Spatrick error.SetErrorString(
731dda28197Spatrick "We only support setting simple integer return types at present.");
732dda28197Spatrick
733dda28197Spatrick return error;
734dda28197Spatrick }
735dda28197Spatrick
GetReturnValueObjectSimple(Thread & thread,CompilerType & return_compiler_type) const736dda28197Spatrick ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
737dda28197Spatrick Thread &thread, CompilerType &return_compiler_type) const {
738dda28197Spatrick ValueObjectSP return_valobj_sp;
739dda28197Spatrick return return_valobj_sp;
740dda28197Spatrick }
741dda28197Spatrick
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const742dda28197Spatrick ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
743dda28197Spatrick Thread &thread, CompilerType &return_compiler_type) const {
744dda28197Spatrick ValueObjectSP return_valobj_sp;
745dda28197Spatrick Value value;
746dda28197Spatrick
747dda28197Spatrick if (!return_compiler_type)
748dda28197Spatrick return return_valobj_sp;
749dda28197Spatrick
750dda28197Spatrick ExecutionContext exe_ctx(thread.shared_from_this());
751dda28197Spatrick if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
752dda28197Spatrick return return_valobj_sp;
753dda28197Spatrick
754dda28197Spatrick Target *target = exe_ctx.GetTargetPtr();
755dda28197Spatrick const ArchSpec target_arch = target->GetArchitecture();
756dda28197Spatrick ByteOrder target_byte_order = target_arch.GetByteOrder();
757dda28197Spatrick value.SetCompilerType(return_compiler_type);
758dda28197Spatrick uint32_t fp_flag =
759dda28197Spatrick target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
760dda28197Spatrick
761dda28197Spatrick RegisterContext *reg_ctx = thread.GetRegisterContext().get();
762dda28197Spatrick if (!reg_ctx)
763dda28197Spatrick return return_valobj_sp;
764dda28197Spatrick
765dda28197Spatrick bool is_signed = false;
766dda28197Spatrick bool is_complex = false;
767dda28197Spatrick uint32_t count = 0;
768dda28197Spatrick
769dda28197Spatrick // In MIPS register "r2" (v0) holds the integer function return values
770dda28197Spatrick const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
771*f6aab3d8Srobert std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
772dda28197Spatrick if (!bit_width)
773dda28197Spatrick return return_valobj_sp;
774dda28197Spatrick if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
775dda28197Spatrick switch (*bit_width) {
776dda28197Spatrick default:
777dda28197Spatrick return return_valobj_sp;
778dda28197Spatrick case 64: {
779dda28197Spatrick const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
780dda28197Spatrick uint64_t raw_value;
781dda28197Spatrick raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
782dda28197Spatrick raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
783dda28197Spatrick UINT32_MAX))
784dda28197Spatrick << 32;
785dda28197Spatrick if (is_signed)
786dda28197Spatrick value.GetScalar() = (int64_t)raw_value;
787dda28197Spatrick else
788dda28197Spatrick value.GetScalar() = (uint64_t)raw_value;
789dda28197Spatrick } break;
790dda28197Spatrick case 32:
791dda28197Spatrick if (is_signed)
792dda28197Spatrick value.GetScalar() = (int32_t)(
793dda28197Spatrick reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
794dda28197Spatrick else
795dda28197Spatrick value.GetScalar() = (uint32_t)(
796dda28197Spatrick reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
797dda28197Spatrick break;
798dda28197Spatrick case 16:
799dda28197Spatrick if (is_signed)
800dda28197Spatrick value.GetScalar() = (int16_t)(
801dda28197Spatrick reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
802dda28197Spatrick else
803dda28197Spatrick value.GetScalar() = (uint16_t)(
804dda28197Spatrick reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
805dda28197Spatrick break;
806dda28197Spatrick case 8:
807dda28197Spatrick if (is_signed)
808dda28197Spatrick value.GetScalar() = (int8_t)(
809dda28197Spatrick reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
810dda28197Spatrick else
811dda28197Spatrick value.GetScalar() = (uint8_t)(
812dda28197Spatrick reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
813dda28197Spatrick break;
814dda28197Spatrick }
815dda28197Spatrick } else if (return_compiler_type.IsPointerType()) {
816dda28197Spatrick uint32_t ptr =
817dda28197Spatrick thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
818dda28197Spatrick UINT32_MAX;
819dda28197Spatrick value.GetScalar() = ptr;
820dda28197Spatrick } else if (return_compiler_type.IsAggregateType()) {
821dda28197Spatrick // Structure/Vector is always passed in memory and pointer to that memory
822dda28197Spatrick // is passed in r2.
823dda28197Spatrick uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
824dda28197Spatrick reg_ctx->GetRegisterInfoByName("r2", 0), 0);
825dda28197Spatrick // We have got the address. Create a memory object out of it
826dda28197Spatrick return_valobj_sp = ValueObjectMemory::Create(
827dda28197Spatrick &thread, "", Address(mem_address, nullptr), return_compiler_type);
828dda28197Spatrick return return_valobj_sp;
829dda28197Spatrick } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
830dda28197Spatrick if (IsSoftFloat(fp_flag)) {
831dda28197Spatrick uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
832dda28197Spatrick if (count != 1 && is_complex)
833dda28197Spatrick return return_valobj_sp;
834dda28197Spatrick switch (*bit_width) {
835dda28197Spatrick default:
836dda28197Spatrick return return_valobj_sp;
837dda28197Spatrick case 32:
838*f6aab3d8Srobert static_assert(sizeof(float) == sizeof(uint32_t));
839dda28197Spatrick value.GetScalar() = *((float *)(&raw_value));
840dda28197Spatrick break;
841dda28197Spatrick case 64:
842*f6aab3d8Srobert static_assert(sizeof(double) == sizeof(uint64_t));
843dda28197Spatrick const RegisterInfo *r3_reg_info =
844dda28197Spatrick reg_ctx->GetRegisterInfoByName("r3", 0);
845dda28197Spatrick if (target_byte_order == eByteOrderLittle)
846dda28197Spatrick raw_value =
847dda28197Spatrick ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
848dda28197Spatrick raw_value;
849dda28197Spatrick else
850dda28197Spatrick raw_value = (raw_value << 32) |
851dda28197Spatrick reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
852dda28197Spatrick value.GetScalar() = *((double *)(&raw_value));
853dda28197Spatrick break;
854dda28197Spatrick }
855dda28197Spatrick }
856dda28197Spatrick
857dda28197Spatrick else {
858dda28197Spatrick const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
859dda28197Spatrick RegisterValue f0_value;
860dda28197Spatrick DataExtractor f0_data;
861dda28197Spatrick reg_ctx->ReadRegister(f0_info, f0_value);
862dda28197Spatrick f0_value.GetData(f0_data);
863dda28197Spatrick lldb::offset_t offset = 0;
864dda28197Spatrick
865dda28197Spatrick if (count == 1 && !is_complex) {
866dda28197Spatrick switch (*bit_width) {
867dda28197Spatrick default:
868dda28197Spatrick return return_valobj_sp;
869dda28197Spatrick case 64: {
870*f6aab3d8Srobert static_assert(sizeof(double) == sizeof(uint64_t));
871dda28197Spatrick const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
872dda28197Spatrick RegisterValue f1_value;
873dda28197Spatrick DataExtractor f1_data;
874dda28197Spatrick reg_ctx->ReadRegister(f1_info, f1_value);
875dda28197Spatrick DataExtractor *copy_from_extractor = nullptr;
876*f6aab3d8Srobert WritableDataBufferSP data_sp(new DataBufferHeap(8, 0));
877dda28197Spatrick DataExtractor return_ext(
878dda28197Spatrick data_sp, target_byte_order,
879dda28197Spatrick target->GetArchitecture().GetAddressByteSize());
880dda28197Spatrick
881dda28197Spatrick if (target_byte_order == eByteOrderLittle) {
882dda28197Spatrick copy_from_extractor = &f0_data;
883dda28197Spatrick copy_from_extractor->CopyByteOrderedData(
884dda28197Spatrick offset, 4, data_sp->GetBytes(), 4, target_byte_order);
885dda28197Spatrick f1_value.GetData(f1_data);
886dda28197Spatrick copy_from_extractor = &f1_data;
887dda28197Spatrick copy_from_extractor->CopyByteOrderedData(
888dda28197Spatrick offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
889dda28197Spatrick } else {
890dda28197Spatrick copy_from_extractor = &f0_data;
891dda28197Spatrick copy_from_extractor->CopyByteOrderedData(
892dda28197Spatrick offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
893dda28197Spatrick f1_value.GetData(f1_data);
894dda28197Spatrick copy_from_extractor = &f1_data;
895dda28197Spatrick copy_from_extractor->CopyByteOrderedData(
896dda28197Spatrick offset, 4, data_sp->GetBytes(), 4, target_byte_order);
897dda28197Spatrick }
898dda28197Spatrick value.GetScalar() = (double)return_ext.GetDouble(&offset);
899dda28197Spatrick break;
900dda28197Spatrick }
901dda28197Spatrick case 32: {
902*f6aab3d8Srobert static_assert(sizeof(float) == sizeof(uint32_t));
903dda28197Spatrick value.GetScalar() = (float)f0_data.GetFloat(&offset);
904dda28197Spatrick break;
905dda28197Spatrick }
906dda28197Spatrick }
907dda28197Spatrick } else {
908dda28197Spatrick // not handled yet
909dda28197Spatrick return return_valobj_sp;
910dda28197Spatrick }
911dda28197Spatrick }
912dda28197Spatrick } else {
913dda28197Spatrick // not handled yet
914dda28197Spatrick return return_valobj_sp;
915dda28197Spatrick }
916dda28197Spatrick
917dda28197Spatrick // If we get here, we have a valid Value, so make our ValueObject out of it:
918dda28197Spatrick
919dda28197Spatrick return_valobj_sp = ValueObjectConstResult::Create(
920dda28197Spatrick thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
921dda28197Spatrick return return_valobj_sp;
922dda28197Spatrick }
923dda28197Spatrick
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)924dda28197Spatrick bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
925dda28197Spatrick unwind_plan.Clear();
926dda28197Spatrick unwind_plan.SetRegisterKind(eRegisterKindDWARF);
927dda28197Spatrick
928dda28197Spatrick UnwindPlan::RowSP row(new UnwindPlan::Row);
929dda28197Spatrick
930dda28197Spatrick // Our Call Frame Address is the stack pointer value
931dda28197Spatrick row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
932dda28197Spatrick
933dda28197Spatrick // The previous PC is in the RA
934dda28197Spatrick row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
935dda28197Spatrick unwind_plan.AppendRow(row);
936dda28197Spatrick
937dda28197Spatrick // All other registers are the same.
938dda28197Spatrick
939dda28197Spatrick unwind_plan.SetSourceName("mips at-func-entry default");
940dda28197Spatrick unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
941dda28197Spatrick unwind_plan.SetReturnAddressRegister(dwarf_r31);
942dda28197Spatrick return true;
943dda28197Spatrick }
944dda28197Spatrick
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)945dda28197Spatrick bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
946dda28197Spatrick unwind_plan.Clear();
947dda28197Spatrick unwind_plan.SetRegisterKind(eRegisterKindDWARF);
948dda28197Spatrick
949dda28197Spatrick UnwindPlan::RowSP row(new UnwindPlan::Row);
950dda28197Spatrick
951be691f3bSpatrick row->SetUnspecifiedRegistersAreUndefined(true);
952dda28197Spatrick row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
953dda28197Spatrick
954dda28197Spatrick row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
955dda28197Spatrick
956dda28197Spatrick unwind_plan.AppendRow(row);
957dda28197Spatrick unwind_plan.SetSourceName("mips default unwind plan");
958dda28197Spatrick unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
959dda28197Spatrick unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
960dda28197Spatrick unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
961dda28197Spatrick return true;
962dda28197Spatrick }
963dda28197Spatrick
RegisterIsVolatile(const RegisterInfo * reg_info)964dda28197Spatrick bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
965dda28197Spatrick return !RegisterIsCalleeSaved(reg_info);
966dda28197Spatrick }
967dda28197Spatrick
IsSoftFloat(uint32_t fp_flags) const968dda28197Spatrick bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
969dda28197Spatrick return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
970dda28197Spatrick }
971dda28197Spatrick
RegisterIsCalleeSaved(const RegisterInfo * reg_info)972dda28197Spatrick bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
973dda28197Spatrick if (reg_info) {
974dda28197Spatrick // Preserved registers are :
975dda28197Spatrick // r16-r23, r28, r29, r30, r31
976dda28197Spatrick const char *name = reg_info->name;
977dda28197Spatrick
978dda28197Spatrick if (name[0] == 'r') {
979dda28197Spatrick switch (name[1]) {
980dda28197Spatrick case '1':
981dda28197Spatrick if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
982dda28197Spatrick name[2] == '9') // r16-r19
983dda28197Spatrick return name[3] == '\0';
984dda28197Spatrick break;
985dda28197Spatrick case '2':
986dda28197Spatrick if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
987dda28197Spatrick name[2] == '3' // r20-r23
988dda28197Spatrick || name[2] == '8' || name[2] == '9') // r28 and r29
989dda28197Spatrick return name[3] == '\0';
990dda28197Spatrick break;
991dda28197Spatrick case '3':
992dda28197Spatrick if (name[2] == '0' || name[2] == '1') // r30 and r31
993dda28197Spatrick return name[3] == '\0';
994dda28197Spatrick break;
995dda28197Spatrick }
996dda28197Spatrick
997dda28197Spatrick if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
998dda28197Spatrick return true;
999dda28197Spatrick if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
1000dda28197Spatrick return true;
1001dda28197Spatrick if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
1002dda28197Spatrick return true;
1003dda28197Spatrick if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
1004dda28197Spatrick return true;
1005dda28197Spatrick }
1006dda28197Spatrick }
1007dda28197Spatrick return false;
1008dda28197Spatrick }
1009dda28197Spatrick
Initialize()1010dda28197Spatrick void ABISysV_mips::Initialize() {
1011dda28197Spatrick PluginManager::RegisterPlugin(
1012dda28197Spatrick GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1013dda28197Spatrick }
1014dda28197Spatrick
Terminate()1015dda28197Spatrick void ABISysV_mips::Terminate() {
1016dda28197Spatrick PluginManager::UnregisterPlugin(CreateInstance);
1017dda28197Spatrick }
1018