1 //===-- ABISysV_mips64.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_mips64.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/Symbol/UnwindPlan.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/StackFrame.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Target/Thread.h"
23 #include "lldb/Utility/ConstString.h"
24 #include "lldb/Utility/DataExtractor.h"
25 #include "lldb/Utility/LLDBLog.h"
26 #include "lldb/Utility/Log.h"
27 #include "lldb/Utility/RegisterValue.h"
28 #include "lldb/Utility/Status.h"
29 #include "lldb/ValueObject/ValueObjectConstResult.h"
30 #include "lldb/ValueObject/ValueObjectMemory.h"
31 #include "lldb/ValueObject/ValueObjectRegister.h"
35 using namespace lldb_private
;
37 LLDB_PLUGIN_DEFINE(ABISysV_mips64
)
80 static const RegisterInfo g_register_infos_mips64
[] = {
87 {dwarf_r0
, dwarf_r0
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
99 {dwarf_r1
, dwarf_r1
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
100 LLDB_INVALID_REGNUM
},
112 {dwarf_r2
, dwarf_r2
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
113 LLDB_INVALID_REGNUM
},
124 {dwarf_r3
, dwarf_r3
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
125 LLDB_INVALID_REGNUM
},
136 {dwarf_r4
, dwarf_r4
, LLDB_REGNUM_GENERIC_ARG1
, LLDB_INVALID_REGNUM
,
137 LLDB_INVALID_REGNUM
},
148 {dwarf_r5
, dwarf_r5
, LLDB_REGNUM_GENERIC_ARG2
, LLDB_INVALID_REGNUM
,
149 LLDB_INVALID_REGNUM
},
160 {dwarf_r6
, dwarf_r6
, LLDB_REGNUM_GENERIC_ARG3
, LLDB_INVALID_REGNUM
,
161 LLDB_INVALID_REGNUM
},
172 {dwarf_r7
, dwarf_r7
, LLDB_REGNUM_GENERIC_ARG4
, LLDB_INVALID_REGNUM
,
173 LLDB_INVALID_REGNUM
},
184 {dwarf_r8
, dwarf_r8
, LLDB_REGNUM_GENERIC_ARG5
, LLDB_INVALID_REGNUM
,
185 LLDB_INVALID_REGNUM
},
196 {dwarf_r9
, dwarf_r9
, LLDB_REGNUM_GENERIC_ARG6
, LLDB_INVALID_REGNUM
,
197 LLDB_INVALID_REGNUM
},
208 {dwarf_r10
, dwarf_r10
, LLDB_REGNUM_GENERIC_ARG7
, LLDB_INVALID_REGNUM
,
209 LLDB_INVALID_REGNUM
},
220 {dwarf_r11
, dwarf_r11
, LLDB_REGNUM_GENERIC_ARG8
, LLDB_INVALID_REGNUM
,
221 LLDB_INVALID_REGNUM
},
232 {dwarf_r12
, dwarf_r12
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
233 LLDB_INVALID_REGNUM
},
244 {dwarf_r13
, dwarf_r13
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
245 LLDB_INVALID_REGNUM
},
256 {dwarf_r14
, dwarf_r14
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
257 LLDB_INVALID_REGNUM
},
268 {dwarf_r15
, dwarf_r15
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
269 LLDB_INVALID_REGNUM
},
280 {dwarf_r16
, dwarf_r16
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
281 LLDB_INVALID_REGNUM
},
292 {dwarf_r17
, dwarf_r17
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
293 LLDB_INVALID_REGNUM
},
304 {dwarf_r18
, dwarf_r18
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
305 LLDB_INVALID_REGNUM
},
316 {dwarf_r19
, dwarf_r19
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
317 LLDB_INVALID_REGNUM
},
328 {dwarf_r20
, dwarf_r20
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
329 LLDB_INVALID_REGNUM
},
340 {dwarf_r21
, dwarf_r21
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
341 LLDB_INVALID_REGNUM
},
352 {dwarf_r22
, dwarf_r22
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
353 LLDB_INVALID_REGNUM
},
364 {dwarf_r23
, dwarf_r23
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
365 LLDB_INVALID_REGNUM
},
376 {dwarf_r24
, dwarf_r24
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
377 LLDB_INVALID_REGNUM
},
388 {dwarf_r25
, dwarf_r25
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
389 LLDB_INVALID_REGNUM
},
400 {dwarf_r26
, dwarf_r26
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
401 LLDB_INVALID_REGNUM
},
412 {dwarf_r27
, dwarf_r27
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
413 LLDB_INVALID_REGNUM
},
424 {dwarf_r28
, dwarf_r28
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
425 LLDB_INVALID_REGNUM
},
436 {dwarf_r29
, dwarf_r29
, LLDB_REGNUM_GENERIC_SP
, LLDB_INVALID_REGNUM
,
437 LLDB_INVALID_REGNUM
},
448 {dwarf_r30
, dwarf_r30
, LLDB_REGNUM_GENERIC_FP
, LLDB_INVALID_REGNUM
,
449 LLDB_INVALID_REGNUM
},
460 {dwarf_r31
, dwarf_r31
, LLDB_REGNUM_GENERIC_RA
, LLDB_INVALID_REGNUM
,
461 LLDB_INVALID_REGNUM
},
472 {dwarf_sr
, dwarf_sr
, LLDB_REGNUM_GENERIC_FLAGS
, LLDB_INVALID_REGNUM
,
473 LLDB_INVALID_REGNUM
},
484 {dwarf_lo
, dwarf_lo
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
485 LLDB_INVALID_REGNUM
},
496 {dwarf_hi
, dwarf_hi
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
497 LLDB_INVALID_REGNUM
},
508 {dwarf_bad
, dwarf_bad
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
509 LLDB_INVALID_REGNUM
},
520 {dwarf_cause
, dwarf_cause
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
521 LLDB_INVALID_REGNUM
},
532 {dwarf_pc
, dwarf_pc
, LLDB_REGNUM_GENERIC_PC
, LLDB_INVALID_REGNUM
,
533 LLDB_INVALID_REGNUM
},
540 static const uint32_t k_num_register_infos
= std::size(g_register_infos_mips64
);
542 const lldb_private::RegisterInfo
*
543 ABISysV_mips64::GetRegisterInfoArray(uint32_t &count
) {
544 count
= k_num_register_infos
;
545 return g_register_infos_mips64
;
548 size_t ABISysV_mips64::GetRedZoneSize() const { return 0; }
553 ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp
, const ArchSpec
&arch
) {
554 if (arch
.GetTriple().isMIPS64())
556 new ABISysV_mips64(std::move(process_sp
), MakeMCRegisterInfo(arch
)));
560 bool ABISysV_mips64::PrepareTrivialCall(Thread
&thread
, addr_t sp
,
561 addr_t func_addr
, addr_t return_addr
,
562 llvm::ArrayRef
<addr_t
> args
) const {
563 Log
*log
= GetLog(LLDBLog::Expressions
);
567 s
.Printf("ABISysV_mips64::PrepareTrivialCall (tid = 0x%" PRIx64
568 ", sp = 0x%" PRIx64
", func_addr = 0x%" PRIx64
569 ", return_addr = 0x%" PRIx64
,
570 thread
.GetID(), (uint64_t)sp
, (uint64_t)func_addr
,
571 (uint64_t)return_addr
);
573 for (size_t i
= 0; i
< args
.size(); ++i
)
574 s
.Printf(", arg%zd = 0x%" PRIx64
, i
+ 1, args
[i
]);
576 log
->PutString(s
.GetString());
579 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
583 const RegisterInfo
*reg_info
= nullptr;
585 if (args
.size() > 8) // TODO handle more than 8 arguments
588 for (size_t i
= 0; i
< args
.size(); ++i
) {
589 reg_info
= reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
,
590 LLDB_REGNUM_GENERIC_ARG1
+ i
);
591 LLDB_LOGF(log
, "About to write arg%zd (0x%" PRIx64
") into %s", i
+ 1,
592 args
[i
], reg_info
->name
);
593 if (!reg_ctx
->WriteRegisterFromUnsigned(reg_info
, args
[i
]))
597 // First, align the SP
599 LLDB_LOGF(log
, "16-byte aligning SP: 0x%" PRIx64
" to 0x%" PRIx64
,
600 (uint64_t)sp
, (uint64_t)(sp
& ~0xfull
));
602 sp
&= ~(0xfull
); // 16-byte alignment
605 const RegisterInfo
*pc_reg_info
=
606 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
607 const RegisterInfo
*sp_reg_info
=
608 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_SP
);
609 const RegisterInfo
*ra_reg_info
=
610 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_RA
);
611 const RegisterInfo
*r25_info
= reg_ctx
->GetRegisterInfoByName("r25", 0);
612 const RegisterInfo
*r0_info
= reg_ctx
->GetRegisterInfoByName("zero", 0);
614 LLDB_LOGF(log
, "Writing R0: 0x%" PRIx64
, (uint64_t)0);
616 /* Write r0 with 0, in case we are stopped in syscall,
617 * such setting prevents automatic decrement of the PC.
618 * This clears the bug 23659 for MIPS.
620 if (!reg_ctx
->WriteRegisterFromUnsigned(r0_info
, (uint64_t)0))
623 LLDB_LOGF(log
, "Writing SP: 0x%" PRIx64
, (uint64_t)sp
);
625 // Set "sp" to the requested value
626 if (!reg_ctx
->WriteRegisterFromUnsigned(sp_reg_info
, sp
))
629 LLDB_LOGF(log
, "Writing RA: 0x%" PRIx64
, (uint64_t)return_addr
);
631 // Set "ra" to the return address
632 if (!reg_ctx
->WriteRegisterFromUnsigned(ra_reg_info
, return_addr
))
635 LLDB_LOGF(log
, "Writing PC: 0x%" PRIx64
, (uint64_t)func_addr
);
637 // Set pc to the address of the called function.
638 if (!reg_ctx
->WriteRegisterFromUnsigned(pc_reg_info
, func_addr
))
641 LLDB_LOGF(log
, "Writing r25: 0x%" PRIx64
, (uint64_t)func_addr
);
643 // All callers of position independent functions must place the address of
644 // the called function in t9 (r25)
645 if (!reg_ctx
->WriteRegisterFromUnsigned(r25_info
, func_addr
))
651 bool ABISysV_mips64::GetArgumentValues(Thread
&thread
,
652 ValueList
&values
) const {
656 Status
ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP
&frame_sp
,
657 lldb::ValueObjectSP
&new_value_sp
) {
660 error
= Status::FromErrorString("Empty value object for return value.");
664 CompilerType compiler_type
= new_value_sp
->GetCompilerType();
665 if (!compiler_type
) {
666 error
= Status::FromErrorString("Null clang type for return value.");
670 Thread
*thread
= frame_sp
->GetThread().get();
672 RegisterContext
*reg_ctx
= thread
->GetRegisterContext().get();
675 error
= Status::FromErrorString("no registers are available");
679 size_t num_bytes
= new_value_sp
->GetData(data
, data_error
);
680 if (data_error
.Fail()) {
681 error
= Status::FromErrorStringWithFormat(
682 "Couldn't convert return value to raw data: %s",
683 data_error
.AsCString());
687 const uint32_t type_flags
= compiler_type
.GetTypeInfo(nullptr);
689 if (type_flags
& eTypeIsScalar
|| type_flags
& eTypeIsPointer
) {
690 if (type_flags
& eTypeIsInteger
|| type_flags
& eTypeIsPointer
) {
691 lldb::offset_t offset
= 0;
693 if (num_bytes
<= 16) {
694 const RegisterInfo
*r2_info
= reg_ctx
->GetRegisterInfoByName("r2", 0);
695 if (num_bytes
<= 8) {
696 uint64_t raw_value
= data
.GetMaxU64(&offset
, num_bytes
);
698 if (!reg_ctx
->WriteRegisterFromUnsigned(r2_info
, raw_value
))
699 error
= Status::FromErrorString("failed to write register r2");
701 uint64_t raw_value
= data
.GetMaxU64(&offset
, 8);
702 if (reg_ctx
->WriteRegisterFromUnsigned(r2_info
, raw_value
)) {
703 const RegisterInfo
*r3_info
=
704 reg_ctx
->GetRegisterInfoByName("r3", 0);
705 raw_value
= data
.GetMaxU64(&offset
, num_bytes
- offset
);
707 if (!reg_ctx
->WriteRegisterFromUnsigned(r3_info
, raw_value
))
708 error
= Status::FromErrorString("failed to write register r3");
710 error
= Status::FromErrorString("failed to write register r2");
713 error
= Status::FromErrorString(
714 "We don't support returning longer than 128 bit "
715 "integer values at present.");
717 } else if (type_flags
& eTypeIsFloat
) {
718 error
= Status::FromErrorString("TODO: Handle Float Types.");
720 } else if (type_flags
& eTypeIsVector
) {
722 Status::FromErrorString("returning vector values are not supported");
728 ValueObjectSP
ABISysV_mips64::GetReturnValueObjectSimple(
729 Thread
&thread
, CompilerType
&return_compiler_type
) const {
730 ValueObjectSP return_valobj_sp
;
731 return return_valobj_sp
;
734 ValueObjectSP
ABISysV_mips64::GetReturnValueObjectImpl(
735 Thread
&thread
, CompilerType
&return_compiler_type
) const {
736 ValueObjectSP return_valobj_sp
;
740 ExecutionContext
exe_ctx(thread
.shared_from_this());
741 if (exe_ctx
.GetTargetPtr() == nullptr || exe_ctx
.GetProcessPtr() == nullptr)
742 return return_valobj_sp
;
744 value
.SetCompilerType(return_compiler_type
);
746 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
748 return return_valobj_sp
;
750 Target
*target
= exe_ctx
.GetTargetPtr();
751 const ArchSpec target_arch
= target
->GetArchitecture();
752 ByteOrder target_byte_order
= target_arch
.GetByteOrder();
753 std::optional
<uint64_t> byte_size
= return_compiler_type
.GetByteSize(&thread
);
755 return return_valobj_sp
;
756 const uint32_t type_flags
= return_compiler_type
.GetTypeInfo(nullptr);
758 target_arch
.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask
;
760 const RegisterInfo
*r2_info
= reg_ctx
->GetRegisterInfoByName("r2", 0);
761 const RegisterInfo
*r3_info
= reg_ctx
->GetRegisterInfoByName("r3", 0);
762 assert(r2_info
&& r3_info
&& "Basic registers should always be present.");
764 if (type_flags
& eTypeIsScalar
|| type_flags
& eTypeIsPointer
) {
765 value
.SetValueType(Value::ValueType::Scalar
);
767 bool success
= false;
768 if (type_flags
& eTypeIsInteger
|| type_flags
& eTypeIsPointer
) {
769 // Extract the register context so we can read arguments from registers
770 // In MIPS register "r2" (v0) holds the integer function return values
772 uint64_t raw_value
= reg_ctx
->ReadRegisterAsUnsigned(r2_info
, 0);
774 const bool is_signed
= (type_flags
& eTypeIsSigned
) != 0;
775 switch (*byte_size
) {
779 case sizeof(uint64_t):
781 value
.GetScalar() = (int64_t)(raw_value
);
783 value
.GetScalar() = (uint64_t)(raw_value
);
787 case sizeof(uint32_t):
789 value
.GetScalar() = (int32_t)(raw_value
& UINT32_MAX
);
791 value
.GetScalar() = (uint32_t)(raw_value
& UINT32_MAX
);
795 case sizeof(uint16_t):
797 value
.GetScalar() = (int16_t)(raw_value
& UINT16_MAX
);
799 value
.GetScalar() = (uint16_t)(raw_value
& UINT16_MAX
);
803 case sizeof(uint8_t):
805 value
.GetScalar() = (int8_t)(raw_value
& UINT8_MAX
);
807 value
.GetScalar() = (uint8_t)(raw_value
& UINT8_MAX
);
811 } else if (type_flags
& eTypeIsFloat
) {
812 if (type_flags
& eTypeIsComplex
) {
813 // Don't handle complex yet.
814 } else if (IsSoftFloat(fp_flag
)) {
815 uint64_t raw_value
= reg_ctx
->ReadRegisterAsUnsigned(r2_info
, 0);
816 switch (*byte_size
) {
818 value
.GetScalar() = *((float *)(&raw_value
));
822 value
.GetScalar() = *((double *)(&raw_value
));
827 if (target_byte_order
== eByteOrderLittle
) {
828 result
[0] = raw_value
;
829 result
[1] = reg_ctx
->ReadRegisterAsUnsigned(r3_info
, 0);
830 value
.GetScalar() = *((long double *)(result
));
832 result
[0] = reg_ctx
->ReadRegisterAsUnsigned(r3_info
, 0);
833 result
[1] = raw_value
;
834 value
.GetScalar() = *((long double *)(result
));
841 if (*byte_size
<= sizeof(long double)) {
842 const RegisterInfo
*f0_info
= reg_ctx
->GetRegisterInfoByName("f0", 0);
844 RegisterValue f0_value
;
845 DataExtractor f0_data
;
847 reg_ctx
->ReadRegister(f0_info
, f0_value
);
849 f0_value
.GetData(f0_data
);
851 lldb::offset_t offset
= 0;
852 if (*byte_size
== sizeof(float)) {
853 value
.GetScalar() = (float)f0_data
.GetFloat(&offset
);
855 } else if (*byte_size
== sizeof(double)) {
856 value
.GetScalar() = (double)f0_data
.GetDouble(&offset
);
858 } else if (*byte_size
== sizeof(long double)) {
859 const RegisterInfo
*f2_info
=
860 reg_ctx
->GetRegisterInfoByName("f2", 0);
861 RegisterValue f2_value
;
862 DataExtractor f2_data
;
863 reg_ctx
->ReadRegister(f2_info
, f2_value
);
864 DataExtractor
*copy_from_extractor
= nullptr;
865 WritableDataBufferSP
data_sp(new DataBufferHeap(16, 0));
866 DataExtractor
return_ext(
867 data_sp
, target_byte_order
,
868 target
->GetArchitecture().GetAddressByteSize());
870 if (target_byte_order
== eByteOrderLittle
) {
871 copy_from_extractor
= &f0_data
;
872 copy_from_extractor
->CopyByteOrderedData(
873 0, 8, data_sp
->GetBytes(), *byte_size
- 8, target_byte_order
);
874 f2_value
.GetData(f2_data
);
875 copy_from_extractor
= &f2_data
;
876 copy_from_extractor
->CopyByteOrderedData(
877 0, 8, data_sp
->GetBytes() + 8, *byte_size
- 8,
880 copy_from_extractor
= &f0_data
;
881 copy_from_extractor
->CopyByteOrderedData(
882 0, 8, data_sp
->GetBytes() + 8, *byte_size
- 8,
884 f2_value
.GetData(f2_data
);
885 copy_from_extractor
= &f2_data
;
886 copy_from_extractor
->CopyByteOrderedData(
887 0, 8, data_sp
->GetBytes(), *byte_size
- 8, target_byte_order
);
890 return_valobj_sp
= ValueObjectConstResult::Create(
891 &thread
, return_compiler_type
, ConstString(""), return_ext
);
892 return return_valobj_sp
;
899 return_valobj_sp
= ValueObjectConstResult::Create(
900 thread
.GetStackFrameAtIndex(0).get(), value
, ConstString(""));
901 } else if (type_flags
& eTypeIsStructUnion
|| type_flags
& eTypeIsClass
||
902 type_flags
& eTypeIsVector
) {
903 // Any structure of up to 16 bytes in size is returned in the registers.
904 if (*byte_size
<= 16) {
905 WritableDataBufferSP
data_sp(new DataBufferHeap(16, 0));
906 DataExtractor
return_ext(data_sp
, target_byte_order
,
907 target
->GetArchitecture().GetAddressByteSize());
909 RegisterValue r2_value
, r3_value
, f0_value
, f1_value
, f2_value
;
910 // Tracks how much bytes of r2 and r3 registers we've consumed so far
911 uint32_t integer_bytes
= 0;
913 // True if return values are in FP return registers.
914 bool use_fp_regs
= false;
915 // True if we found any non floating point field in structure.
916 bool found_non_fp_field
= false;
917 // True if return values are in r2 register.
919 // True if return values are in r3 register.
921 // True if the result is copied into our data buffer
926 const uint32_t num_children
= return_compiler_type
.GetNumFields();
928 // A structure consisting of one or two FP values (and nothing else) will
929 // be returned in the two FP return-value registers i.e fp0 and fp2.
930 if (num_children
<= 2) {
931 uint64_t field_bit_offset
= 0;
933 // Check if this structure contains only floating point fields
934 for (uint32_t idx
= 0; idx
< num_children
; idx
++) {
935 CompilerType field_compiler_type
=
936 return_compiler_type
.GetFieldAtIndex(idx
, name
, &field_bit_offset
,
939 if (field_compiler_type
.IsFloatingPointType(count
, is_complex
))
942 found_non_fp_field
= true;
945 if (use_fp_regs
&& !found_non_fp_field
) {
946 // We have one or two FP-only values in this structure. Get it from
948 DataExtractor f0_data
, f1_data
, f2_data
;
949 const RegisterInfo
*f0_info
= reg_ctx
->GetRegisterInfoByName("f0", 0);
950 const RegisterInfo
*f1_info
= reg_ctx
->GetRegisterInfoByName("f1", 0);
951 const RegisterInfo
*f2_info
= reg_ctx
->GetRegisterInfoByName("f2", 0);
953 reg_ctx
->ReadRegister(f0_info
, f0_value
);
954 reg_ctx
->ReadRegister(f2_info
, f2_value
);
956 f0_value
.GetData(f0_data
);
958 for (uint32_t idx
= 0; idx
< num_children
; idx
++) {
959 CompilerType field_compiler_type
=
960 return_compiler_type
.GetFieldAtIndex(
961 idx
, name
, &field_bit_offset
, nullptr, nullptr);
962 std::optional
<uint64_t> field_byte_width
=
963 field_compiler_type
.GetByteSize(&thread
);
964 if (!field_byte_width
)
965 return return_valobj_sp
;
967 DataExtractor
*copy_from_extractor
= nullptr;
968 uint64_t return_value
[2];
972 // This case is for long double type.
973 if (*field_byte_width
== 16) {
975 // If structure contains long double type, then it is returned
976 // in fp0/fp1 registers.
977 if (target_byte_order
== eByteOrderLittle
) {
978 return_value
[0] = f0_data
.GetU64(&offset
);
979 reg_ctx
->ReadRegister(f1_info
, f1_value
);
980 f1_value
.GetData(f1_data
);
982 return_value
[1] = f1_data
.GetU64(&offset
);
984 return_value
[1] = f0_data
.GetU64(&offset
);
985 reg_ctx
->ReadRegister(f1_info
, f1_value
);
986 f1_value
.GetData(f1_data
);
988 return_value
[0] = f1_data
.GetU64(&offset
);
991 f0_data
.SetData(return_value
, *field_byte_width
,
994 copy_from_extractor
= &f0_data
; // This is in f0, copy from
995 // register to our result
998 f2_value
.GetData(f2_data
);
999 // This is in f2, copy from register to our result structure
1000 copy_from_extractor
= &f2_data
;
1003 // Sanity check to avoid crash
1004 if (!copy_from_extractor
||
1005 *field_byte_width
> copy_from_extractor
->GetByteSize())
1006 return return_valobj_sp
;
1008 // copy the register contents into our data buffer
1009 copy_from_extractor
->CopyByteOrderedData(
1010 0, *field_byte_width
,
1011 data_sp
->GetBytes() + (field_bit_offset
/ 8), *field_byte_width
,
1015 // The result is in our data buffer. Create a variable object out of
1017 return_valobj_sp
= ValueObjectConstResult::Create(
1018 &thread
, return_compiler_type
, ConstString(""), return_ext
);
1020 return return_valobj_sp
;
1024 // If we reach here, it means this structure either contains more than
1025 // two fields or it contains at least one non floating point type. In
1026 // that case, all fields are returned in GP return registers.
1027 for (uint32_t idx
= 0; idx
< num_children
; idx
++) {
1028 uint64_t field_bit_offset
= 0;
1032 CompilerType field_compiler_type
= return_compiler_type
.GetFieldAtIndex(
1033 idx
, name
, &field_bit_offset
, nullptr, nullptr);
1034 std::optional
<uint64_t> field_byte_width
=
1035 field_compiler_type
.GetByteSize(&thread
);
1037 // if we don't know the size of the field (e.g. invalid type), just
1039 if (!field_byte_width
|| *field_byte_width
== 0)
1042 uint32_t field_byte_offset
= field_bit_offset
/ 8;
1044 if (field_compiler_type
.IsIntegerOrEnumerationType(is_signed
) ||
1045 field_compiler_type
.IsPointerType() ||
1046 field_compiler_type
.IsFloatingPointType(count
, is_complex
)) {
1047 padding
= field_byte_offset
- integer_bytes
;
1049 if (integer_bytes
< 8) {
1050 // We have not yet consumed r2 completely.
1051 if (integer_bytes
+ *field_byte_width
+ padding
<= 8) {
1052 // This field fits in r2, copy its value from r2 to our result
1054 integer_bytes
= integer_bytes
+ *field_byte_width
+
1055 padding
; // Increase the consumed bytes.
1058 // There isn't enough space left in r2 for this field, so this
1060 integer_bytes
= integer_bytes
+ *field_byte_width
+
1061 padding
; // Increase the consumed bytes.
1065 // We already have consumed at-least 8 bytes that means r2 is done,
1066 // and this field will be in r3. Check if this field can fit in r3.
1067 else if (integer_bytes
+ *field_byte_width
+ padding
<= 16) {
1068 integer_bytes
= integer_bytes
+ *field_byte_width
+ padding
;
1071 // There isn't any space left for this field, this should not
1072 // happen as we have already checked the overall size is not
1073 // greater than 16 bytes. For now, return a nullptr return value
1075 return return_valobj_sp
;
1079 // Vector types up to 16 bytes are returned in GP return registers
1080 if (type_flags
& eTypeIsVector
) {
1081 if (*byte_size
<= 8)
1090 reg_ctx
->ReadRegister(r2_info
, r2_value
);
1092 const size_t bytes_copied
= r2_value
.GetAsMemoryData(
1093 *r2_info
, data_sp
->GetBytes(), r2_info
->byte_size
,
1094 target_byte_order
, error
);
1095 if (bytes_copied
!= r2_info
->byte_size
)
1096 return return_valobj_sp
;
1100 reg_ctx
->ReadRegister(r3_info
, r3_value
);
1101 const size_t bytes_copied
= r3_value
.GetAsMemoryData(
1102 *r3_info
, data_sp
->GetBytes() + r2_info
->byte_size
,
1103 r3_info
->byte_size
, target_byte_order
, error
);
1105 if (bytes_copied
!= r3_info
->byte_size
)
1106 return return_valobj_sp
;
1110 // The result is in our data buffer. Create a variable object out of
1112 return_valobj_sp
= ValueObjectConstResult::Create(
1113 &thread
, return_compiler_type
, ConstString(""), return_ext
);
1115 return return_valobj_sp
;
1118 // Any structure/vector greater than 16 bytes in size is returned in
1119 // memory. The pointer to that memory is returned in r2.
1120 uint64_t mem_address
= reg_ctx
->ReadRegisterAsUnsigned(
1121 reg_ctx
->GetRegisterInfoByName("r2", 0), 0);
1123 // We have got the address. Create a memory object out of it
1124 return_valobj_sp
= ValueObjectMemory::Create(
1125 &thread
, "", Address(mem_address
, nullptr), return_compiler_type
);
1127 return return_valobj_sp
;
1130 bool ABISysV_mips64::CreateFunctionEntryUnwindPlan(UnwindPlan
&unwind_plan
) {
1131 unwind_plan
.Clear();
1132 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
1134 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
1136 // Our Call Frame Address is the stack pointer value
1137 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29
, 0);
1139 // The previous PC is in the RA
1140 row
->SetRegisterLocationToRegister(dwarf_pc
, dwarf_r31
, true);
1141 unwind_plan
.AppendRow(row
);
1143 // All other registers are the same.
1145 unwind_plan
.SetSourceName("mips64 at-func-entry default");
1146 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
1147 unwind_plan
.SetReturnAddressRegister(dwarf_r31
);
1151 bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan
&unwind_plan
) {
1152 unwind_plan
.Clear();
1153 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
1155 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
1157 row
->SetUnspecifiedRegistersAreUndefined(true);
1158 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29
, 0);
1160 row
->SetRegisterLocationToRegister(dwarf_pc
, dwarf_r31
, true);
1162 unwind_plan
.AppendRow(row
);
1163 unwind_plan
.SetSourceName("mips64 default unwind plan");
1164 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
1165 unwind_plan
.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo
);
1166 unwind_plan
.SetUnwindPlanForSignalTrap(eLazyBoolNo
);
1170 bool ABISysV_mips64::RegisterIsVolatile(const RegisterInfo
*reg_info
) {
1171 return !RegisterIsCalleeSaved(reg_info
);
1174 bool ABISysV_mips64::IsSoftFloat(uint32_t fp_flag
) const {
1175 return (fp_flag
== lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT
);
1178 bool ABISysV_mips64::RegisterIsCalleeSaved(const RegisterInfo
*reg_info
) {
1180 // Preserved registers are :
1181 // r16-r23, r28, r29, r30, r31
1183 int reg
= ((reg_info
->byte_offset
) / 8);
1185 bool save
= (reg
>= 16) && (reg
<= 23);
1186 save
|= (reg
>= 28) && (reg
<= 31);
1193 void ABISysV_mips64::Initialize() {
1194 PluginManager::RegisterPlugin(
1195 GetPluginNameStatic(), "System V ABI for mips64 targets", CreateInstance
);
1198 void ABISysV_mips64::Terminate() {
1199 PluginManager::UnregisterPlugin(CreateInstance
);