1 //===-- ABISysV_mips.cpp --------------------------------------------------===//
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/TargetParser/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/LLDBLog.h"
29 #include "lldb/Utility/Log.h"
30 #include "lldb/Utility/RegisterValue.h"
31 #include "lldb/Utility/Status.h"
35 using namespace lldb_private
;
37 LLDB_PLUGIN_DEFINE(ABISysV_mips
)
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 // =================== ========== =================
93 {dwarf_r0
, dwarf_r0
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
105 {dwarf_r1
, dwarf_r1
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
106 LLDB_INVALID_REGNUM
},
117 {dwarf_r2
, dwarf_r2
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
118 LLDB_INVALID_REGNUM
},
129 {dwarf_r3
, dwarf_r3
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
130 LLDB_INVALID_REGNUM
},
141 {dwarf_r4
, dwarf_r4
, LLDB_REGNUM_GENERIC_ARG1
, LLDB_INVALID_REGNUM
,
142 LLDB_INVALID_REGNUM
},
153 {dwarf_r5
, dwarf_r5
, LLDB_REGNUM_GENERIC_ARG2
, LLDB_INVALID_REGNUM
,
154 LLDB_INVALID_REGNUM
},
165 {dwarf_r6
, dwarf_r6
, LLDB_REGNUM_GENERIC_ARG3
, LLDB_INVALID_REGNUM
,
166 LLDB_INVALID_REGNUM
},
177 {dwarf_r7
, dwarf_r7
, LLDB_REGNUM_GENERIC_ARG4
, LLDB_INVALID_REGNUM
,
178 LLDB_INVALID_REGNUM
},
189 {dwarf_r8
, dwarf_r8
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
190 LLDB_INVALID_REGNUM
},
201 {dwarf_r9
, dwarf_r9
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
202 LLDB_INVALID_REGNUM
},
213 {dwarf_r10
, dwarf_r10
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
214 LLDB_INVALID_REGNUM
},
225 {dwarf_r11
, dwarf_r11
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
226 LLDB_INVALID_REGNUM
},
237 {dwarf_r12
, dwarf_r12
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
238 LLDB_INVALID_REGNUM
},
249 {dwarf_r13
, dwarf_r13
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
250 LLDB_INVALID_REGNUM
},
261 {dwarf_r14
, dwarf_r14
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
262 LLDB_INVALID_REGNUM
},
273 {dwarf_r15
, dwarf_r15
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
274 LLDB_INVALID_REGNUM
},
285 {dwarf_r16
, dwarf_r16
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
286 LLDB_INVALID_REGNUM
},
297 {dwarf_r17
, dwarf_r17
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
298 LLDB_INVALID_REGNUM
},
309 {dwarf_r18
, dwarf_r18
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
310 LLDB_INVALID_REGNUM
},
321 {dwarf_r19
, dwarf_r19
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
322 LLDB_INVALID_REGNUM
},
333 {dwarf_r20
, dwarf_r20
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
334 LLDB_INVALID_REGNUM
},
345 {dwarf_r21
, dwarf_r21
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
346 LLDB_INVALID_REGNUM
},
357 {dwarf_r22
, dwarf_r22
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
358 LLDB_INVALID_REGNUM
},
369 {dwarf_r23
, dwarf_r23
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
370 LLDB_INVALID_REGNUM
},
381 {dwarf_r24
, dwarf_r24
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
382 LLDB_INVALID_REGNUM
},
393 {dwarf_r25
, dwarf_r25
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
394 LLDB_INVALID_REGNUM
},
405 {dwarf_r26
, dwarf_r26
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
406 LLDB_INVALID_REGNUM
},
417 {dwarf_r27
, dwarf_r27
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
418 LLDB_INVALID_REGNUM
},
429 {dwarf_r28
, dwarf_r28
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
430 LLDB_INVALID_REGNUM
},
441 {dwarf_r29
, dwarf_r29
, LLDB_REGNUM_GENERIC_SP
, LLDB_INVALID_REGNUM
,
442 LLDB_INVALID_REGNUM
},
453 {dwarf_r30
, dwarf_r30
, LLDB_REGNUM_GENERIC_FP
, LLDB_INVALID_REGNUM
,
454 LLDB_INVALID_REGNUM
},
465 {dwarf_r31
, dwarf_r31
, LLDB_REGNUM_GENERIC_RA
, LLDB_INVALID_REGNUM
,
466 LLDB_INVALID_REGNUM
},
477 {dwarf_sr
, dwarf_sr
, LLDB_REGNUM_GENERIC_FLAGS
, LLDB_INVALID_REGNUM
,
478 LLDB_INVALID_REGNUM
},
489 {dwarf_lo
, dwarf_lo
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
490 LLDB_INVALID_REGNUM
},
501 {dwarf_hi
, dwarf_hi
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
502 LLDB_INVALID_REGNUM
},
513 {dwarf_bad
, dwarf_bad
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
514 LLDB_INVALID_REGNUM
},
525 {dwarf_cause
, dwarf_cause
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
526 LLDB_INVALID_REGNUM
},
537 {dwarf_pc
, dwarf_pc
, LLDB_REGNUM_GENERIC_PC
, LLDB_INVALID_REGNUM
,
538 LLDB_INVALID_REGNUM
},
545 static const uint32_t k_num_register_infos
= std::size(g_register_infos
);
547 const lldb_private::RegisterInfo
*
548 ABISysV_mips::GetRegisterInfoArray(uint32_t &count
) {
549 count
= k_num_register_infos
;
550 return g_register_infos
;
553 size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
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
)) {
563 new ABISysV_mips(std::move(process_sp
), MakeMCRegisterInfo(arch
)));
568 bool ABISysV_mips::PrepareTrivialCall(Thread
&thread
, addr_t sp
,
569 addr_t func_addr
, addr_t return_addr
,
570 llvm::ArrayRef
<addr_t
> args
) const {
571 Log
*log
= GetLog(LLDBLog::Expressions
);
575 s
.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
576 ", sp = 0x%" PRIx64
", func_addr = 0x%" PRIx64
577 ", return_addr = 0x%" PRIx64
,
578 thread
.GetID(), (uint64_t)sp
, (uint64_t)func_addr
,
579 (uint64_t)return_addr
);
581 for (size_t i
= 0; i
< args
.size(); ++i
)
582 s
.Printf(", arg%zd = 0x%" PRIx64
, i
+ 1, args
[i
]);
584 log
->PutString(s
.GetString());
587 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
591 const RegisterInfo
*reg_info
= nullptr;
593 RegisterValue reg_value
;
595 // Argument registers
596 const char *reg_names
[] = {"r4", "r5", "r6", "r7"};
598 llvm::ArrayRef
<addr_t
>::iterator ai
= args
.begin(), ae
= args
.end();
600 // Write arguments to registers
601 for (size_t i
= 0; i
< std::size(reg_names
); ++i
) {
605 reg_info
= reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
,
606 LLDB_REGNUM_GENERIC_ARG1
+ i
);
607 LLDB_LOGF(log
, "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
);
636 LLDB_LOGF(log
, "About to write arg%zd (0x%" PRIx64
") at 0x%" PRIx64
"",
637 i
+ 1, args
[i
], arg_pos
);
640 ->WriteRegisterValueToMemory(reg_info
, arg_pos
,
641 reg_info
->byte_size
, reg_value
)
644 arg_pos
+= reg_info
->byte_size
;
650 const RegisterInfo
*pc_reg_info
=
651 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
652 const RegisterInfo
*sp_reg_info
=
653 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_SP
);
654 const RegisterInfo
*ra_reg_info
=
655 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_RA
);
656 const RegisterInfo
*r25_info
= reg_ctx
->GetRegisterInfoByName("r25", 0);
657 const RegisterInfo
*r0_info
= reg_ctx
->GetRegisterInfoByName("zero", 0);
659 LLDB_LOGF(log
, "Writing R0: 0x%" PRIx64
, (uint64_t)0);
661 /* Write r0 with 0, in case we are stopped in syscall,
662 * such setting prevents automatic decrement of the PC.
663 * This clears the bug 23659 for MIPS.
665 if (!reg_ctx
->WriteRegisterFromUnsigned(r0_info
, (uint64_t)0))
668 LLDB_LOGF(log
, "Writing SP: 0x%" PRIx64
, (uint64_t)sp
);
670 // Set "sp" to the requested value
671 if (!reg_ctx
->WriteRegisterFromUnsigned(sp_reg_info
, sp
))
674 LLDB_LOGF(log
, "Writing RA: 0x%" PRIx64
, (uint64_t)return_addr
);
676 // Set "ra" to the return address
677 if (!reg_ctx
->WriteRegisterFromUnsigned(ra_reg_info
, return_addr
))
680 LLDB_LOGF(log
, "Writing PC: 0x%" PRIx64
, (uint64_t)func_addr
);
682 // Set pc to the address of the called function.
683 if (!reg_ctx
->WriteRegisterFromUnsigned(pc_reg_info
, func_addr
))
686 LLDB_LOGF(log
, "Writing r25: 0x%" PRIx64
, (uint64_t)func_addr
);
688 // All callers of position independent functions must place the address of
689 // the called function in t9 (r25)
690 if (!reg_ctx
->WriteRegisterFromUnsigned(r25_info
, func_addr
))
696 bool ABISysV_mips::GetArgumentValues(Thread
&thread
, ValueList
&values
) const {
700 Status
ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP
&frame_sp
,
701 lldb::ValueObjectSP
&new_value_sp
) {
704 error
.SetErrorString("Empty value object for return value.");
708 CompilerType compiler_type
= new_value_sp
->GetCompilerType();
709 if (!compiler_type
) {
710 error
.SetErrorString("Null clang type for return value.");
714 Thread
*thread
= frame_sp
->GetThread().get();
720 RegisterContext
*reg_ctx
= thread
->GetRegisterContext().get();
722 bool set_it_simple
= false;
723 if (compiler_type
.IsIntegerOrEnumerationType(is_signed
) ||
724 compiler_type
.IsPointerType()) {
727 size_t num_bytes
= new_value_sp
->GetData(data
, data_error
);
728 if (data_error
.Fail()) {
729 error
.SetErrorStringWithFormat(
730 "Couldn't convert return value to raw data: %s",
731 data_error
.AsCString());
735 lldb::offset_t offset
= 0;
736 if (num_bytes
<= 8) {
737 const RegisterInfo
*r2_info
= reg_ctx
->GetRegisterInfoByName("r2", 0);
738 if (num_bytes
<= 4) {
739 uint32_t raw_value
= data
.GetMaxU32(&offset
, num_bytes
);
741 if (reg_ctx
->WriteRegisterFromUnsigned(r2_info
, raw_value
))
742 set_it_simple
= true;
744 uint32_t raw_value
= data
.GetMaxU32(&offset
, 4);
746 if (reg_ctx
->WriteRegisterFromUnsigned(r2_info
, raw_value
)) {
747 const RegisterInfo
*r3_info
= reg_ctx
->GetRegisterInfoByName("r3", 0);
748 uint32_t raw_value
= data
.GetMaxU32(&offset
, num_bytes
- offset
);
750 if (reg_ctx
->WriteRegisterFromUnsigned(r3_info
, raw_value
))
751 set_it_simple
= true;
755 error
.SetErrorString("We don't support returning longer than 64 bit "
756 "integer values at present.");
758 } else if (compiler_type
.IsFloatingPointType(count
, is_complex
)) {
760 error
.SetErrorString(
761 "We don't support returning complex values at present");
763 error
.SetErrorString(
764 "We don't support returning float values at present");
768 error
.SetErrorString(
769 "We only support setting simple integer return types at present.");
774 ValueObjectSP
ABISysV_mips::GetReturnValueObjectSimple(
775 Thread
&thread
, CompilerType
&return_compiler_type
) const {
776 ValueObjectSP return_valobj_sp
;
777 return return_valobj_sp
;
780 ValueObjectSP
ABISysV_mips::GetReturnValueObjectImpl(
781 Thread
&thread
, CompilerType
&return_compiler_type
) const {
782 ValueObjectSP return_valobj_sp
;
785 if (!return_compiler_type
)
786 return return_valobj_sp
;
788 ExecutionContext
exe_ctx(thread
.shared_from_this());
789 if (exe_ctx
.GetTargetPtr() == nullptr || exe_ctx
.GetProcessPtr() == nullptr)
790 return return_valobj_sp
;
792 Target
*target
= exe_ctx
.GetTargetPtr();
793 const ArchSpec target_arch
= target
->GetArchitecture();
794 ByteOrder target_byte_order
= target_arch
.GetByteOrder();
795 value
.SetCompilerType(return_compiler_type
);
797 target_arch
.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask
;
799 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
801 return return_valobj_sp
;
803 bool is_signed
= false;
804 bool is_complex
= false;
807 // In MIPS register "r2" (v0) holds the integer function return values
808 const RegisterInfo
*r2_reg_info
= reg_ctx
->GetRegisterInfoByName("r2", 0);
809 std::optional
<uint64_t> bit_width
= return_compiler_type
.GetBitSize(&thread
);
811 return return_valobj_sp
;
812 if (return_compiler_type
.IsIntegerOrEnumerationType(is_signed
)) {
813 switch (*bit_width
) {
815 return return_valobj_sp
;
817 const RegisterInfo
*r3_reg_info
= reg_ctx
->GetRegisterInfoByName("r3", 0);
819 raw_value
= reg_ctx
->ReadRegisterAsUnsigned(r2_reg_info
, 0) & UINT32_MAX
;
820 raw_value
|= ((uint64_t)(reg_ctx
->ReadRegisterAsUnsigned(r3_reg_info
, 0) &
824 value
.GetScalar() = (int64_t)raw_value
;
826 value
.GetScalar() = (uint64_t)raw_value
;
830 value
.GetScalar() = (int32_t)(
831 reg_ctx
->ReadRegisterAsUnsigned(r2_reg_info
, 0) & UINT32_MAX
);
833 value
.GetScalar() = (uint32_t)(
834 reg_ctx
->ReadRegisterAsUnsigned(r2_reg_info
, 0) & UINT32_MAX
);
838 value
.GetScalar() = (int16_t)(
839 reg_ctx
->ReadRegisterAsUnsigned(r2_reg_info
, 0) & UINT16_MAX
);
841 value
.GetScalar() = (uint16_t)(
842 reg_ctx
->ReadRegisterAsUnsigned(r2_reg_info
, 0) & UINT16_MAX
);
846 value
.GetScalar() = (int8_t)(
847 reg_ctx
->ReadRegisterAsUnsigned(r2_reg_info
, 0) & UINT8_MAX
);
849 value
.GetScalar() = (uint8_t)(
850 reg_ctx
->ReadRegisterAsUnsigned(r2_reg_info
, 0) & UINT8_MAX
);
853 } else if (return_compiler_type
.IsPointerType()) {
855 thread
.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info
, 0) &
857 value
.GetScalar() = ptr
;
858 } else if (return_compiler_type
.IsAggregateType()) {
859 // Structure/Vector is always passed in memory and pointer to that memory
861 uint64_t mem_address
= reg_ctx
->ReadRegisterAsUnsigned(
862 reg_ctx
->GetRegisterInfoByName("r2", 0), 0);
863 // We have got the address. Create a memory object out of it
864 return_valobj_sp
= ValueObjectMemory::Create(
865 &thread
, "", Address(mem_address
, nullptr), return_compiler_type
);
866 return return_valobj_sp
;
867 } else if (return_compiler_type
.IsFloatingPointType(count
, is_complex
)) {
868 if (IsSoftFloat(fp_flag
)) {
869 uint64_t raw_value
= reg_ctx
->ReadRegisterAsUnsigned(r2_reg_info
, 0);
870 if (count
!= 1 && is_complex
)
871 return return_valobj_sp
;
872 switch (*bit_width
) {
874 return return_valobj_sp
;
876 static_assert(sizeof(float) == sizeof(uint32_t));
877 value
.GetScalar() = *((float *)(&raw_value
));
880 static_assert(sizeof(double) == sizeof(uint64_t));
881 const RegisterInfo
*r3_reg_info
=
882 reg_ctx
->GetRegisterInfoByName("r3", 0);
883 if (target_byte_order
== eByteOrderLittle
)
885 ((reg_ctx
->ReadRegisterAsUnsigned(r3_reg_info
, 0)) << 32) |
888 raw_value
= (raw_value
<< 32) |
889 reg_ctx
->ReadRegisterAsUnsigned(r3_reg_info
, 0);
890 value
.GetScalar() = *((double *)(&raw_value
));
896 const RegisterInfo
*f0_info
= reg_ctx
->GetRegisterInfoByName("f0", 0);
897 RegisterValue f0_value
;
898 DataExtractor f0_data
;
899 reg_ctx
->ReadRegister(f0_info
, f0_value
);
900 f0_value
.GetData(f0_data
);
901 lldb::offset_t offset
= 0;
903 if (count
== 1 && !is_complex
) {
904 switch (*bit_width
) {
906 return return_valobj_sp
;
908 static_assert(sizeof(double) == sizeof(uint64_t));
909 const RegisterInfo
*f1_info
= reg_ctx
->GetRegisterInfoByName("f1", 0);
910 RegisterValue f1_value
;
911 DataExtractor f1_data
;
912 reg_ctx
->ReadRegister(f1_info
, f1_value
);
913 DataExtractor
*copy_from_extractor
= nullptr;
914 WritableDataBufferSP
data_sp(new DataBufferHeap(8, 0));
915 DataExtractor
return_ext(
916 data_sp
, target_byte_order
,
917 target
->GetArchitecture().GetAddressByteSize());
919 if (target_byte_order
== eByteOrderLittle
) {
920 copy_from_extractor
= &f0_data
;
921 copy_from_extractor
->CopyByteOrderedData(
922 offset
, 4, data_sp
->GetBytes(), 4, target_byte_order
);
923 f1_value
.GetData(f1_data
);
924 copy_from_extractor
= &f1_data
;
925 copy_from_extractor
->CopyByteOrderedData(
926 offset
, 4, data_sp
->GetBytes() + 4, 4, target_byte_order
);
928 copy_from_extractor
= &f0_data
;
929 copy_from_extractor
->CopyByteOrderedData(
930 offset
, 4, data_sp
->GetBytes() + 4, 4, target_byte_order
);
931 f1_value
.GetData(f1_data
);
932 copy_from_extractor
= &f1_data
;
933 copy_from_extractor
->CopyByteOrderedData(
934 offset
, 4, data_sp
->GetBytes(), 4, target_byte_order
);
936 value
.GetScalar() = (double)return_ext
.GetDouble(&offset
);
940 static_assert(sizeof(float) == sizeof(uint32_t));
941 value
.GetScalar() = (float)f0_data
.GetFloat(&offset
);
947 return return_valobj_sp
;
952 return return_valobj_sp
;
955 // If we get here, we have a valid Value, so make our ValueObject out of it:
957 return_valobj_sp
= ValueObjectConstResult::Create(
958 thread
.GetStackFrameAtIndex(0).get(), value
, ConstString(""));
959 return return_valobj_sp
;
962 bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan
&unwind_plan
) {
964 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
966 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
968 // Our Call Frame Address is the stack pointer value
969 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29
, 0);
971 // The previous PC is in the RA
972 row
->SetRegisterLocationToRegister(dwarf_pc
, dwarf_r31
, true);
973 unwind_plan
.AppendRow(row
);
975 // All other registers are the same.
977 unwind_plan
.SetSourceName("mips at-func-entry default");
978 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
979 unwind_plan
.SetReturnAddressRegister(dwarf_r31
);
983 bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan
&unwind_plan
) {
985 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
987 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
989 row
->SetUnspecifiedRegistersAreUndefined(true);
990 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29
, 0);
992 row
->SetRegisterLocationToRegister(dwarf_pc
, dwarf_r31
, true);
994 unwind_plan
.AppendRow(row
);
995 unwind_plan
.SetSourceName("mips default unwind plan");
996 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
997 unwind_plan
.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo
);
998 unwind_plan
.SetUnwindPlanForSignalTrap(eLazyBoolNo
);
1002 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo
*reg_info
) {
1003 return !RegisterIsCalleeSaved(reg_info
);
1006 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags
) const {
1007 return (fp_flags
== lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT
);
1010 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo
*reg_info
) {
1012 // Preserved registers are :
1013 // r16-r23, r28, r29, r30, r31
1014 const char *name
= reg_info
->name
;
1016 if (name
[0] == 'r') {
1019 if (name
[2] == '6' || name
[2] == '7' || name
[2] == '8' ||
1020 name
[2] == '9') // r16-r19
1021 return name
[3] == '\0';
1024 if (name
[2] == '0' || name
[2] == '1' || name
[2] == '2' ||
1025 name
[2] == '3' // r20-r23
1026 || name
[2] == '8' || name
[2] == '9') // r28 and r29
1027 return name
[3] == '\0';
1030 if (name
[2] == '0' || name
[2] == '1') // r30 and r31
1031 return name
[3] == '\0';
1035 if (name
[0] == 'g' && name
[1] == 'p' && name
[2] == '\0') // gp (r28)
1037 if (name
[0] == 's' && name
[1] == 'p' && name
[2] == '\0') // sp (r29)
1039 if (name
[0] == 'f' && name
[1] == 'p' && name
[2] == '\0') // fp (r30)
1041 if (name
[0] == 'r' && name
[1] == 'a' && name
[2] == '\0') // ra (r31)
1048 void ABISysV_mips::Initialize() {
1049 PluginManager::RegisterPlugin(
1050 GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance
);
1053 void ABISysV_mips::Terminate() {
1054 PluginManager::UnregisterPlugin(CreateInstance
);