1 //===-- ABISysV_mips.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "ABISysV_mips.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/Triple.h"
15 #include "lldb/Core/Module.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Core/Value.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/Core/ValueObjectMemory.h"
20 #include "lldb/Core/ValueObjectRegister.h"
21 #include "lldb/Symbol/UnwindPlan.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/RegisterContext.h"
24 #include "lldb/Target/StackFrame.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Thread.h"
27 #include "lldb/Utility/ConstString.h"
28 #include "lldb/Utility/DataExtractor.h"
29 #include "lldb/Utility/Log.h"
30 #include "lldb/Utility/RegisterValue.h"
31 #include "lldb/Utility/Status.h"
34 using namespace lldb_private;
77 static const RegisterInfo g_register_infos[] = {
78 // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME
79 // DWARF GENERIC PROCESS PLUGINS
80 // LLDB NATIVE VALUE REGS INVALIDATE REGS
81 // ======== ====== == === ============= =========== ============
82 // ============== ============ =================
83 // =================== ========== =================
90 {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
102 {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
103 LLDB_INVALID_REGNUM},
114 {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
115 LLDB_INVALID_REGNUM},
126 {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
127 LLDB_INVALID_REGNUM},
138 {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
139 LLDB_INVALID_REGNUM},
150 {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
151 LLDB_INVALID_REGNUM},
162 {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
163 LLDB_INVALID_REGNUM},
174 {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
175 LLDB_INVALID_REGNUM},
186 {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
187 LLDB_INVALID_REGNUM},
198 {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
199 LLDB_INVALID_REGNUM},
210 {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
211 LLDB_INVALID_REGNUM},
222 {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
223 LLDB_INVALID_REGNUM},
234 {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
235 LLDB_INVALID_REGNUM},
246 {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
247 LLDB_INVALID_REGNUM},
258 {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
259 LLDB_INVALID_REGNUM},
270 {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
271 LLDB_INVALID_REGNUM},
282 {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
283 LLDB_INVALID_REGNUM},
294 {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
295 LLDB_INVALID_REGNUM},
306 {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
307 LLDB_INVALID_REGNUM},
318 {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
319 LLDB_INVALID_REGNUM},
330 {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
331 LLDB_INVALID_REGNUM},
342 {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
343 LLDB_INVALID_REGNUM},
354 {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
355 LLDB_INVALID_REGNUM},
366 {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
367 LLDB_INVALID_REGNUM},
378 {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
379 LLDB_INVALID_REGNUM},
390 {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
391 LLDB_INVALID_REGNUM},
402 {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
403 LLDB_INVALID_REGNUM},
414 {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
415 LLDB_INVALID_REGNUM},
426 {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
427 LLDB_INVALID_REGNUM},
438 {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
439 LLDB_INVALID_REGNUM},
450 {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
451 LLDB_INVALID_REGNUM},
462 {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
463 LLDB_INVALID_REGNUM},
474 {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
475 LLDB_INVALID_REGNUM},
486 {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
487 LLDB_INVALID_REGNUM},
498 {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
499 LLDB_INVALID_REGNUM},
510 {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
511 LLDB_INVALID_REGNUM},
522 {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
523 LLDB_INVALID_REGNUM},
534 {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
535 LLDB_INVALID_REGNUM},
542 static const uint32_t k_num_register_infos =
543 llvm::array_lengthof(g_register_infos);
545 const lldb_private::RegisterInfo *
546 ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
547 count = k_num_register_infos;
548 return g_register_infos;
551 size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
553 //------------------------------------------------------------------
555 //------------------------------------------------------------------
558 ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
559 const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
560 if ((arch_type == llvm::Triple::mips) ||
561 (arch_type == llvm::Triple::mipsel)) {
562 return ABISP(new ABISysV_mips(process_sp));
567 bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
568 addr_t func_addr, addr_t return_addr,
569 llvm::ArrayRef<addr_t> args) const {
570 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
574 s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
575 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
576 ", return_addr = 0x%" PRIx64,
577 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
578 (uint64_t)return_addr);
580 for (size_t i = 0; i < args.size(); ++i)
581 s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
583 log->PutString(s.GetString());
586 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
590 const RegisterInfo *reg_info = nullptr;
592 RegisterValue reg_value;
594 // Argument registers
595 const char *reg_names[] = {"r4", "r5", "r6", "r7"};
597 llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
599 // Write arguments to registers
600 for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) {
604 reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
605 LLDB_REGNUM_GENERIC_ARG1 + i);
607 log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
608 args[i], reg_info->name);
610 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
616 // If we have more than 4 arguments --Spill onto the stack
618 // No of arguments to go on stack
619 size_t num_stack_regs = args.size();
621 // Allocate needed space for args on the stack
622 sp -= (num_stack_regs * 4);
624 // Keep the stack 8 byte aligned
625 sp &= ~(8ull - 1ull);
627 // just using arg1 to get the right size
628 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
629 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
631 addr_t arg_pos = sp + 16;
634 for (; ai != ae; ++ai) {
635 reg_value.SetUInt32(*ai);
637 log->Printf("About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
638 i + 1, args[i], arg_pos);
641 ->WriteRegisterValueToMemory(reg_info, arg_pos,
642 reg_info->byte_size, reg_value)
645 arg_pos += reg_info->byte_size;
651 const RegisterInfo *pc_reg_info =
652 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
653 const RegisterInfo *sp_reg_info =
654 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
655 const RegisterInfo *ra_reg_info =
656 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
657 const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
658 const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
661 log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0);
663 /* Write r0 with 0, in case we are stopped in syscall,
664 * such setting prevents automatic decrement of the PC.
665 * This clears the bug 23659 for MIPS.
667 if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
671 log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
673 // Set "sp" to the requested value
674 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
678 log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
680 // Set "ra" to the return address
681 if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
685 log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
687 // Set pc to the address of the called function.
688 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
692 log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
694 // All callers of position independent functions must place the address of
695 // the called function in t9 (r25)
696 if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
702 bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
706 Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
707 lldb::ValueObjectSP &new_value_sp) {
710 error.SetErrorString("Empty value object for return value.");
714 CompilerType compiler_type = new_value_sp->GetCompilerType();
715 if (!compiler_type) {
716 error.SetErrorString("Null clang type for return value.");
720 Thread *thread = frame_sp->GetThread().get();
726 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
728 bool set_it_simple = false;
729 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
730 compiler_type.IsPointerType()) {
733 size_t num_bytes = new_value_sp->GetData(data, data_error);
734 if (data_error.Fail()) {
735 error.SetErrorStringWithFormat(
736 "Couldn't convert return value to raw data: %s",
737 data_error.AsCString());
741 lldb::offset_t offset = 0;
742 if (num_bytes <= 8) {
743 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
744 if (num_bytes <= 4) {
745 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
747 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
748 set_it_simple = true;
750 uint32_t raw_value = data.GetMaxU32(&offset, 4);
752 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
753 const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
754 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
756 if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
757 set_it_simple = true;
761 error.SetErrorString("We don't support returning longer than 64 bit "
762 "integer values at present.");
764 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
766 error.SetErrorString(
767 "We don't support returning complex values at present");
769 error.SetErrorString(
770 "We don't support returning float values at present");
774 error.SetErrorString(
775 "We only support setting simple integer return types at present.");
780 ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
781 Thread &thread, CompilerType &return_compiler_type) const {
782 ValueObjectSP return_valobj_sp;
783 return return_valobj_sp;
786 ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
787 Thread &thread, CompilerType &return_compiler_type) const {
788 ValueObjectSP return_valobj_sp;
791 if (!return_compiler_type)
792 return return_valobj_sp;
794 ExecutionContext exe_ctx(thread.shared_from_this());
795 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
796 return return_valobj_sp;
798 Target *target = exe_ctx.GetTargetPtr();
799 const ArchSpec target_arch = target->GetArchitecture();
800 ByteOrder target_byte_order = target_arch.GetByteOrder();
801 value.SetCompilerType(return_compiler_type);
803 target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
805 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
807 return return_valobj_sp;
809 bool is_signed = false;
810 bool is_complex = false;
813 // In MIPS register "r2" (v0) holds the integer function return values
814 const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
815 llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
817 return return_valobj_sp;
818 if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
819 switch (*bit_width) {
821 return return_valobj_sp;
823 const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
825 raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
826 raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
830 value.GetScalar() = (int64_t)raw_value;
832 value.GetScalar() = (uint64_t)raw_value;
836 value.GetScalar() = (int32_t)(
837 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
839 value.GetScalar() = (uint32_t)(
840 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
844 value.GetScalar() = (int16_t)(
845 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
847 value.GetScalar() = (uint16_t)(
848 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
852 value.GetScalar() = (int8_t)(
853 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
855 value.GetScalar() = (uint8_t)(
856 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
859 } else if (return_compiler_type.IsPointerType()) {
861 thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
863 value.GetScalar() = ptr;
864 } else if (return_compiler_type.IsAggregateType()) {
865 // Structure/Vector is always passed in memory and pointer to that memory
867 uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
868 reg_ctx->GetRegisterInfoByName("r2", 0), 0);
869 // We have got the address. Create a memory object out of it
870 return_valobj_sp = ValueObjectMemory::Create(
871 &thread, "", Address(mem_address, nullptr), return_compiler_type);
872 return return_valobj_sp;
873 } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
874 if (IsSoftFloat(fp_flag)) {
875 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
876 if (count != 1 && is_complex)
877 return return_valobj_sp;
878 switch (*bit_width) {
880 return return_valobj_sp;
882 static_assert(sizeof(float) == sizeof(uint32_t), "");
883 value.GetScalar() = *((float *)(&raw_value));
886 static_assert(sizeof(double) == sizeof(uint64_t), "");
887 const RegisterInfo *r3_reg_info =
888 reg_ctx->GetRegisterInfoByName("r3", 0);
889 if (target_byte_order == eByteOrderLittle)
891 ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
894 raw_value = (raw_value << 32) |
895 reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
896 value.GetScalar() = *((double *)(&raw_value));
902 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
903 RegisterValue f0_value;
904 DataExtractor f0_data;
905 reg_ctx->ReadRegister(f0_info, f0_value);
906 f0_value.GetData(f0_data);
907 lldb::offset_t offset = 0;
909 if (count == 1 && !is_complex) {
910 switch (*bit_width) {
912 return return_valobj_sp;
914 static_assert(sizeof(double) == sizeof(uint64_t), "");
915 const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
916 RegisterValue f1_value;
917 DataExtractor f1_data;
918 reg_ctx->ReadRegister(f1_info, f1_value);
919 DataExtractor *copy_from_extractor = nullptr;
920 DataBufferSP data_sp(new DataBufferHeap(8, 0));
921 DataExtractor return_ext(
922 data_sp, target_byte_order,
923 target->GetArchitecture().GetAddressByteSize());
925 if (target_byte_order == eByteOrderLittle) {
926 copy_from_extractor = &f0_data;
927 copy_from_extractor->CopyByteOrderedData(
928 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
929 f1_value.GetData(f1_data);
930 copy_from_extractor = &f1_data;
931 copy_from_extractor->CopyByteOrderedData(
932 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
934 copy_from_extractor = &f0_data;
935 copy_from_extractor->CopyByteOrderedData(
936 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
937 f1_value.GetData(f1_data);
938 copy_from_extractor = &f1_data;
939 copy_from_extractor->CopyByteOrderedData(
940 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
942 value.GetScalar() = (double)return_ext.GetDouble(&offset);
946 static_assert(sizeof(float) == sizeof(uint32_t), "");
947 value.GetScalar() = (float)f0_data.GetFloat(&offset);
953 return return_valobj_sp;
958 return return_valobj_sp;
961 // If we get here, we have a valid Value, so make our ValueObject out of it:
963 return_valobj_sp = ValueObjectConstResult::Create(
964 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
965 return return_valobj_sp;
968 bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
970 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
972 UnwindPlan::RowSP row(new UnwindPlan::Row);
974 // Our Call Frame Address is the stack pointer value
975 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
977 // The previous PC is in the RA
978 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
979 unwind_plan.AppendRow(row);
981 // All other registers are the same.
983 unwind_plan.SetSourceName("mips at-func-entry default");
984 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
985 unwind_plan.SetReturnAddressRegister(dwarf_r31);
989 bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
991 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
993 UnwindPlan::RowSP row(new UnwindPlan::Row);
995 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
997 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
999 unwind_plan.AppendRow(row);
1000 unwind_plan.SetSourceName("mips default unwind plan");
1001 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1002 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1006 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
1007 return !RegisterIsCalleeSaved(reg_info);
1010 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
1011 return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1014 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1016 // Preserved registers are :
1017 // r16-r23, r28, r29, r30, r31
1018 const char *name = reg_info->name;
1020 if (name[0] == 'r') {
1023 if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
1024 name[2] == '9') // r16-r19
1025 return name[3] == '\0';
1028 if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
1029 name[2] == '3' // r20-r23
1030 || name[2] == '8' || name[2] == '9') // r28 and r29
1031 return name[3] == '\0';
1034 if (name[2] == '0' || name[2] == '1') // r30 and r31
1035 return name[3] == '\0';
1039 if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
1041 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
1043 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
1045 if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
1052 void ABISysV_mips::Initialize() {
1053 PluginManager::RegisterPlugin(
1054 GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1057 void ABISysV_mips::Terminate() {
1058 PluginManager::UnregisterPlugin(CreateInstance);
1061 lldb_private::ConstString ABISysV_mips::GetPluginNameStatic() {
1062 static ConstString g_name("sysv-mips");
1066 //------------------------------------------------------------------
1067 // PluginInterface protocol
1068 //------------------------------------------------------------------
1070 lldb_private::ConstString ABISysV_mips::GetPluginName() {
1071 return GetPluginNameStatic();
1074 uint32_t ABISysV_mips::GetPluginVersion() { return 1; }