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 
33 using namespace lldb;
34 using namespace lldb_private;
35 
36 LLDB_PLUGIN_DEFINE(ABISysV_mips)
37 
38 enum dwarf_regnums {
39   dwarf_r0 = 0,
40   dwarf_r1,
41   dwarf_r2,
42   dwarf_r3,
43   dwarf_r4,
44   dwarf_r5,
45   dwarf_r6,
46   dwarf_r7,
47   dwarf_r8,
48   dwarf_r9,
49   dwarf_r10,
50   dwarf_r11,
51   dwarf_r12,
52   dwarf_r13,
53   dwarf_r14,
54   dwarf_r15,
55   dwarf_r16,
56   dwarf_r17,
57   dwarf_r18,
58   dwarf_r19,
59   dwarf_r20,
60   dwarf_r21,
61   dwarf_r22,
62   dwarf_r23,
63   dwarf_r24,
64   dwarf_r25,
65   dwarf_r26,
66   dwarf_r27,
67   dwarf_r28,
68   dwarf_r29,
69   dwarf_r30,
70   dwarf_r31,
71   dwarf_sr,
72   dwarf_lo,
73   dwarf_hi,
74   dwarf_bad,
75   dwarf_cause,
76   dwarf_pc
77 };
78 
79 static const RegisterInfo g_register_infos[] = {
80     //  NAME      ALT    SZ OFF ENCODING        FORMAT         EH_FRAME
81     //  DWARF                   GENERIC                     PROCESS PLUGINS
82     //  LLDB NATIVE            VALUE REGS  INVALIDATE REGS
83     //  ========  ======  == === =============  ===========    ============
84     //  ==============          ============                =================
85     //  ===================     ========== =================
86     {"r0",
87      "zero",
88      4,
89      0,
90      eEncodingUint,
91      eFormatHex,
92      {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
93       LLDB_INVALID_REGNUM},
94      nullptr,
95      nullptr,
96     },
97     {"r1",
98      "AT",
99      4,
100      0,
101      eEncodingUint,
102      eFormatHex,
103      {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
104       LLDB_INVALID_REGNUM},
105      nullptr,
106      nullptr,
107     },
108     {"r2",
109      "v0",
110      4,
111      0,
112      eEncodingUint,
113      eFormatHex,
114      {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
115       LLDB_INVALID_REGNUM},
116      nullptr,
117      nullptr,
118     },
119     {"r3",
120      "v1",
121      4,
122      0,
123      eEncodingUint,
124      eFormatHex,
125      {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
126       LLDB_INVALID_REGNUM},
127      nullptr,
128      nullptr,
129     },
130     {"r4",
131      nullptr,
132      4,
133      0,
134      eEncodingUint,
135      eFormatHex,
136      {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
137       LLDB_INVALID_REGNUM},
138      nullptr,
139      nullptr,
140     },
141     {"r5",
142      nullptr,
143      4,
144      0,
145      eEncodingUint,
146      eFormatHex,
147      {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
148       LLDB_INVALID_REGNUM},
149      nullptr,
150      nullptr,
151     },
152     {"r6",
153      nullptr,
154      4,
155      0,
156      eEncodingUint,
157      eFormatHex,
158      {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
159       LLDB_INVALID_REGNUM},
160      nullptr,
161      nullptr,
162     },
163     {"r7",
164      nullptr,
165      4,
166      0,
167      eEncodingUint,
168      eFormatHex,
169      {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
170       LLDB_INVALID_REGNUM},
171      nullptr,
172      nullptr,
173     },
174     {"r8",
175      "arg5",
176      4,
177      0,
178      eEncodingUint,
179      eFormatHex,
180      {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
181       LLDB_INVALID_REGNUM},
182      nullptr,
183      nullptr,
184     },
185     {"r9",
186      "arg6",
187      4,
188      0,
189      eEncodingUint,
190      eFormatHex,
191      {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
192       LLDB_INVALID_REGNUM},
193      nullptr,
194      nullptr,
195     },
196     {"r10",
197      "arg7",
198      4,
199      0,
200      eEncodingUint,
201      eFormatHex,
202      {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
203       LLDB_INVALID_REGNUM},
204      nullptr,
205      nullptr,
206     },
207     {"r11",
208      "arg8",
209      4,
210      0,
211      eEncodingUint,
212      eFormatHex,
213      {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
214       LLDB_INVALID_REGNUM},
215      nullptr,
216      nullptr,
217     },
218     {"r12",
219      nullptr,
220      4,
221      0,
222      eEncodingUint,
223      eFormatHex,
224      {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
225       LLDB_INVALID_REGNUM},
226      nullptr,
227      nullptr,
228     },
229     {"r13",
230      nullptr,
231      4,
232      0,
233      eEncodingUint,
234      eFormatHex,
235      {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
236       LLDB_INVALID_REGNUM},
237      nullptr,
238      nullptr,
239     },
240     {"r14",
241      nullptr,
242      4,
243      0,
244      eEncodingUint,
245      eFormatHex,
246      {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
247       LLDB_INVALID_REGNUM},
248      nullptr,
249      nullptr,
250     },
251     {"r15",
252      nullptr,
253      4,
254      0,
255      eEncodingUint,
256      eFormatHex,
257      {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
258       LLDB_INVALID_REGNUM},
259      nullptr,
260      nullptr,
261     },
262     {"r16",
263      nullptr,
264      4,
265      0,
266      eEncodingUint,
267      eFormatHex,
268      {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
269       LLDB_INVALID_REGNUM},
270      nullptr,
271      nullptr,
272     },
273     {"r17",
274      nullptr,
275      4,
276      0,
277      eEncodingUint,
278      eFormatHex,
279      {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
280       LLDB_INVALID_REGNUM},
281      nullptr,
282      nullptr,
283     },
284     {"r18",
285      nullptr,
286      4,
287      0,
288      eEncodingUint,
289      eFormatHex,
290      {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
291       LLDB_INVALID_REGNUM},
292      nullptr,
293      nullptr,
294     },
295     {"r19",
296      nullptr,
297      4,
298      0,
299      eEncodingUint,
300      eFormatHex,
301      {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
302       LLDB_INVALID_REGNUM},
303      nullptr,
304      nullptr,
305     },
306     {"r20",
307      nullptr,
308      4,
309      0,
310      eEncodingUint,
311      eFormatHex,
312      {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
313       LLDB_INVALID_REGNUM},
314      nullptr,
315      nullptr,
316     },
317     {"r21",
318      nullptr,
319      4,
320      0,
321      eEncodingUint,
322      eFormatHex,
323      {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
324       LLDB_INVALID_REGNUM},
325      nullptr,
326      nullptr,
327     },
328     {"r22",
329      nullptr,
330      4,
331      0,
332      eEncodingUint,
333      eFormatHex,
334      {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
335       LLDB_INVALID_REGNUM},
336      nullptr,
337      nullptr,
338     },
339     {"r23",
340      nullptr,
341      4,
342      0,
343      eEncodingUint,
344      eFormatHex,
345      {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
346       LLDB_INVALID_REGNUM},
347      nullptr,
348      nullptr,
349     },
350     {"r24",
351      nullptr,
352      4,
353      0,
354      eEncodingUint,
355      eFormatHex,
356      {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
357       LLDB_INVALID_REGNUM},
358      nullptr,
359      nullptr,
360     },
361     {"r25",
362      nullptr,
363      4,
364      0,
365      eEncodingUint,
366      eFormatHex,
367      {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
368       LLDB_INVALID_REGNUM},
369      nullptr,
370      nullptr,
371     },
372     {"r26",
373      nullptr,
374      4,
375      0,
376      eEncodingUint,
377      eFormatHex,
378      {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
379       LLDB_INVALID_REGNUM},
380      nullptr,
381      nullptr,
382     },
383     {"r27",
384      nullptr,
385      4,
386      0,
387      eEncodingUint,
388      eFormatHex,
389      {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
390       LLDB_INVALID_REGNUM},
391      nullptr,
392      nullptr,
393     },
394     {"r28",
395      "gp",
396      4,
397      0,
398      eEncodingUint,
399      eFormatHex,
400      {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
401       LLDB_INVALID_REGNUM},
402      nullptr,
403      nullptr,
404     },
405     {"r29",
406      nullptr,
407      4,
408      0,
409      eEncodingUint,
410      eFormatHex,
411      {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
412       LLDB_INVALID_REGNUM},
413      nullptr,
414      nullptr,
415     },
416     {"r30",
417      nullptr,
418      4,
419      0,
420      eEncodingUint,
421      eFormatHex,
422      {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
423       LLDB_INVALID_REGNUM},
424      nullptr,
425      nullptr,
426     },
427     {"r31",
428      nullptr,
429      4,
430      0,
431      eEncodingUint,
432      eFormatHex,
433      {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
434       LLDB_INVALID_REGNUM},
435      nullptr,
436      nullptr,
437     },
438     {"sr",
439      nullptr,
440      4,
441      0,
442      eEncodingUint,
443      eFormatHex,
444      {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
445       LLDB_INVALID_REGNUM},
446      nullptr,
447      nullptr,
448     },
449     {"lo",
450      nullptr,
451      4,
452      0,
453      eEncodingUint,
454      eFormatHex,
455      {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
456       LLDB_INVALID_REGNUM},
457      nullptr,
458      nullptr,
459     },
460     {"hi",
461      nullptr,
462      4,
463      0,
464      eEncodingUint,
465      eFormatHex,
466      {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
467       LLDB_INVALID_REGNUM},
468      nullptr,
469      nullptr,
470     },
471     {"bad",
472      nullptr,
473      4,
474      0,
475      eEncodingUint,
476      eFormatHex,
477      {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
478       LLDB_INVALID_REGNUM},
479      nullptr,
480      nullptr,
481     },
482     {"cause",
483      nullptr,
484      4,
485      0,
486      eEncodingUint,
487      eFormatHex,
488      {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
489       LLDB_INVALID_REGNUM},
490      nullptr,
491      nullptr,
492     },
493     {"pc",
494      nullptr,
495      4,
496      0,
497      eEncodingUint,
498      eFormatHex,
499      {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
500       LLDB_INVALID_REGNUM},
501      nullptr,
502      nullptr,
503     },
504 };
505 
506 static const uint32_t k_num_register_infos =
507     llvm::array_lengthof(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 < llvm::array_lengthof(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   llvm::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