1 //===-- ABISysV_mips.cpp ----------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "ABISysV_mips.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/Triple.h"
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"
33 using namespace lldb_private;
76 static const RegisterInfo g_register_infos[] = {
77 // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME
78 // DWARF GENERIC PROCESS PLUGINS
79 // LLDB NATIVE VALUE REGS INVALIDATE REGS
80 // ======== ====== == === ============= =========== ============
81 // ============== ============ =================
82 // =================== ========== =================
89 {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
101 {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
102 LLDB_INVALID_REGNUM},
113 {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
114 LLDB_INVALID_REGNUM},
125 {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
126 LLDB_INVALID_REGNUM},
137 {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
138 LLDB_INVALID_REGNUM},
149 {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
150 LLDB_INVALID_REGNUM},
161 {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
162 LLDB_INVALID_REGNUM},
173 {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
174 LLDB_INVALID_REGNUM},
185 {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
186 LLDB_INVALID_REGNUM},
197 {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
198 LLDB_INVALID_REGNUM},
209 {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
210 LLDB_INVALID_REGNUM},
221 {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
222 LLDB_INVALID_REGNUM},
233 {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
234 LLDB_INVALID_REGNUM},
245 {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
246 LLDB_INVALID_REGNUM},
257 {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
258 LLDB_INVALID_REGNUM},
269 {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
270 LLDB_INVALID_REGNUM},
281 {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
282 LLDB_INVALID_REGNUM},
293 {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
294 LLDB_INVALID_REGNUM},
305 {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
306 LLDB_INVALID_REGNUM},
317 {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
318 LLDB_INVALID_REGNUM},
329 {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
330 LLDB_INVALID_REGNUM},
341 {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
342 LLDB_INVALID_REGNUM},
353 {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
354 LLDB_INVALID_REGNUM},
365 {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
366 LLDB_INVALID_REGNUM},
377 {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
378 LLDB_INVALID_REGNUM},
389 {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
390 LLDB_INVALID_REGNUM},
401 {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
402 LLDB_INVALID_REGNUM},
413 {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
414 LLDB_INVALID_REGNUM},
425 {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
426 LLDB_INVALID_REGNUM},
437 {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
438 LLDB_INVALID_REGNUM},
449 {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
450 LLDB_INVALID_REGNUM},
461 {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
462 LLDB_INVALID_REGNUM},
473 {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
474 LLDB_INVALID_REGNUM},
485 {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
486 LLDB_INVALID_REGNUM},
497 {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
498 LLDB_INVALID_REGNUM},
509 {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
510 LLDB_INVALID_REGNUM},
521 {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
522 LLDB_INVALID_REGNUM},
533 {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
534 LLDB_INVALID_REGNUM},
541 static const uint32_t k_num_register_infos =
542 llvm::array_lengthof(g_register_infos);
544 const lldb_private::RegisterInfo *
545 ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
546 count = k_num_register_infos;
547 return g_register_infos;
550 size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
555 ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
556 const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
557 if ((arch_type == llvm::Triple::mips) ||
558 (arch_type == llvm::Triple::mipsel)) {
559 return ABISP(new ABISysV_mips(process_sp));
564 bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
565 addr_t func_addr, addr_t return_addr,
566 llvm::ArrayRef<addr_t> args) const {
567 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
571 s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
572 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
573 ", return_addr = 0x%" PRIx64,
574 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
575 (uint64_t)return_addr);
577 for (size_t i = 0; i < args.size(); ++i)
578 s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
580 log->PutString(s.GetString());
583 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
587 const RegisterInfo *reg_info = nullptr;
589 RegisterValue reg_value;
591 // Argument registers
592 const char *reg_names[] = {"r4", "r5", "r6", "r7"};
594 llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
596 // Write arguments to registers
597 for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) {
601 reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
602 LLDB_REGNUM_GENERIC_ARG1 + i);
604 log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
605 args[i], reg_info->name);
607 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
613 // If we have more than 4 arguments --Spill onto the stack
615 // No of arguments to go on stack
616 size_t num_stack_regs = args.size();
618 // Allocate needed space for args on the stack
619 sp -= (num_stack_regs * 4);
621 // Keep the stack 8 byte aligned
622 sp &= ~(8ull - 1ull);
624 // just using arg1 to get the right size
625 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
626 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
628 addr_t arg_pos = sp + 16;
631 for (; ai != ae; ++ai) {
632 reg_value.SetUInt32(*ai);
634 log->Printf("About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
635 i + 1, args[i], arg_pos);
638 ->WriteRegisterValueToMemory(reg_info, arg_pos,
639 reg_info->byte_size, reg_value)
642 arg_pos += reg_info->byte_size;
648 const RegisterInfo *pc_reg_info =
649 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
650 const RegisterInfo *sp_reg_info =
651 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
652 const RegisterInfo *ra_reg_info =
653 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
654 const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
655 const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
658 log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0);
660 /* Write r0 with 0, in case we are stopped in syscall,
661 * such setting prevents automatic decrement of the PC.
662 * This clears the bug 23659 for MIPS.
664 if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
668 log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
670 // Set "sp" to the requested value
671 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
675 log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
677 // Set "ra" to the return address
678 if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
682 log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
684 // Set pc to the address of the called function.
685 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
689 log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
691 // All callers of position independent functions must place the address of
692 // the called function in t9 (r25)
693 if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
699 bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
703 Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
704 lldb::ValueObjectSP &new_value_sp) {
707 error.SetErrorString("Empty value object for return value.");
711 CompilerType compiler_type = new_value_sp->GetCompilerType();
712 if (!compiler_type) {
713 error.SetErrorString("Null clang type for return value.");
717 Thread *thread = frame_sp->GetThread().get();
723 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
725 bool set_it_simple = false;
726 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
727 compiler_type.IsPointerType()) {
730 size_t num_bytes = new_value_sp->GetData(data, data_error);
731 if (data_error.Fail()) {
732 error.SetErrorStringWithFormat(
733 "Couldn't convert return value to raw data: %s",
734 data_error.AsCString());
738 lldb::offset_t offset = 0;
739 if (num_bytes <= 8) {
740 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
741 if (num_bytes <= 4) {
742 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
744 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
745 set_it_simple = true;
747 uint32_t raw_value = data.GetMaxU32(&offset, 4);
749 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
750 const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
751 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
753 if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
754 set_it_simple = true;
758 error.SetErrorString("We don't support returning longer than 64 bit "
759 "integer values at present.");
761 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
763 error.SetErrorString(
764 "We don't support returning complex values at present");
766 error.SetErrorString(
767 "We don't support returning float values at present");
771 error.SetErrorString(
772 "We only support setting simple integer return types at present.");
777 ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
778 Thread &thread, CompilerType &return_compiler_type) const {
779 ValueObjectSP return_valobj_sp;
780 return return_valobj_sp;
783 ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
784 Thread &thread, CompilerType &return_compiler_type) const {
785 ValueObjectSP return_valobj_sp;
788 if (!return_compiler_type)
789 return return_valobj_sp;
791 ExecutionContext exe_ctx(thread.shared_from_this());
792 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
793 return return_valobj_sp;
795 Target *target = exe_ctx.GetTargetPtr();
796 const ArchSpec target_arch = target->GetArchitecture();
797 ByteOrder target_byte_order = target_arch.GetByteOrder();
798 value.SetCompilerType(return_compiler_type);
800 target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
802 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
804 return return_valobj_sp;
806 bool is_signed = false;
807 bool is_complex = false;
810 // In MIPS register "r2" (v0) holds the integer function return values
811 const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
812 llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
814 return return_valobj_sp;
815 if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
816 switch (*bit_width) {
818 return return_valobj_sp;
820 const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
822 raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
823 raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
827 value.GetScalar() = (int64_t)raw_value;
829 value.GetScalar() = (uint64_t)raw_value;
833 value.GetScalar() = (int32_t)(
834 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
836 value.GetScalar() = (uint32_t)(
837 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
841 value.GetScalar() = (int16_t)(
842 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
844 value.GetScalar() = (uint16_t)(
845 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
849 value.GetScalar() = (int8_t)(
850 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
852 value.GetScalar() = (uint8_t)(
853 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
856 } else if (return_compiler_type.IsPointerType()) {
858 thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
860 value.GetScalar() = ptr;
861 } else if (return_compiler_type.IsAggregateType()) {
862 // Structure/Vector is always passed in memory and pointer to that memory
864 uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
865 reg_ctx->GetRegisterInfoByName("r2", 0), 0);
866 // We have got the address. Create a memory object out of it
867 return_valobj_sp = ValueObjectMemory::Create(
868 &thread, "", Address(mem_address, nullptr), return_compiler_type);
869 return return_valobj_sp;
870 } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
871 if (IsSoftFloat(fp_flag)) {
872 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
873 if (count != 1 && is_complex)
874 return return_valobj_sp;
875 switch (*bit_width) {
877 return return_valobj_sp;
879 static_assert(sizeof(float) == sizeof(uint32_t), "");
880 value.GetScalar() = *((float *)(&raw_value));
883 static_assert(sizeof(double) == sizeof(uint64_t), "");
884 const RegisterInfo *r3_reg_info =
885 reg_ctx->GetRegisterInfoByName("r3", 0);
886 if (target_byte_order == eByteOrderLittle)
888 ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
891 raw_value = (raw_value << 32) |
892 reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
893 value.GetScalar() = *((double *)(&raw_value));
899 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
900 RegisterValue f0_value;
901 DataExtractor f0_data;
902 reg_ctx->ReadRegister(f0_info, f0_value);
903 f0_value.GetData(f0_data);
904 lldb::offset_t offset = 0;
906 if (count == 1 && !is_complex) {
907 switch (*bit_width) {
909 return return_valobj_sp;
911 static_assert(sizeof(double) == sizeof(uint64_t), "");
912 const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
913 RegisterValue f1_value;
914 DataExtractor f1_data;
915 reg_ctx->ReadRegister(f1_info, f1_value);
916 DataExtractor *copy_from_extractor = nullptr;
917 DataBufferSP data_sp(new DataBufferHeap(8, 0));
918 DataExtractor return_ext(
919 data_sp, target_byte_order,
920 target->GetArchitecture().GetAddressByteSize());
922 if (target_byte_order == eByteOrderLittle) {
923 copy_from_extractor = &f0_data;
924 copy_from_extractor->CopyByteOrderedData(
925 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
926 f1_value.GetData(f1_data);
927 copy_from_extractor = &f1_data;
928 copy_from_extractor->CopyByteOrderedData(
929 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
931 copy_from_extractor = &f0_data;
932 copy_from_extractor->CopyByteOrderedData(
933 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
934 f1_value.GetData(f1_data);
935 copy_from_extractor = &f1_data;
936 copy_from_extractor->CopyByteOrderedData(
937 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
939 value.GetScalar() = (double)return_ext.GetDouble(&offset);
943 static_assert(sizeof(float) == sizeof(uint32_t), "");
944 value.GetScalar() = (float)f0_data.GetFloat(&offset);
950 return return_valobj_sp;
955 return return_valobj_sp;
958 // If we get here, we have a valid Value, so make our ValueObject out of it:
960 return_valobj_sp = ValueObjectConstResult::Create(
961 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
962 return return_valobj_sp;
965 bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
967 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
969 UnwindPlan::RowSP row(new UnwindPlan::Row);
971 // Our Call Frame Address is the stack pointer value
972 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
974 // The previous PC is in the RA
975 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
976 unwind_plan.AppendRow(row);
978 // All other registers are the same.
980 unwind_plan.SetSourceName("mips at-func-entry default");
981 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
982 unwind_plan.SetReturnAddressRegister(dwarf_r31);
986 bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
988 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
990 UnwindPlan::RowSP row(new UnwindPlan::Row);
992 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
994 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
996 unwind_plan.AppendRow(row);
997 unwind_plan.SetSourceName("mips default unwind plan");
998 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
999 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1003 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
1004 return !RegisterIsCalleeSaved(reg_info);
1007 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
1008 return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1011 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1013 // Preserved registers are :
1014 // r16-r23, r28, r29, r30, r31
1015 const char *name = reg_info->name;
1017 if (name[0] == 'r') {
1020 if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
1021 name[2] == '9') // r16-r19
1022 return name[3] == '\0';
1025 if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
1026 name[2] == '3' // r20-r23
1027 || name[2] == '8' || name[2] == '9') // r28 and r29
1028 return name[3] == '\0';
1031 if (name[2] == '0' || name[2] == '1') // r30 and r31
1032 return name[3] == '\0';
1036 if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
1038 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
1040 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
1042 if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
1049 void ABISysV_mips::Initialize() {
1050 PluginManager::RegisterPlugin(
1051 GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1054 void ABISysV_mips::Terminate() {
1055 PluginManager::UnregisterPlugin(CreateInstance);
1058 lldb_private::ConstString ABISysV_mips::GetPluginNameStatic() {
1059 static ConstString g_name("sysv-mips");
1063 // PluginInterface protocol
1065 lldb_private::ConstString ABISysV_mips::GetPluginName() {
1066 return GetPluginNameStatic();
1069 uint32_t ABISysV_mips::GetPluginVersion() { return 1; }