1 //===-- ABISysV_mips64.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ABISysV_mips64.h"
10 
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/Triple.h"
13 
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/Value.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/Core/ValueObjectMemory.h"
19 #include "lldb/Core/ValueObjectRegister.h"
20 #include "lldb/Symbol/UnwindPlan.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/StackFrame.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Utility/ConstString.h"
27 #include "lldb/Utility/DataExtractor.h"
28 #include "lldb/Utility/Log.h"
29 #include "lldb/Utility/RegisterValue.h"
30 #include "lldb/Utility/Status.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 LLDB_PLUGIN_DEFINE(ABISysV_mips64)
36 
37 enum dwarf_regnums {
38   dwarf_r0 = 0,
39   dwarf_r1,
40   dwarf_r2,
41   dwarf_r3,
42   dwarf_r4,
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   dwarf_r16,
55   dwarf_r17,
56   dwarf_r18,
57   dwarf_r19,
58   dwarf_r20,
59   dwarf_r21,
60   dwarf_r22,
61   dwarf_r23,
62   dwarf_r24,
63   dwarf_r25,
64   dwarf_r26,
65   dwarf_r27,
66   dwarf_r28,
67   dwarf_r29,
68   dwarf_r30,
69   dwarf_r31,
70   dwarf_sr,
71   dwarf_lo,
72   dwarf_hi,
73   dwarf_bad,
74   dwarf_cause,
75   dwarf_pc
76 };
77 
78 static const RegisterInfo g_register_infos_mips64[] = {
79     //  NAME      ALT    SZ OFF ENCODING        FORMAT         EH_FRAME
80     //  DWARF                   GENERIC                     PROCESS PLUGIN
81     //  LLDB NATIVE
82     //  ========  ======  == === =============  ==========     =============
83     //  =================       ====================        =================
84     //  ====================
85     {"r0",
86      "zero",
87      8,
88      0,
89      eEncodingUint,
90      eFormatHex,
91      {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
92       LLDB_INVALID_REGNUM},
93      nullptr,
94      nullptr,
95     },
96     {"r1",
97      "AT",
98      8,
99      0,
100      eEncodingUint,
101      eFormatHex,
102      {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
103       LLDB_INVALID_REGNUM},
104      nullptr,
105      nullptr,
106     },
107     {"r2",
108      "v0",
109      8,
110      0,
111      eEncodingUint,
112      eFormatHex,
113      {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
114       LLDB_INVALID_REGNUM},
115      nullptr,
116      nullptr,
117     },
118     {"r3",
119      "v1",
120      8,
121      0,
122      eEncodingUint,
123      eFormatHex,
124      {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
125       LLDB_INVALID_REGNUM},
126      nullptr,
127      nullptr,
128     },
129     {"r4",
130      nullptr,
131      8,
132      0,
133      eEncodingUint,
134      eFormatHex,
135      {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
136       LLDB_INVALID_REGNUM},
137      nullptr,
138      nullptr,
139     },
140     {"r5",
141      nullptr,
142      8,
143      0,
144      eEncodingUint,
145      eFormatHex,
146      {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
147       LLDB_INVALID_REGNUM},
148      nullptr,
149      nullptr,
150     },
151     {"r6",
152      nullptr,
153      8,
154      0,
155      eEncodingUint,
156      eFormatHex,
157      {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
158       LLDB_INVALID_REGNUM},
159      nullptr,
160      nullptr,
161     },
162     {"r7",
163      nullptr,
164      8,
165      0,
166      eEncodingUint,
167      eFormatHex,
168      {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
169       LLDB_INVALID_REGNUM},
170      nullptr,
171      nullptr,
172     },
173     {"r8",
174      nullptr,
175      8,
176      0,
177      eEncodingUint,
178      eFormatHex,
179      {dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM,
180       LLDB_INVALID_REGNUM},
181      nullptr,
182      nullptr,
183     },
184     {"r9",
185      nullptr,
186      8,
187      0,
188      eEncodingUint,
189      eFormatHex,
190      {dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM,
191       LLDB_INVALID_REGNUM},
192      nullptr,
193      nullptr,
194     },
195     {"r10",
196      nullptr,
197      8,
198      0,
199      eEncodingUint,
200      eFormatHex,
201      {dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM,
202       LLDB_INVALID_REGNUM},
203      nullptr,
204      nullptr,
205     },
206     {"r11",
207      nullptr,
208      8,
209      0,
210      eEncodingUint,
211      eFormatHex,
212      {dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM,
213       LLDB_INVALID_REGNUM},
214      nullptr,
215      nullptr,
216     },
217     {"r12",
218      nullptr,
219      8,
220      0,
221      eEncodingUint,
222      eFormatHex,
223      {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
224       LLDB_INVALID_REGNUM},
225      nullptr,
226      nullptr,
227     },
228     {"r13",
229      nullptr,
230      8,
231      0,
232      eEncodingUint,
233      eFormatHex,
234      {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
235       LLDB_INVALID_REGNUM},
236      nullptr,
237      nullptr,
238     },
239     {"r14",
240      nullptr,
241      8,
242      0,
243      eEncodingUint,
244      eFormatHex,
245      {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
246       LLDB_INVALID_REGNUM},
247      nullptr,
248      nullptr,
249     },
250     {"r15",
251      nullptr,
252      8,
253      0,
254      eEncodingUint,
255      eFormatHex,
256      {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
257       LLDB_INVALID_REGNUM},
258      nullptr,
259      nullptr,
260     },
261     {"r16",
262      nullptr,
263      8,
264      0,
265      eEncodingUint,
266      eFormatHex,
267      {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
268       LLDB_INVALID_REGNUM},
269      nullptr,
270      nullptr,
271     },
272     {"r17",
273      nullptr,
274      8,
275      0,
276      eEncodingUint,
277      eFormatHex,
278      {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
279       LLDB_INVALID_REGNUM},
280      nullptr,
281      nullptr,
282     },
283     {"r18",
284      nullptr,
285      8,
286      0,
287      eEncodingUint,
288      eFormatHex,
289      {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
290       LLDB_INVALID_REGNUM},
291      nullptr,
292      nullptr,
293     },
294     {"r19",
295      nullptr,
296      8,
297      0,
298      eEncodingUint,
299      eFormatHex,
300      {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
301       LLDB_INVALID_REGNUM},
302      nullptr,
303      nullptr,
304     },
305     {"r20",
306      nullptr,
307      8,
308      0,
309      eEncodingUint,
310      eFormatHex,
311      {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
312       LLDB_INVALID_REGNUM},
313      nullptr,
314      nullptr,
315     },
316     {"r21",
317      nullptr,
318      8,
319      0,
320      eEncodingUint,
321      eFormatHex,
322      {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
323       LLDB_INVALID_REGNUM},
324      nullptr,
325      nullptr,
326     },
327     {"r22",
328      nullptr,
329      8,
330      0,
331      eEncodingUint,
332      eFormatHex,
333      {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
334       LLDB_INVALID_REGNUM},
335      nullptr,
336      nullptr,
337     },
338     {"r23",
339      nullptr,
340      8,
341      0,
342      eEncodingUint,
343      eFormatHex,
344      {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
345       LLDB_INVALID_REGNUM},
346      nullptr,
347      nullptr,
348     },
349     {"r24",
350      nullptr,
351      8,
352      0,
353      eEncodingUint,
354      eFormatHex,
355      {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
356       LLDB_INVALID_REGNUM},
357      nullptr,
358      nullptr,
359     },
360     {"r25",
361      nullptr,
362      8,
363      0,
364      eEncodingUint,
365      eFormatHex,
366      {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
367       LLDB_INVALID_REGNUM},
368      nullptr,
369      nullptr,
370     },
371     {"r26",
372      nullptr,
373      8,
374      0,
375      eEncodingUint,
376      eFormatHex,
377      {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
378       LLDB_INVALID_REGNUM},
379      nullptr,
380      nullptr,
381     },
382     {"r27",
383      nullptr,
384      8,
385      0,
386      eEncodingUint,
387      eFormatHex,
388      {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
389       LLDB_INVALID_REGNUM},
390      nullptr,
391      nullptr,
392     },
393     {"r28",
394      "gp",
395      8,
396      0,
397      eEncodingUint,
398      eFormatHex,
399      {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
400       LLDB_INVALID_REGNUM},
401      nullptr,
402      nullptr,
403     },
404     {"r29",
405      nullptr,
406      8,
407      0,
408      eEncodingUint,
409      eFormatHex,
410      {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
411       LLDB_INVALID_REGNUM},
412      nullptr,
413      nullptr,
414     },
415     {"r30",
416      nullptr,
417      8,
418      0,
419      eEncodingUint,
420      eFormatHex,
421      {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
422       LLDB_INVALID_REGNUM},
423      nullptr,
424      nullptr,
425     },
426     {"r31",
427      nullptr,
428      8,
429      0,
430      eEncodingUint,
431      eFormatHex,
432      {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
433       LLDB_INVALID_REGNUM},
434      nullptr,
435      nullptr,
436     },
437     {"sr",
438      nullptr,
439      4,
440      0,
441      eEncodingUint,
442      eFormatHex,
443      {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
444       LLDB_INVALID_REGNUM},
445      nullptr,
446      nullptr,
447     },
448     {"lo",
449      nullptr,
450      8,
451      0,
452      eEncodingUint,
453      eFormatHex,
454      {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
455       LLDB_INVALID_REGNUM},
456      nullptr,
457      nullptr,
458     },
459     {"hi",
460      nullptr,
461      8,
462      0,
463      eEncodingUint,
464      eFormatHex,
465      {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
466       LLDB_INVALID_REGNUM},
467      nullptr,
468      nullptr,
469     },
470     {"bad",
471      nullptr,
472      8,
473      0,
474      eEncodingUint,
475      eFormatHex,
476      {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
477       LLDB_INVALID_REGNUM},
478      nullptr,
479      nullptr,
480     },
481     {"cause",
482      nullptr,
483      8,
484      0,
485      eEncodingUint,
486      eFormatHex,
487      {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
488       LLDB_INVALID_REGNUM},
489      nullptr,
490      nullptr,
491     },
492     {"pc",
493      nullptr,
494      8,
495      0,
496      eEncodingUint,
497      eFormatHex,
498      {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
499       LLDB_INVALID_REGNUM},
500      nullptr,
501      nullptr,
502     },
503 };
504 
505 static const uint32_t k_num_register_infos =
506     llvm::array_lengthof(g_register_infos_mips64);
507 
508 const lldb_private::RegisterInfo *
509 ABISysV_mips64::GetRegisterInfoArray(uint32_t &count) {
510   count = k_num_register_infos;
511   return g_register_infos_mips64;
512 }
513 
514 size_t ABISysV_mips64::GetRedZoneSize() const { return 0; }
515 
516 // Static Functions
517 
518 ABISP
519 ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
520   if (arch.GetTriple().isMIPS64())
521     return ABISP(
522         new ABISysV_mips64(std::move(process_sp), MakeMCRegisterInfo(arch)));
523   return ABISP();
524 }
525 
526 bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp,
527                                         addr_t func_addr, addr_t return_addr,
528                                         llvm::ArrayRef<addr_t> args) const {
529   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
530 
531   if (log) {
532     StreamString s;
533     s.Printf("ABISysV_mips64::PrepareTrivialCall (tid = 0x%" PRIx64
534              ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
535              ", return_addr = 0x%" PRIx64,
536              thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
537              (uint64_t)return_addr);
538 
539     for (size_t i = 0; i < args.size(); ++i)
540       s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
541     s.PutCString(")");
542     log->PutString(s.GetString());
543   }
544 
545   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
546   if (!reg_ctx)
547     return false;
548 
549   const RegisterInfo *reg_info = nullptr;
550 
551   if (args.size() > 8) // TODO handle more than 8 arguments
552     return false;
553 
554   for (size_t i = 0; i < args.size(); ++i) {
555     reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
556                                         LLDB_REGNUM_GENERIC_ARG1 + i);
557     LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
558               args[i], reg_info->name);
559     if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
560       return false;
561   }
562 
563   // First, align the SP
564 
565   LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64,
566             (uint64_t)sp, (uint64_t)(sp & ~0xfull));
567 
568   sp &= ~(0xfull); // 16-byte alignment
569 
570   Status error;
571   const RegisterInfo *pc_reg_info =
572       reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
573   const RegisterInfo *sp_reg_info =
574       reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
575   const RegisterInfo *ra_reg_info =
576       reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
577   const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
578   const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
579 
580   LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
581 
582   /* Write r0 with 0, in case we are stopped in syscall,
583    * such setting prevents automatic decrement of the PC.
584    * This clears the bug 23659 for MIPS.
585   */
586   if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
587     return false;
588 
589   LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
590 
591   // Set "sp" to the requested value
592   if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
593     return false;
594 
595   LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
596 
597   // Set "ra" to the return address
598   if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
599     return false;
600 
601   LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
602 
603   // Set pc to the address of the called function.
604   if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
605     return false;
606 
607   LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
608 
609   // All callers of position independent functions must place the address of
610   // the called function in t9 (r25)
611   if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
612     return false;
613 
614   return true;
615 }
616 
617 bool ABISysV_mips64::GetArgumentValues(Thread &thread,
618                                        ValueList &values) const {
619   return false;
620 }
621 
622 Status ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
623                                             lldb::ValueObjectSP &new_value_sp) {
624   Status error;
625   if (!new_value_sp) {
626     error.SetErrorString("Empty value object for return value.");
627     return error;
628   }
629 
630   CompilerType compiler_type = new_value_sp->GetCompilerType();
631   if (!compiler_type) {
632     error.SetErrorString("Null clang type for return value.");
633     return error;
634   }
635 
636   Thread *thread = frame_sp->GetThread().get();
637 
638   RegisterContext *reg_ctx = thread->GetRegisterContext().get();
639 
640   if (!reg_ctx)
641     error.SetErrorString("no registers are available");
642 
643   DataExtractor data;
644   Status data_error;
645   size_t num_bytes = new_value_sp->GetData(data, data_error);
646   if (data_error.Fail()) {
647     error.SetErrorStringWithFormat(
648         "Couldn't convert return value to raw data: %s",
649         data_error.AsCString());
650     return error;
651   }
652 
653   const uint32_t type_flags = compiler_type.GetTypeInfo(nullptr);
654 
655   if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
656     if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
657       lldb::offset_t offset = 0;
658 
659       if (num_bytes <= 16) {
660         const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
661         if (num_bytes <= 8) {
662           uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
663 
664           if (!reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
665             error.SetErrorString("failed to write register r2");
666         } else {
667           uint64_t raw_value = data.GetMaxU64(&offset, 8);
668           if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
669             const RegisterInfo *r3_info =
670                 reg_ctx->GetRegisterInfoByName("r3", 0);
671             raw_value = data.GetMaxU64(&offset, num_bytes - offset);
672 
673             if (!reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
674               error.SetErrorString("failed to write register r3");
675           } else
676             error.SetErrorString("failed to write register r2");
677         }
678       } else {
679         error.SetErrorString("We don't support returning longer than 128 bit "
680                              "integer values at present.");
681       }
682     } else if (type_flags & eTypeIsFloat) {
683       error.SetErrorString("TODO: Handle Float Types.");
684     }
685   } else if (type_flags & eTypeIsVector) {
686     error.SetErrorString("returning vector values are not supported");
687   }
688 
689   return error;
690 }
691 
692 ValueObjectSP ABISysV_mips64::GetReturnValueObjectSimple(
693     Thread &thread, CompilerType &return_compiler_type) const {
694   ValueObjectSP return_valobj_sp;
695   return return_valobj_sp;
696 }
697 
698 ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
699     Thread &thread, CompilerType &return_compiler_type) const {
700   ValueObjectSP return_valobj_sp;
701   Value value;
702   Status error;
703 
704   ExecutionContext exe_ctx(thread.shared_from_this());
705   if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
706     return return_valobj_sp;
707 
708   value.SetCompilerType(return_compiler_type);
709 
710   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
711   if (!reg_ctx)
712     return return_valobj_sp;
713 
714   Target *target = exe_ctx.GetTargetPtr();
715   const ArchSpec target_arch = target->GetArchitecture();
716   ByteOrder target_byte_order = target_arch.GetByteOrder();
717   llvm::Optional<uint64_t> byte_size =
718       return_compiler_type.GetByteSize(&thread);
719   if (!byte_size)
720     return return_valobj_sp;
721   const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
722   uint32_t fp_flag =
723       target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
724 
725   const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
726   const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
727 
728   if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
729     value.SetValueType(Value::ValueType::Scalar);
730 
731     bool success = false;
732     if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
733       // Extract the register context so we can read arguments from registers
734       // In MIPS register "r2" (v0) holds the integer function return values
735 
736       uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
737 
738       const bool is_signed = (type_flags & eTypeIsSigned) != 0;
739       switch (*byte_size) {
740       default:
741         break;
742 
743       case sizeof(uint64_t):
744         if (is_signed)
745           value.GetScalar() = (int64_t)(raw_value);
746         else
747           value.GetScalar() = (uint64_t)(raw_value);
748         success = true;
749         break;
750 
751       case sizeof(uint32_t):
752         if (is_signed)
753           value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
754         else
755           value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
756         success = true;
757         break;
758 
759       case sizeof(uint16_t):
760         if (is_signed)
761           value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
762         else
763           value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
764         success = true;
765         break;
766 
767       case sizeof(uint8_t):
768         if (is_signed)
769           value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
770         else
771           value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
772         success = true;
773         break;
774       }
775     } else if (type_flags & eTypeIsFloat) {
776       if (type_flags & eTypeIsComplex) {
777         // Don't handle complex yet.
778       } else if (IsSoftFloat(fp_flag)) {
779         uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
780         switch (*byte_size) {
781         case 4:
782           value.GetScalar() = *((float *)(&raw_value));
783           success = true;
784           break;
785         case 8:
786           value.GetScalar() = *((double *)(&raw_value));
787           success = true;
788           break;
789         case 16:
790           uint64_t result[2];
791           if (target_byte_order == eByteOrderLittle) {
792             result[0] = raw_value;
793             result[1] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);
794             value.GetScalar() = *((long double *)(result));
795           } else {
796             result[0] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);
797             result[1] = raw_value;
798             value.GetScalar() = *((long double *)(result));
799           }
800           success = true;
801           break;
802         }
803 
804       } else {
805         if (*byte_size <= sizeof(long double)) {
806           const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
807 
808           RegisterValue f0_value;
809           DataExtractor f0_data;
810 
811           reg_ctx->ReadRegister(f0_info, f0_value);
812 
813           f0_value.GetData(f0_data);
814 
815           lldb::offset_t offset = 0;
816           if (*byte_size == sizeof(float)) {
817             value.GetScalar() = (float)f0_data.GetFloat(&offset);
818             success = true;
819           } else if (*byte_size == sizeof(double)) {
820             value.GetScalar() = (double)f0_data.GetDouble(&offset);
821             success = true;
822           } else if (*byte_size == sizeof(long double)) {
823             const RegisterInfo *f2_info =
824                 reg_ctx->GetRegisterInfoByName("f2", 0);
825             RegisterValue f2_value;
826             DataExtractor f2_data;
827             reg_ctx->ReadRegister(f2_info, f2_value);
828             DataExtractor *copy_from_extractor = nullptr;
829             DataBufferSP data_sp(new DataBufferHeap(16, 0));
830             DataExtractor return_ext(
831                 data_sp, target_byte_order,
832                 target->GetArchitecture().GetAddressByteSize());
833 
834             if (target_byte_order == eByteOrderLittle) {
835               copy_from_extractor = &f0_data;
836               copy_from_extractor->CopyByteOrderedData(
837                   0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
838               f2_value.GetData(f2_data);
839               copy_from_extractor = &f2_data;
840               copy_from_extractor->CopyByteOrderedData(
841                   0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
842                   target_byte_order);
843             } else {
844               copy_from_extractor = &f0_data;
845               copy_from_extractor->CopyByteOrderedData(
846                   0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
847                   target_byte_order);
848               f2_value.GetData(f2_data);
849               copy_from_extractor = &f2_data;
850               copy_from_extractor->CopyByteOrderedData(
851                   0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
852             }
853 
854             return_valobj_sp = ValueObjectConstResult::Create(
855                 &thread, return_compiler_type, ConstString(""), return_ext);
856             return return_valobj_sp;
857           }
858         }
859       }
860     }
861 
862     if (success)
863       return_valobj_sp = ValueObjectConstResult::Create(
864           thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
865   } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass ||
866              type_flags & eTypeIsVector) {
867     // Any structure of up to 16 bytes in size is returned in the registers.
868     if (*byte_size <= 16) {
869       DataBufferSP data_sp(new DataBufferHeap(16, 0));
870       DataExtractor return_ext(data_sp, target_byte_order,
871                                target->GetArchitecture().GetAddressByteSize());
872 
873       RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value;
874       // Tracks how much bytes of r2 and r3 registers we've consumed so far
875       uint32_t integer_bytes = 0;
876 
877       // True if return values are in FP return registers.
878       bool use_fp_regs = false;
879       // True if we found any non floating point field in structure.
880       bool found_non_fp_field = false;
881       // True if return values are in r2 register.
882       bool use_r2 = false;
883       // True if return values are in r3 register.
884       bool use_r3 = false;
885       // True if the result is copied into our data buffer
886       bool sucess = false;
887       std::string name;
888       bool is_complex;
889       uint32_t count;
890       const uint32_t num_children = return_compiler_type.GetNumFields();
891 
892       // A structure consisting of one or two FP values (and nothing else) will
893       // be returned in the two FP return-value registers i.e fp0 and fp2.
894       if (num_children <= 2) {
895         uint64_t field_bit_offset = 0;
896 
897         // Check if this structure contains only floating point fields
898         for (uint32_t idx = 0; idx < num_children; idx++) {
899           CompilerType field_compiler_type =
900               return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset,
901                                                    nullptr, nullptr);
902 
903           if (field_compiler_type.IsFloatingPointType(count, is_complex))
904             use_fp_regs = true;
905           else
906             found_non_fp_field = true;
907         }
908 
909         if (use_fp_regs && !found_non_fp_field) {
910           // We have one or two FP-only values in this structure. Get it from
911           // f0/f2 registers.
912           DataExtractor f0_data, f1_data, f2_data;
913           const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
914           const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
915           const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0);
916 
917           reg_ctx->ReadRegister(f0_info, f0_value);
918           reg_ctx->ReadRegister(f2_info, f2_value);
919 
920           f0_value.GetData(f0_data);
921 
922           for (uint32_t idx = 0; idx < num_children; idx++) {
923             CompilerType field_compiler_type =
924                 return_compiler_type.GetFieldAtIndex(
925                     idx, name, &field_bit_offset, nullptr, nullptr);
926             llvm::Optional<uint64_t> field_byte_width =
927                 field_compiler_type.GetByteSize(&thread);
928             if (!field_byte_width)
929               return return_valobj_sp;
930 
931             DataExtractor *copy_from_extractor = nullptr;
932             uint64_t return_value[2];
933             offset_t offset = 0;
934 
935             if (idx == 0) {
936               // This case is for long double type.
937               if (*field_byte_width == 16) {
938 
939                 // If structure contains long double type, then it is returned
940                 // in fp0/fp1 registers.
941                 if (target_byte_order == eByteOrderLittle) {
942                   return_value[0] = f0_data.GetU64(&offset);
943                   reg_ctx->ReadRegister(f1_info, f1_value);
944                   f1_value.GetData(f1_data);
945                   offset = 0;
946                   return_value[1] = f1_data.GetU64(&offset);
947                 } else {
948                   return_value[1] = f0_data.GetU64(&offset);
949                   reg_ctx->ReadRegister(f1_info, f1_value);
950                   f1_value.GetData(f1_data);
951                   offset = 0;
952                   return_value[0] = f1_data.GetU64(&offset);
953                 }
954 
955                 f0_data.SetData(return_value, *field_byte_width,
956                                 target_byte_order);
957               }
958               copy_from_extractor = &f0_data; // This is in f0, copy from
959                                               // register to our result
960                                               // structure
961             } else {
962               f2_value.GetData(f2_data);
963               // This is in f2, copy from register to our result structure
964               copy_from_extractor = &f2_data;
965             }
966 
967             // Sanity check to avoid crash
968             if (!copy_from_extractor ||
969                 *field_byte_width > copy_from_extractor->GetByteSize())
970               return return_valobj_sp;
971 
972             // copy the register contents into our data buffer
973             copy_from_extractor->CopyByteOrderedData(
974                 0, *field_byte_width,
975                 data_sp->GetBytes() + (field_bit_offset / 8), *field_byte_width,
976                 target_byte_order);
977           }
978 
979           // The result is in our data buffer.  Create a variable object out of
980           // it
981           return_valobj_sp = ValueObjectConstResult::Create(
982               &thread, return_compiler_type, ConstString(""), return_ext);
983 
984           return return_valobj_sp;
985         }
986       }
987 
988       // If we reach here, it means this structure either contains more than
989       // two fields or it contains at least one non floating point type. In
990       // that case, all fields are returned in GP return registers.
991       for (uint32_t idx = 0; idx < num_children; idx++) {
992         uint64_t field_bit_offset = 0;
993         bool is_signed;
994         uint32_t padding;
995 
996         CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
997             idx, name, &field_bit_offset, nullptr, nullptr);
998         llvm::Optional<uint64_t> field_byte_width =
999             field_compiler_type.GetByteSize(&thread);
1000 
1001         // if we don't know the size of the field (e.g. invalid type), just
1002         // bail out
1003         if (!field_byte_width || *field_byte_width == 0)
1004           break;
1005 
1006         uint32_t field_byte_offset = field_bit_offset / 8;
1007 
1008         if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
1009             field_compiler_type.IsPointerType() ||
1010             field_compiler_type.IsFloatingPointType(count, is_complex)) {
1011           padding = field_byte_offset - integer_bytes;
1012 
1013           if (integer_bytes < 8) {
1014             // We have not yet consumed r2 completely.
1015             if (integer_bytes + *field_byte_width + padding <= 8) {
1016               // This field fits in r2, copy its value from r2 to our result
1017               // structure
1018               integer_bytes = integer_bytes + *field_byte_width +
1019                               padding; // Increase the consumed bytes.
1020               use_r2 = true;
1021             } else {
1022               // There isn't enough space left in r2 for this field, so this
1023               // will be in r3.
1024               integer_bytes = integer_bytes + *field_byte_width +
1025                               padding; // Increase the consumed bytes.
1026               use_r3 = true;
1027             }
1028           }
1029           // We already have consumed at-least 8 bytes that means r2 is done,
1030           // and this field will be in r3. Check if this field can fit in r3.
1031           else if (integer_bytes + *field_byte_width + padding <= 16) {
1032             integer_bytes = integer_bytes + *field_byte_width + padding;
1033             use_r3 = true;
1034           } else {
1035             // There isn't any space left for this field, this should not
1036             // happen as we have already checked the overall size is not
1037             // greater than 16 bytes. For now, return a nullptr return value
1038             // object.
1039             return return_valobj_sp;
1040           }
1041         }
1042       }
1043       // Vector types up to 16 bytes are returned in GP return registers
1044       if (type_flags & eTypeIsVector) {
1045         if (*byte_size <= 8)
1046           use_r2 = true;
1047         else {
1048           use_r2 = true;
1049           use_r3 = true;
1050         }
1051       }
1052 
1053       if (use_r2) {
1054         reg_ctx->ReadRegister(r2_info, r2_value);
1055 
1056         const size_t bytes_copied = r2_value.GetAsMemoryData(
1057             r2_info, data_sp->GetBytes(), r2_info->byte_size, target_byte_order,
1058             error);
1059         if (bytes_copied != r2_info->byte_size)
1060           return return_valobj_sp;
1061         sucess = true;
1062       }
1063       if (use_r3) {
1064         reg_ctx->ReadRegister(r3_info, r3_value);
1065         const size_t bytes_copied = r3_value.GetAsMemoryData(
1066             r3_info, data_sp->GetBytes() + r2_info->byte_size,
1067             r3_info->byte_size, target_byte_order, error);
1068 
1069         if (bytes_copied != r3_info->byte_size)
1070           return return_valobj_sp;
1071         sucess = true;
1072       }
1073       if (sucess) {
1074         // The result is in our data buffer.  Create a variable object out of
1075         // it
1076         return_valobj_sp = ValueObjectConstResult::Create(
1077             &thread, return_compiler_type, ConstString(""), return_ext);
1078       }
1079       return return_valobj_sp;
1080     }
1081 
1082     // Any structure/vector greater than 16 bytes in size is returned in
1083     // memory. The pointer to that memory is returned in r2.
1084     uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
1085         reg_ctx->GetRegisterInfoByName("r2", 0), 0);
1086 
1087     // We have got the address. Create a memory object out of it
1088     return_valobj_sp = ValueObjectMemory::Create(
1089         &thread, "", Address(mem_address, nullptr), return_compiler_type);
1090   }
1091   return return_valobj_sp;
1092 }
1093 
1094 bool ABISysV_mips64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
1095   unwind_plan.Clear();
1096   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1097 
1098   UnwindPlan::RowSP row(new UnwindPlan::Row);
1099 
1100   // Our Call Frame Address is the stack pointer value
1101   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
1102 
1103   // The previous PC is in the RA
1104   row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
1105   unwind_plan.AppendRow(row);
1106 
1107   // All other registers are the same.
1108 
1109   unwind_plan.SetSourceName("mips64 at-func-entry default");
1110   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1111   unwind_plan.SetReturnAddressRegister(dwarf_r31);
1112   return true;
1113 }
1114 
1115 bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
1116   unwind_plan.Clear();
1117   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1118 
1119   UnwindPlan::RowSP row(new UnwindPlan::Row);
1120 
1121   row->SetUnspecifiedRegistersAreUndefined(true);
1122   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
1123 
1124   row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
1125 
1126   unwind_plan.AppendRow(row);
1127   unwind_plan.SetSourceName("mips64 default unwind plan");
1128   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1129   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1130   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1131   return true;
1132 }
1133 
1134 bool ABISysV_mips64::RegisterIsVolatile(const RegisterInfo *reg_info) {
1135   return !RegisterIsCalleeSaved(reg_info);
1136 }
1137 
1138 bool ABISysV_mips64::IsSoftFloat(uint32_t fp_flag) const {
1139   return (fp_flag == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1140 }
1141 
1142 bool ABISysV_mips64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1143   if (reg_info) {
1144     // Preserved registers are :
1145     // r16-r23, r28, r29, r30, r31
1146 
1147     int reg = ((reg_info->byte_offset) / 8);
1148 
1149     bool save = (reg >= 16) && (reg <= 23);
1150     save |= (reg >= 28) && (reg <= 31);
1151 
1152     return save;
1153   }
1154   return false;
1155 }
1156 
1157 void ABISysV_mips64::Initialize() {
1158   PluginManager::RegisterPlugin(
1159       GetPluginNameStatic(), "System V ABI for mips64 targets", CreateInstance);
1160 }
1161 
1162 void ABISysV_mips64::Terminate() {
1163   PluginManager::UnregisterPlugin(CreateInstance);
1164 }
1165