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