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)) {
560 new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch)));
565 bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
566 addr_t func_addr, addr_t return_addr,
567 llvm::ArrayRef<addr_t> args) const {
568 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
572 s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
573 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
574 ", return_addr = 0x%" PRIx64,
575 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
576 (uint64_t)return_addr);
578 for (size_t i = 0; i < args.size(); ++i)
579 s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
581 log->PutString(s.GetString());
584 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
588 const RegisterInfo *reg_info = nullptr;
590 RegisterValue reg_value;
592 // Argument registers
593 const char *reg_names[] = {"r4", "r5", "r6", "r7"};
595 llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
597 // Write arguments to registers
598 for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) {
602 reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
603 LLDB_REGNUM_GENERIC_ARG1 + i);
604 LLDB_LOGF(log, "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);
633 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
634 i + 1, args[i], arg_pos);
637 ->WriteRegisterValueToMemory(reg_info, arg_pos,
638 reg_info->byte_size, reg_value)
641 arg_pos += reg_info->byte_size;
647 const RegisterInfo *pc_reg_info =
648 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
649 const RegisterInfo *sp_reg_info =
650 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
651 const RegisterInfo *ra_reg_info =
652 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
653 const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
654 const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
656 LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
658 /* Write r0 with 0, in case we are stopped in syscall,
659 * such setting prevents automatic decrement of the PC.
660 * This clears the bug 23659 for MIPS.
662 if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
665 LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
667 // Set "sp" to the requested value
668 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
671 LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
673 // Set "ra" to the return address
674 if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
677 LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
679 // Set pc to the address of the called function.
680 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
683 LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
685 // All callers of position independent functions must place the address of
686 // the called function in t9 (r25)
687 if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
693 bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
697 Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
698 lldb::ValueObjectSP &new_value_sp) {
701 error.SetErrorString("Empty value object for return value.");
705 CompilerType compiler_type = new_value_sp->GetCompilerType();
706 if (!compiler_type) {
707 error.SetErrorString("Null clang type for return value.");
711 Thread *thread = frame_sp->GetThread().get();
717 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
719 bool set_it_simple = false;
720 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
721 compiler_type.IsPointerType()) {
724 size_t num_bytes = new_value_sp->GetData(data, data_error);
725 if (data_error.Fail()) {
726 error.SetErrorStringWithFormat(
727 "Couldn't convert return value to raw data: %s",
728 data_error.AsCString());
732 lldb::offset_t offset = 0;
733 if (num_bytes <= 8) {
734 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
735 if (num_bytes <= 4) {
736 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
738 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
739 set_it_simple = true;
741 uint32_t raw_value = data.GetMaxU32(&offset, 4);
743 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
744 const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
745 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
747 if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
748 set_it_simple = true;
752 error.SetErrorString("We don't support returning longer than 64 bit "
753 "integer values at present.");
755 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
757 error.SetErrorString(
758 "We don't support returning complex values at present");
760 error.SetErrorString(
761 "We don't support returning float values at present");
765 error.SetErrorString(
766 "We only support setting simple integer return types at present.");
771 ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
772 Thread &thread, CompilerType &return_compiler_type) const {
773 ValueObjectSP return_valobj_sp;
774 return return_valobj_sp;
777 ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
778 Thread &thread, CompilerType &return_compiler_type) const {
779 ValueObjectSP return_valobj_sp;
782 if (!return_compiler_type)
783 return return_valobj_sp;
785 ExecutionContext exe_ctx(thread.shared_from_this());
786 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
787 return return_valobj_sp;
789 Target *target = exe_ctx.GetTargetPtr();
790 const ArchSpec target_arch = target->GetArchitecture();
791 ByteOrder target_byte_order = target_arch.GetByteOrder();
792 value.SetCompilerType(return_compiler_type);
794 target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
796 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
798 return return_valobj_sp;
800 bool is_signed = false;
801 bool is_complex = false;
804 // In MIPS register "r2" (v0) holds the integer function return values
805 const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
806 llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
808 return return_valobj_sp;
809 if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
810 switch (*bit_width) {
812 return return_valobj_sp;
814 const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
816 raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
817 raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
821 value.GetScalar() = (int64_t)raw_value;
823 value.GetScalar() = (uint64_t)raw_value;
827 value.GetScalar() = (int32_t)(
828 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
830 value.GetScalar() = (uint32_t)(
831 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
835 value.GetScalar() = (int16_t)(
836 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
838 value.GetScalar() = (uint16_t)(
839 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
843 value.GetScalar() = (int8_t)(
844 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
846 value.GetScalar() = (uint8_t)(
847 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
850 } else if (return_compiler_type.IsPointerType()) {
852 thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
854 value.GetScalar() = ptr;
855 } else if (return_compiler_type.IsAggregateType()) {
856 // Structure/Vector is always passed in memory and pointer to that memory
858 uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
859 reg_ctx->GetRegisterInfoByName("r2", 0), 0);
860 // We have got the address. Create a memory object out of it
861 return_valobj_sp = ValueObjectMemory::Create(
862 &thread, "", Address(mem_address, nullptr), return_compiler_type);
863 return return_valobj_sp;
864 } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
865 if (IsSoftFloat(fp_flag)) {
866 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
867 if (count != 1 && is_complex)
868 return return_valobj_sp;
869 switch (*bit_width) {
871 return return_valobj_sp;
873 static_assert(sizeof(float) == sizeof(uint32_t), "");
874 value.GetScalar() = *((float *)(&raw_value));
877 static_assert(sizeof(double) == sizeof(uint64_t), "");
878 const RegisterInfo *r3_reg_info =
879 reg_ctx->GetRegisterInfoByName("r3", 0);
880 if (target_byte_order == eByteOrderLittle)
882 ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
885 raw_value = (raw_value << 32) |
886 reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
887 value.GetScalar() = *((double *)(&raw_value));
893 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
894 RegisterValue f0_value;
895 DataExtractor f0_data;
896 reg_ctx->ReadRegister(f0_info, f0_value);
897 f0_value.GetData(f0_data);
898 lldb::offset_t offset = 0;
900 if (count == 1 && !is_complex) {
901 switch (*bit_width) {
903 return return_valobj_sp;
905 static_assert(sizeof(double) == sizeof(uint64_t), "");
906 const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
907 RegisterValue f1_value;
908 DataExtractor f1_data;
909 reg_ctx->ReadRegister(f1_info, f1_value);
910 DataExtractor *copy_from_extractor = nullptr;
911 DataBufferSP data_sp(new DataBufferHeap(8, 0));
912 DataExtractor return_ext(
913 data_sp, target_byte_order,
914 target->GetArchitecture().GetAddressByteSize());
916 if (target_byte_order == eByteOrderLittle) {
917 copy_from_extractor = &f0_data;
918 copy_from_extractor->CopyByteOrderedData(
919 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
920 f1_value.GetData(f1_data);
921 copy_from_extractor = &f1_data;
922 copy_from_extractor->CopyByteOrderedData(
923 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
925 copy_from_extractor = &f0_data;
926 copy_from_extractor->CopyByteOrderedData(
927 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
928 f1_value.GetData(f1_data);
929 copy_from_extractor = &f1_data;
930 copy_from_extractor->CopyByteOrderedData(
931 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
933 value.GetScalar() = (double)return_ext.GetDouble(&offset);
937 static_assert(sizeof(float) == sizeof(uint32_t), "");
938 value.GetScalar() = (float)f0_data.GetFloat(&offset);
944 return return_valobj_sp;
949 return return_valobj_sp;
952 // If we get here, we have a valid Value, so make our ValueObject out of it:
954 return_valobj_sp = ValueObjectConstResult::Create(
955 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
956 return return_valobj_sp;
959 bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
961 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
963 UnwindPlan::RowSP row(new UnwindPlan::Row);
965 // Our Call Frame Address is the stack pointer value
966 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
968 // The previous PC is in the RA
969 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
970 unwind_plan.AppendRow(row);
972 // All other registers are the same.
974 unwind_plan.SetSourceName("mips at-func-entry default");
975 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
976 unwind_plan.SetReturnAddressRegister(dwarf_r31);
980 bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
982 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
984 UnwindPlan::RowSP row(new UnwindPlan::Row);
986 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
988 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
990 unwind_plan.AppendRow(row);
991 unwind_plan.SetSourceName("mips default unwind plan");
992 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
993 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
994 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
998 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
999 return !RegisterIsCalleeSaved(reg_info);
1002 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
1003 return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1006 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1008 // Preserved registers are :
1009 // r16-r23, r28, r29, r30, r31
1010 const char *name = reg_info->name;
1012 if (name[0] == 'r') {
1015 if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
1016 name[2] == '9') // r16-r19
1017 return name[3] == '\0';
1020 if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
1021 name[2] == '3' // r20-r23
1022 || name[2] == '8' || name[2] == '9') // r28 and r29
1023 return name[3] == '\0';
1026 if (name[2] == '0' || name[2] == '1') // r30 and r31
1027 return name[3] == '\0';
1031 if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
1033 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
1035 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
1037 if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
1044 void ABISysV_mips::Initialize() {
1045 PluginManager::RegisterPlugin(
1046 GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1049 void ABISysV_mips::Terminate() {
1050 PluginManager::UnregisterPlugin(CreateInstance);
1053 lldb_private::ConstString ABISysV_mips::GetPluginNameStatic() {
1054 static ConstString g_name("sysv-mips");
1058 // PluginInterface protocol
1060 lldb_private::ConstString ABISysV_mips::GetPluginName() {
1061 return GetPluginNameStatic();
1064 uint32_t ABISysV_mips::GetPluginVersion() { return 1; }