xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- ABISysV_mips64.cpp ------------------------------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #include "ABISysV_mips64.h"
105ffd83dbSDimitry Andric 
115ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h"
12*06c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "lldb/Core/Module.h"
155ffd83dbSDimitry Andric #include "lldb/Core/PluginManager.h"
165ffd83dbSDimitry Andric #include "lldb/Core/Value.h"
175ffd83dbSDimitry Andric #include "lldb/Core/ValueObjectConstResult.h"
185ffd83dbSDimitry Andric #include "lldb/Core/ValueObjectMemory.h"
195ffd83dbSDimitry Andric #include "lldb/Core/ValueObjectRegister.h"
205ffd83dbSDimitry Andric #include "lldb/Symbol/UnwindPlan.h"
215ffd83dbSDimitry Andric #include "lldb/Target/Process.h"
225ffd83dbSDimitry Andric #include "lldb/Target/RegisterContext.h"
235ffd83dbSDimitry Andric #include "lldb/Target/StackFrame.h"
245ffd83dbSDimitry Andric #include "lldb/Target/Target.h"
255ffd83dbSDimitry Andric #include "lldb/Target/Thread.h"
265ffd83dbSDimitry Andric #include "lldb/Utility/ConstString.h"
275ffd83dbSDimitry Andric #include "lldb/Utility/DataExtractor.h"
2881ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
295ffd83dbSDimitry Andric #include "lldb/Utility/Log.h"
305ffd83dbSDimitry Andric #include "lldb/Utility/RegisterValue.h"
315ffd83dbSDimitry Andric #include "lldb/Utility/Status.h"
32bdd1243dSDimitry Andric #include <optional>
335ffd83dbSDimitry Andric 
345ffd83dbSDimitry Andric using namespace lldb;
355ffd83dbSDimitry Andric using namespace lldb_private;
365ffd83dbSDimitry Andric 
375ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(ABISysV_mips64)
385ffd83dbSDimitry Andric 
395ffd83dbSDimitry Andric enum dwarf_regnums {
405ffd83dbSDimitry Andric   dwarf_r0 = 0,
415ffd83dbSDimitry Andric   dwarf_r1,
425ffd83dbSDimitry Andric   dwarf_r2,
435ffd83dbSDimitry Andric   dwarf_r3,
445ffd83dbSDimitry Andric   dwarf_r4,
455ffd83dbSDimitry Andric   dwarf_r5,
465ffd83dbSDimitry Andric   dwarf_r6,
475ffd83dbSDimitry Andric   dwarf_r7,
485ffd83dbSDimitry Andric   dwarf_r8,
495ffd83dbSDimitry Andric   dwarf_r9,
505ffd83dbSDimitry Andric   dwarf_r10,
515ffd83dbSDimitry Andric   dwarf_r11,
525ffd83dbSDimitry Andric   dwarf_r12,
535ffd83dbSDimitry Andric   dwarf_r13,
545ffd83dbSDimitry Andric   dwarf_r14,
555ffd83dbSDimitry Andric   dwarf_r15,
565ffd83dbSDimitry Andric   dwarf_r16,
575ffd83dbSDimitry Andric   dwarf_r17,
585ffd83dbSDimitry Andric   dwarf_r18,
595ffd83dbSDimitry Andric   dwarf_r19,
605ffd83dbSDimitry Andric   dwarf_r20,
615ffd83dbSDimitry Andric   dwarf_r21,
625ffd83dbSDimitry Andric   dwarf_r22,
635ffd83dbSDimitry Andric   dwarf_r23,
645ffd83dbSDimitry Andric   dwarf_r24,
655ffd83dbSDimitry Andric   dwarf_r25,
665ffd83dbSDimitry Andric   dwarf_r26,
675ffd83dbSDimitry Andric   dwarf_r27,
685ffd83dbSDimitry Andric   dwarf_r28,
695ffd83dbSDimitry Andric   dwarf_r29,
705ffd83dbSDimitry Andric   dwarf_r30,
715ffd83dbSDimitry Andric   dwarf_r31,
725ffd83dbSDimitry Andric   dwarf_sr,
735ffd83dbSDimitry Andric   dwarf_lo,
745ffd83dbSDimitry Andric   dwarf_hi,
755ffd83dbSDimitry Andric   dwarf_bad,
765ffd83dbSDimitry Andric   dwarf_cause,
775ffd83dbSDimitry Andric   dwarf_pc
785ffd83dbSDimitry Andric };
795ffd83dbSDimitry Andric 
805ffd83dbSDimitry Andric static const RegisterInfo g_register_infos_mips64[] = {
815ffd83dbSDimitry Andric     //  NAME      ALT    SZ OFF ENCODING        FORMAT         EH_FRAME
825ffd83dbSDimitry Andric     //  DWARF                   GENERIC                     PROCESS PLUGIN
835ffd83dbSDimitry Andric     //  LLDB NATIVE
845ffd83dbSDimitry Andric     //  ========  ======  == === =============  ==========     =============
855ffd83dbSDimitry Andric     //  =================       ====================        =================
865ffd83dbSDimitry Andric     //  ====================
875ffd83dbSDimitry Andric     {"r0",
885ffd83dbSDimitry Andric      "zero",
895ffd83dbSDimitry Andric      8,
905ffd83dbSDimitry Andric      0,
915ffd83dbSDimitry Andric      eEncodingUint,
925ffd83dbSDimitry Andric      eFormatHex,
935ffd83dbSDimitry Andric      {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
945ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
955ffd83dbSDimitry Andric      nullptr,
965ffd83dbSDimitry Andric      nullptr,
97*06c3fb27SDimitry Andric      nullptr,
98349cc55cSDimitry Andric     },
995ffd83dbSDimitry Andric     {"r1",
1005ffd83dbSDimitry Andric      "AT",
1015ffd83dbSDimitry Andric      8,
1025ffd83dbSDimitry Andric      0,
1035ffd83dbSDimitry Andric      eEncodingUint,
1045ffd83dbSDimitry Andric      eFormatHex,
1055ffd83dbSDimitry Andric      {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
1065ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
1075ffd83dbSDimitry Andric      nullptr,
1085ffd83dbSDimitry Andric      nullptr,
109*06c3fb27SDimitry Andric      nullptr,
110*06c3fb27SDimitry Andric 
111349cc55cSDimitry Andric     },
1125ffd83dbSDimitry Andric     {"r2",
1135ffd83dbSDimitry Andric      "v0",
1145ffd83dbSDimitry Andric      8,
1155ffd83dbSDimitry Andric      0,
1165ffd83dbSDimitry Andric      eEncodingUint,
1175ffd83dbSDimitry Andric      eFormatHex,
1185ffd83dbSDimitry Andric      {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
1195ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
1205ffd83dbSDimitry Andric      nullptr,
1215ffd83dbSDimitry Andric      nullptr,
122*06c3fb27SDimitry Andric      nullptr,
123349cc55cSDimitry Andric     },
1245ffd83dbSDimitry Andric     {"r3",
1255ffd83dbSDimitry Andric      "v1",
1265ffd83dbSDimitry Andric      8,
1275ffd83dbSDimitry Andric      0,
1285ffd83dbSDimitry Andric      eEncodingUint,
1295ffd83dbSDimitry Andric      eFormatHex,
1305ffd83dbSDimitry Andric      {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
1315ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
1325ffd83dbSDimitry Andric      nullptr,
1335ffd83dbSDimitry Andric      nullptr,
134*06c3fb27SDimitry Andric      nullptr,
135349cc55cSDimitry Andric     },
1365ffd83dbSDimitry Andric     {"r4",
137349cc55cSDimitry Andric      nullptr,
1385ffd83dbSDimitry Andric      8,
1395ffd83dbSDimitry Andric      0,
1405ffd83dbSDimitry Andric      eEncodingUint,
1415ffd83dbSDimitry Andric      eFormatHex,
1425ffd83dbSDimitry Andric      {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
1435ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
1445ffd83dbSDimitry Andric      nullptr,
1455ffd83dbSDimitry Andric      nullptr,
146*06c3fb27SDimitry Andric      nullptr,
147349cc55cSDimitry Andric     },
1485ffd83dbSDimitry Andric     {"r5",
149349cc55cSDimitry Andric      nullptr,
1505ffd83dbSDimitry Andric      8,
1515ffd83dbSDimitry Andric      0,
1525ffd83dbSDimitry Andric      eEncodingUint,
1535ffd83dbSDimitry Andric      eFormatHex,
1545ffd83dbSDimitry Andric      {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
1555ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
1565ffd83dbSDimitry Andric      nullptr,
1575ffd83dbSDimitry Andric      nullptr,
158*06c3fb27SDimitry Andric      nullptr,
159349cc55cSDimitry Andric     },
1605ffd83dbSDimitry Andric     {"r6",
161349cc55cSDimitry Andric      nullptr,
1625ffd83dbSDimitry Andric      8,
1635ffd83dbSDimitry Andric      0,
1645ffd83dbSDimitry Andric      eEncodingUint,
1655ffd83dbSDimitry Andric      eFormatHex,
1665ffd83dbSDimitry Andric      {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
1675ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
1685ffd83dbSDimitry Andric      nullptr,
1695ffd83dbSDimitry Andric      nullptr,
170*06c3fb27SDimitry Andric      nullptr,
171349cc55cSDimitry Andric     },
1725ffd83dbSDimitry Andric     {"r7",
173349cc55cSDimitry Andric      nullptr,
1745ffd83dbSDimitry Andric      8,
1755ffd83dbSDimitry Andric      0,
1765ffd83dbSDimitry Andric      eEncodingUint,
1775ffd83dbSDimitry Andric      eFormatHex,
1785ffd83dbSDimitry Andric      {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
1795ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
1805ffd83dbSDimitry Andric      nullptr,
1815ffd83dbSDimitry Andric      nullptr,
182*06c3fb27SDimitry Andric      nullptr,
183349cc55cSDimitry Andric     },
1845ffd83dbSDimitry Andric     {"r8",
185349cc55cSDimitry Andric      nullptr,
1865ffd83dbSDimitry Andric      8,
1875ffd83dbSDimitry Andric      0,
1885ffd83dbSDimitry Andric      eEncodingUint,
1895ffd83dbSDimitry Andric      eFormatHex,
1905ffd83dbSDimitry Andric      {dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM,
1915ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
1925ffd83dbSDimitry Andric      nullptr,
1935ffd83dbSDimitry Andric      nullptr,
194*06c3fb27SDimitry Andric      nullptr,
195349cc55cSDimitry Andric     },
1965ffd83dbSDimitry Andric     {"r9",
197349cc55cSDimitry Andric      nullptr,
1985ffd83dbSDimitry Andric      8,
1995ffd83dbSDimitry Andric      0,
2005ffd83dbSDimitry Andric      eEncodingUint,
2015ffd83dbSDimitry Andric      eFormatHex,
2025ffd83dbSDimitry Andric      {dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM,
2035ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
2045ffd83dbSDimitry Andric      nullptr,
2055ffd83dbSDimitry Andric      nullptr,
206*06c3fb27SDimitry Andric      nullptr,
207349cc55cSDimitry Andric     },
2085ffd83dbSDimitry Andric     {"r10",
209349cc55cSDimitry Andric      nullptr,
2105ffd83dbSDimitry Andric      8,
2115ffd83dbSDimitry Andric      0,
2125ffd83dbSDimitry Andric      eEncodingUint,
2135ffd83dbSDimitry Andric      eFormatHex,
2145ffd83dbSDimitry Andric      {dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM,
2155ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
2165ffd83dbSDimitry Andric      nullptr,
2175ffd83dbSDimitry Andric      nullptr,
218*06c3fb27SDimitry Andric      nullptr,
219349cc55cSDimitry Andric     },
2205ffd83dbSDimitry Andric     {"r11",
221349cc55cSDimitry Andric      nullptr,
2225ffd83dbSDimitry Andric      8,
2235ffd83dbSDimitry Andric      0,
2245ffd83dbSDimitry Andric      eEncodingUint,
2255ffd83dbSDimitry Andric      eFormatHex,
2265ffd83dbSDimitry Andric      {dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM,
2275ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
2285ffd83dbSDimitry Andric      nullptr,
2295ffd83dbSDimitry Andric      nullptr,
230*06c3fb27SDimitry Andric      nullptr,
231349cc55cSDimitry Andric     },
2325ffd83dbSDimitry Andric     {"r12",
2335ffd83dbSDimitry Andric      nullptr,
2345ffd83dbSDimitry Andric      8,
2355ffd83dbSDimitry Andric      0,
2365ffd83dbSDimitry Andric      eEncodingUint,
2375ffd83dbSDimitry Andric      eFormatHex,
2385ffd83dbSDimitry Andric      {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2395ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
2405ffd83dbSDimitry Andric      nullptr,
2415ffd83dbSDimitry Andric      nullptr,
242*06c3fb27SDimitry Andric      nullptr,
243349cc55cSDimitry Andric     },
2445ffd83dbSDimitry Andric     {"r13",
2455ffd83dbSDimitry Andric      nullptr,
2465ffd83dbSDimitry Andric      8,
2475ffd83dbSDimitry Andric      0,
2485ffd83dbSDimitry Andric      eEncodingUint,
2495ffd83dbSDimitry Andric      eFormatHex,
2505ffd83dbSDimitry Andric      {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2515ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
2525ffd83dbSDimitry Andric      nullptr,
2535ffd83dbSDimitry Andric      nullptr,
254*06c3fb27SDimitry Andric      nullptr,
255349cc55cSDimitry Andric     },
2565ffd83dbSDimitry Andric     {"r14",
2575ffd83dbSDimitry Andric      nullptr,
2585ffd83dbSDimitry Andric      8,
2595ffd83dbSDimitry Andric      0,
2605ffd83dbSDimitry Andric      eEncodingUint,
2615ffd83dbSDimitry Andric      eFormatHex,
2625ffd83dbSDimitry Andric      {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2635ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
2645ffd83dbSDimitry Andric      nullptr,
2655ffd83dbSDimitry Andric      nullptr,
266*06c3fb27SDimitry Andric      nullptr,
267349cc55cSDimitry Andric     },
2685ffd83dbSDimitry Andric     {"r15",
2695ffd83dbSDimitry Andric      nullptr,
2705ffd83dbSDimitry Andric      8,
2715ffd83dbSDimitry Andric      0,
2725ffd83dbSDimitry Andric      eEncodingUint,
2735ffd83dbSDimitry Andric      eFormatHex,
2745ffd83dbSDimitry Andric      {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2755ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
2765ffd83dbSDimitry Andric      nullptr,
2775ffd83dbSDimitry Andric      nullptr,
278*06c3fb27SDimitry Andric      nullptr,
279349cc55cSDimitry Andric     },
2805ffd83dbSDimitry Andric     {"r16",
2815ffd83dbSDimitry Andric      nullptr,
2825ffd83dbSDimitry Andric      8,
2835ffd83dbSDimitry Andric      0,
2845ffd83dbSDimitry Andric      eEncodingUint,
2855ffd83dbSDimitry Andric      eFormatHex,
2865ffd83dbSDimitry Andric      {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2875ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
2885ffd83dbSDimitry Andric      nullptr,
2895ffd83dbSDimitry Andric      nullptr,
290*06c3fb27SDimitry Andric      nullptr,
291349cc55cSDimitry Andric     },
2925ffd83dbSDimitry Andric     {"r17",
2935ffd83dbSDimitry Andric      nullptr,
2945ffd83dbSDimitry Andric      8,
2955ffd83dbSDimitry Andric      0,
2965ffd83dbSDimitry Andric      eEncodingUint,
2975ffd83dbSDimitry Andric      eFormatHex,
2985ffd83dbSDimitry Andric      {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2995ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
3005ffd83dbSDimitry Andric      nullptr,
3015ffd83dbSDimitry Andric      nullptr,
302*06c3fb27SDimitry Andric      nullptr,
303349cc55cSDimitry Andric     },
3045ffd83dbSDimitry Andric     {"r18",
3055ffd83dbSDimitry Andric      nullptr,
3065ffd83dbSDimitry Andric      8,
3075ffd83dbSDimitry Andric      0,
3085ffd83dbSDimitry Andric      eEncodingUint,
3095ffd83dbSDimitry Andric      eFormatHex,
3105ffd83dbSDimitry Andric      {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3115ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
3125ffd83dbSDimitry Andric      nullptr,
3135ffd83dbSDimitry Andric      nullptr,
314*06c3fb27SDimitry Andric      nullptr,
315349cc55cSDimitry Andric     },
3165ffd83dbSDimitry Andric     {"r19",
3175ffd83dbSDimitry Andric      nullptr,
3185ffd83dbSDimitry Andric      8,
3195ffd83dbSDimitry Andric      0,
3205ffd83dbSDimitry Andric      eEncodingUint,
3215ffd83dbSDimitry Andric      eFormatHex,
3225ffd83dbSDimitry Andric      {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3235ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
3245ffd83dbSDimitry Andric      nullptr,
3255ffd83dbSDimitry Andric      nullptr,
326*06c3fb27SDimitry Andric      nullptr,
327349cc55cSDimitry Andric     },
3285ffd83dbSDimitry Andric     {"r20",
3295ffd83dbSDimitry Andric      nullptr,
3305ffd83dbSDimitry Andric      8,
3315ffd83dbSDimitry Andric      0,
3325ffd83dbSDimitry Andric      eEncodingUint,
3335ffd83dbSDimitry Andric      eFormatHex,
3345ffd83dbSDimitry Andric      {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3355ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
3365ffd83dbSDimitry Andric      nullptr,
3375ffd83dbSDimitry Andric      nullptr,
338*06c3fb27SDimitry Andric      nullptr,
339349cc55cSDimitry Andric     },
3405ffd83dbSDimitry Andric     {"r21",
3415ffd83dbSDimitry Andric      nullptr,
3425ffd83dbSDimitry Andric      8,
3435ffd83dbSDimitry Andric      0,
3445ffd83dbSDimitry Andric      eEncodingUint,
3455ffd83dbSDimitry Andric      eFormatHex,
3465ffd83dbSDimitry Andric      {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3475ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
3485ffd83dbSDimitry Andric      nullptr,
3495ffd83dbSDimitry Andric      nullptr,
350*06c3fb27SDimitry Andric      nullptr,
351349cc55cSDimitry Andric     },
3525ffd83dbSDimitry Andric     {"r22",
3535ffd83dbSDimitry Andric      nullptr,
3545ffd83dbSDimitry Andric      8,
3555ffd83dbSDimitry Andric      0,
3565ffd83dbSDimitry Andric      eEncodingUint,
3575ffd83dbSDimitry Andric      eFormatHex,
3585ffd83dbSDimitry Andric      {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3595ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
3605ffd83dbSDimitry Andric      nullptr,
3615ffd83dbSDimitry Andric      nullptr,
362*06c3fb27SDimitry Andric      nullptr,
363349cc55cSDimitry Andric     },
3645ffd83dbSDimitry Andric     {"r23",
3655ffd83dbSDimitry Andric      nullptr,
3665ffd83dbSDimitry Andric      8,
3675ffd83dbSDimitry Andric      0,
3685ffd83dbSDimitry Andric      eEncodingUint,
3695ffd83dbSDimitry Andric      eFormatHex,
3705ffd83dbSDimitry Andric      {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3715ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
3725ffd83dbSDimitry Andric      nullptr,
3735ffd83dbSDimitry Andric      nullptr,
374*06c3fb27SDimitry Andric      nullptr,
375349cc55cSDimitry Andric     },
3765ffd83dbSDimitry Andric     {"r24",
3775ffd83dbSDimitry Andric      nullptr,
3785ffd83dbSDimitry Andric      8,
3795ffd83dbSDimitry Andric      0,
3805ffd83dbSDimitry Andric      eEncodingUint,
3815ffd83dbSDimitry Andric      eFormatHex,
3825ffd83dbSDimitry Andric      {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3835ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
3845ffd83dbSDimitry Andric      nullptr,
3855ffd83dbSDimitry Andric      nullptr,
386*06c3fb27SDimitry Andric      nullptr,
387349cc55cSDimitry Andric     },
3885ffd83dbSDimitry Andric     {"r25",
3895ffd83dbSDimitry Andric      nullptr,
3905ffd83dbSDimitry Andric      8,
3915ffd83dbSDimitry Andric      0,
3925ffd83dbSDimitry Andric      eEncodingUint,
3935ffd83dbSDimitry Andric      eFormatHex,
3945ffd83dbSDimitry Andric      {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3955ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
3965ffd83dbSDimitry Andric      nullptr,
3975ffd83dbSDimitry Andric      nullptr,
398*06c3fb27SDimitry Andric      nullptr,
399349cc55cSDimitry Andric     },
4005ffd83dbSDimitry Andric     {"r26",
4015ffd83dbSDimitry Andric      nullptr,
4025ffd83dbSDimitry Andric      8,
4035ffd83dbSDimitry Andric      0,
4045ffd83dbSDimitry Andric      eEncodingUint,
4055ffd83dbSDimitry Andric      eFormatHex,
4065ffd83dbSDimitry Andric      {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
4075ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
4085ffd83dbSDimitry Andric      nullptr,
4095ffd83dbSDimitry Andric      nullptr,
410*06c3fb27SDimitry Andric      nullptr,
411349cc55cSDimitry Andric     },
4125ffd83dbSDimitry Andric     {"r27",
4135ffd83dbSDimitry Andric      nullptr,
4145ffd83dbSDimitry Andric      8,
4155ffd83dbSDimitry Andric      0,
4165ffd83dbSDimitry Andric      eEncodingUint,
4175ffd83dbSDimitry Andric      eFormatHex,
4185ffd83dbSDimitry Andric      {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
4195ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
4205ffd83dbSDimitry Andric      nullptr,
4215ffd83dbSDimitry Andric      nullptr,
422*06c3fb27SDimitry Andric      nullptr,
423349cc55cSDimitry Andric     },
4245ffd83dbSDimitry Andric     {"r28",
4255ffd83dbSDimitry Andric      "gp",
4265ffd83dbSDimitry Andric      8,
4275ffd83dbSDimitry Andric      0,
4285ffd83dbSDimitry Andric      eEncodingUint,
4295ffd83dbSDimitry Andric      eFormatHex,
4305ffd83dbSDimitry Andric      {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
4315ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
4325ffd83dbSDimitry Andric      nullptr,
4335ffd83dbSDimitry Andric      nullptr,
434*06c3fb27SDimitry Andric      nullptr,
435349cc55cSDimitry Andric     },
4365ffd83dbSDimitry Andric     {"r29",
437349cc55cSDimitry Andric      nullptr,
4385ffd83dbSDimitry Andric      8,
4395ffd83dbSDimitry Andric      0,
4405ffd83dbSDimitry Andric      eEncodingUint,
4415ffd83dbSDimitry Andric      eFormatHex,
4425ffd83dbSDimitry Andric      {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
4435ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
4445ffd83dbSDimitry Andric      nullptr,
4455ffd83dbSDimitry Andric      nullptr,
446*06c3fb27SDimitry Andric      nullptr,
447349cc55cSDimitry Andric     },
4485ffd83dbSDimitry Andric     {"r30",
449349cc55cSDimitry Andric      nullptr,
4505ffd83dbSDimitry Andric      8,
4515ffd83dbSDimitry Andric      0,
4525ffd83dbSDimitry Andric      eEncodingUint,
4535ffd83dbSDimitry Andric      eFormatHex,
4545ffd83dbSDimitry Andric      {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
4555ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
4565ffd83dbSDimitry Andric      nullptr,
4575ffd83dbSDimitry Andric      nullptr,
458*06c3fb27SDimitry Andric      nullptr,
459349cc55cSDimitry Andric     },
4605ffd83dbSDimitry Andric     {"r31",
461349cc55cSDimitry Andric      nullptr,
4625ffd83dbSDimitry Andric      8,
4635ffd83dbSDimitry Andric      0,
4645ffd83dbSDimitry Andric      eEncodingUint,
4655ffd83dbSDimitry Andric      eFormatHex,
4665ffd83dbSDimitry Andric      {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
4675ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
4685ffd83dbSDimitry Andric      nullptr,
4695ffd83dbSDimitry Andric      nullptr,
470*06c3fb27SDimitry Andric      nullptr,
471349cc55cSDimitry Andric     },
4725ffd83dbSDimitry Andric     {"sr",
4735ffd83dbSDimitry Andric      nullptr,
4745ffd83dbSDimitry Andric      4,
4755ffd83dbSDimitry Andric      0,
4765ffd83dbSDimitry Andric      eEncodingUint,
4775ffd83dbSDimitry Andric      eFormatHex,
4785ffd83dbSDimitry Andric      {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
4795ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
4805ffd83dbSDimitry Andric      nullptr,
4815ffd83dbSDimitry Andric      nullptr,
482*06c3fb27SDimitry Andric      nullptr,
483349cc55cSDimitry Andric     },
4845ffd83dbSDimitry Andric     {"lo",
4855ffd83dbSDimitry Andric      nullptr,
4865ffd83dbSDimitry Andric      8,
4875ffd83dbSDimitry Andric      0,
4885ffd83dbSDimitry Andric      eEncodingUint,
4895ffd83dbSDimitry Andric      eFormatHex,
4905ffd83dbSDimitry Andric      {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
4915ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
4925ffd83dbSDimitry Andric      nullptr,
4935ffd83dbSDimitry Andric      nullptr,
494*06c3fb27SDimitry Andric      nullptr,
495349cc55cSDimitry Andric     },
4965ffd83dbSDimitry Andric     {"hi",
4975ffd83dbSDimitry Andric      nullptr,
4985ffd83dbSDimitry Andric      8,
4995ffd83dbSDimitry Andric      0,
5005ffd83dbSDimitry Andric      eEncodingUint,
5015ffd83dbSDimitry Andric      eFormatHex,
5025ffd83dbSDimitry Andric      {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
5035ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
5045ffd83dbSDimitry Andric      nullptr,
5055ffd83dbSDimitry Andric      nullptr,
506*06c3fb27SDimitry Andric      nullptr,
507349cc55cSDimitry Andric     },
5085ffd83dbSDimitry Andric     {"bad",
5095ffd83dbSDimitry Andric      nullptr,
5105ffd83dbSDimitry Andric      8,
5115ffd83dbSDimitry Andric      0,
5125ffd83dbSDimitry Andric      eEncodingUint,
5135ffd83dbSDimitry Andric      eFormatHex,
5145ffd83dbSDimitry Andric      {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
5155ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
5165ffd83dbSDimitry Andric      nullptr,
5175ffd83dbSDimitry Andric      nullptr,
518*06c3fb27SDimitry Andric      nullptr,
519349cc55cSDimitry Andric     },
5205ffd83dbSDimitry Andric     {"cause",
5215ffd83dbSDimitry Andric      nullptr,
5225ffd83dbSDimitry Andric      8,
5235ffd83dbSDimitry Andric      0,
5245ffd83dbSDimitry Andric      eEncodingUint,
5255ffd83dbSDimitry Andric      eFormatHex,
5265ffd83dbSDimitry Andric      {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
5275ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
5285ffd83dbSDimitry Andric      nullptr,
5295ffd83dbSDimitry Andric      nullptr,
530*06c3fb27SDimitry Andric      nullptr,
531349cc55cSDimitry Andric     },
5325ffd83dbSDimitry Andric     {"pc",
5335ffd83dbSDimitry Andric      nullptr,
5345ffd83dbSDimitry Andric      8,
5355ffd83dbSDimitry Andric      0,
5365ffd83dbSDimitry Andric      eEncodingUint,
5375ffd83dbSDimitry Andric      eFormatHex,
5385ffd83dbSDimitry Andric      {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
5395ffd83dbSDimitry Andric       LLDB_INVALID_REGNUM},
5405ffd83dbSDimitry Andric      nullptr,
5415ffd83dbSDimitry Andric      nullptr,
542*06c3fb27SDimitry Andric      nullptr,
543349cc55cSDimitry Andric     },
5445ffd83dbSDimitry Andric };
5455ffd83dbSDimitry Andric 
546bdd1243dSDimitry Andric static const uint32_t k_num_register_infos = std::size(g_register_infos_mips64);
5475ffd83dbSDimitry Andric 
5485ffd83dbSDimitry Andric const lldb_private::RegisterInfo *
GetRegisterInfoArray(uint32_t & count)5495ffd83dbSDimitry Andric ABISysV_mips64::GetRegisterInfoArray(uint32_t &count) {
5505ffd83dbSDimitry Andric   count = k_num_register_infos;
5515ffd83dbSDimitry Andric   return g_register_infos_mips64;
5525ffd83dbSDimitry Andric }
5535ffd83dbSDimitry Andric 
GetRedZoneSize() const5545ffd83dbSDimitry Andric size_t ABISysV_mips64::GetRedZoneSize() const { return 0; }
5555ffd83dbSDimitry Andric 
5565ffd83dbSDimitry Andric // Static Functions
5575ffd83dbSDimitry Andric 
5585ffd83dbSDimitry Andric ABISP
CreateInstance(lldb::ProcessSP process_sp,const ArchSpec & arch)5595ffd83dbSDimitry Andric ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
5605ffd83dbSDimitry Andric   if (arch.GetTriple().isMIPS64())
5615ffd83dbSDimitry Andric     return ABISP(
5625ffd83dbSDimitry Andric         new ABISysV_mips64(std::move(process_sp), MakeMCRegisterInfo(arch)));
5635ffd83dbSDimitry Andric   return ABISP();
5645ffd83dbSDimitry Andric }
5655ffd83dbSDimitry Andric 
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,llvm::ArrayRef<addr_t> args) const5665ffd83dbSDimitry Andric bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp,
5675ffd83dbSDimitry Andric                                         addr_t func_addr, addr_t return_addr,
5685ffd83dbSDimitry Andric                                         llvm::ArrayRef<addr_t> args) const {
56981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Expressions);
5705ffd83dbSDimitry Andric 
5715ffd83dbSDimitry Andric   if (log) {
5725ffd83dbSDimitry Andric     StreamString s;
5735ffd83dbSDimitry Andric     s.Printf("ABISysV_mips64::PrepareTrivialCall (tid = 0x%" PRIx64
5745ffd83dbSDimitry Andric              ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
5755ffd83dbSDimitry Andric              ", return_addr = 0x%" PRIx64,
5765ffd83dbSDimitry Andric              thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
5775ffd83dbSDimitry Andric              (uint64_t)return_addr);
5785ffd83dbSDimitry Andric 
5795ffd83dbSDimitry Andric     for (size_t i = 0; i < args.size(); ++i)
5805ffd83dbSDimitry Andric       s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
5815ffd83dbSDimitry Andric     s.PutCString(")");
5825ffd83dbSDimitry Andric     log->PutString(s.GetString());
5835ffd83dbSDimitry Andric   }
5845ffd83dbSDimitry Andric 
5855ffd83dbSDimitry Andric   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
5865ffd83dbSDimitry Andric   if (!reg_ctx)
5875ffd83dbSDimitry Andric     return false;
5885ffd83dbSDimitry Andric 
5895ffd83dbSDimitry Andric   const RegisterInfo *reg_info = nullptr;
5905ffd83dbSDimitry Andric 
5915ffd83dbSDimitry Andric   if (args.size() > 8) // TODO handle more than 8 arguments
5925ffd83dbSDimitry Andric     return false;
5935ffd83dbSDimitry Andric 
5945ffd83dbSDimitry Andric   for (size_t i = 0; i < args.size(); ++i) {
5955ffd83dbSDimitry Andric     reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
5965ffd83dbSDimitry Andric                                         LLDB_REGNUM_GENERIC_ARG1 + i);
5975ffd83dbSDimitry Andric     LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
5985ffd83dbSDimitry Andric               args[i], reg_info->name);
5995ffd83dbSDimitry Andric     if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
6005ffd83dbSDimitry Andric       return false;
6015ffd83dbSDimitry Andric   }
6025ffd83dbSDimitry Andric 
6035ffd83dbSDimitry Andric   // First, align the SP
6045ffd83dbSDimitry Andric 
6055ffd83dbSDimitry Andric   LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64,
6065ffd83dbSDimitry Andric             (uint64_t)sp, (uint64_t)(sp & ~0xfull));
6075ffd83dbSDimitry Andric 
6085ffd83dbSDimitry Andric   sp &= ~(0xfull); // 16-byte alignment
6095ffd83dbSDimitry Andric 
6105ffd83dbSDimitry Andric   Status error;
6115ffd83dbSDimitry Andric   const RegisterInfo *pc_reg_info =
6125ffd83dbSDimitry Andric       reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6135ffd83dbSDimitry Andric   const RegisterInfo *sp_reg_info =
6145ffd83dbSDimitry Andric       reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
6155ffd83dbSDimitry Andric   const RegisterInfo *ra_reg_info =
6165ffd83dbSDimitry Andric       reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
6175ffd83dbSDimitry Andric   const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
6185ffd83dbSDimitry Andric   const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
6195ffd83dbSDimitry Andric 
6205ffd83dbSDimitry Andric   LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
6215ffd83dbSDimitry Andric 
6225ffd83dbSDimitry Andric   /* Write r0 with 0, in case we are stopped in syscall,
6235ffd83dbSDimitry Andric    * such setting prevents automatic decrement of the PC.
6245ffd83dbSDimitry Andric    * This clears the bug 23659 for MIPS.
6255ffd83dbSDimitry Andric   */
6265ffd83dbSDimitry Andric   if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
6275ffd83dbSDimitry Andric     return false;
6285ffd83dbSDimitry Andric 
6295ffd83dbSDimitry Andric   LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
6305ffd83dbSDimitry Andric 
6315ffd83dbSDimitry Andric   // Set "sp" to the requested value
6325ffd83dbSDimitry Andric   if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
6335ffd83dbSDimitry Andric     return false;
6345ffd83dbSDimitry Andric 
6355ffd83dbSDimitry Andric   LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
6365ffd83dbSDimitry Andric 
6375ffd83dbSDimitry Andric   // Set "ra" to the return address
6385ffd83dbSDimitry Andric   if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
6395ffd83dbSDimitry Andric     return false;
6405ffd83dbSDimitry Andric 
6415ffd83dbSDimitry Andric   LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
6425ffd83dbSDimitry Andric 
6435ffd83dbSDimitry Andric   // Set pc to the address of the called function.
6445ffd83dbSDimitry Andric   if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
6455ffd83dbSDimitry Andric     return false;
6465ffd83dbSDimitry Andric 
6475ffd83dbSDimitry Andric   LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
6485ffd83dbSDimitry Andric 
6495ffd83dbSDimitry Andric   // All callers of position independent functions must place the address of
6505ffd83dbSDimitry Andric   // the called function in t9 (r25)
6515ffd83dbSDimitry Andric   if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
6525ffd83dbSDimitry Andric     return false;
6535ffd83dbSDimitry Andric 
6545ffd83dbSDimitry Andric   return true;
6555ffd83dbSDimitry Andric }
6565ffd83dbSDimitry Andric 
GetArgumentValues(Thread & thread,ValueList & values) const6575ffd83dbSDimitry Andric bool ABISysV_mips64::GetArgumentValues(Thread &thread,
6585ffd83dbSDimitry Andric                                        ValueList &values) const {
6595ffd83dbSDimitry Andric   return false;
6605ffd83dbSDimitry Andric }
6615ffd83dbSDimitry Andric 
SetReturnValueObject(lldb::StackFrameSP & frame_sp,lldb::ValueObjectSP & new_value_sp)6625ffd83dbSDimitry Andric Status ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
6635ffd83dbSDimitry Andric                                             lldb::ValueObjectSP &new_value_sp) {
6645ffd83dbSDimitry Andric   Status error;
6655ffd83dbSDimitry Andric   if (!new_value_sp) {
6665ffd83dbSDimitry Andric     error.SetErrorString("Empty value object for return value.");
6675ffd83dbSDimitry Andric     return error;
6685ffd83dbSDimitry Andric   }
6695ffd83dbSDimitry Andric 
6705ffd83dbSDimitry Andric   CompilerType compiler_type = new_value_sp->GetCompilerType();
6715ffd83dbSDimitry Andric   if (!compiler_type) {
6725ffd83dbSDimitry Andric     error.SetErrorString("Null clang type for return value.");
6735ffd83dbSDimitry Andric     return error;
6745ffd83dbSDimitry Andric   }
6755ffd83dbSDimitry Andric 
6765ffd83dbSDimitry Andric   Thread *thread = frame_sp->GetThread().get();
6775ffd83dbSDimitry Andric 
6785ffd83dbSDimitry Andric   RegisterContext *reg_ctx = thread->GetRegisterContext().get();
6795ffd83dbSDimitry Andric 
6805ffd83dbSDimitry Andric   if (!reg_ctx)
6815ffd83dbSDimitry Andric     error.SetErrorString("no registers are available");
6825ffd83dbSDimitry Andric 
6835ffd83dbSDimitry Andric   DataExtractor data;
6845ffd83dbSDimitry Andric   Status data_error;
6855ffd83dbSDimitry Andric   size_t num_bytes = new_value_sp->GetData(data, data_error);
6865ffd83dbSDimitry Andric   if (data_error.Fail()) {
6875ffd83dbSDimitry Andric     error.SetErrorStringWithFormat(
6885ffd83dbSDimitry Andric         "Couldn't convert return value to raw data: %s",
6895ffd83dbSDimitry Andric         data_error.AsCString());
6905ffd83dbSDimitry Andric     return error;
6915ffd83dbSDimitry Andric   }
6925ffd83dbSDimitry Andric 
6935ffd83dbSDimitry Andric   const uint32_t type_flags = compiler_type.GetTypeInfo(nullptr);
6945ffd83dbSDimitry Andric 
6955ffd83dbSDimitry Andric   if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
6965ffd83dbSDimitry Andric     if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
6975ffd83dbSDimitry Andric       lldb::offset_t offset = 0;
6985ffd83dbSDimitry Andric 
6995ffd83dbSDimitry Andric       if (num_bytes <= 16) {
7005ffd83dbSDimitry Andric         const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
7015ffd83dbSDimitry Andric         if (num_bytes <= 8) {
7025ffd83dbSDimitry Andric           uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
7035ffd83dbSDimitry Andric 
7045ffd83dbSDimitry Andric           if (!reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
7055ffd83dbSDimitry Andric             error.SetErrorString("failed to write register r2");
7065ffd83dbSDimitry Andric         } else {
7075ffd83dbSDimitry Andric           uint64_t raw_value = data.GetMaxU64(&offset, 8);
7085ffd83dbSDimitry Andric           if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
7095ffd83dbSDimitry Andric             const RegisterInfo *r3_info =
7105ffd83dbSDimitry Andric                 reg_ctx->GetRegisterInfoByName("r3", 0);
7115ffd83dbSDimitry Andric             raw_value = data.GetMaxU64(&offset, num_bytes - offset);
7125ffd83dbSDimitry Andric 
7135ffd83dbSDimitry Andric             if (!reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
7145ffd83dbSDimitry Andric               error.SetErrorString("failed to write register r3");
7155ffd83dbSDimitry Andric           } else
7165ffd83dbSDimitry Andric             error.SetErrorString("failed to write register r2");
7175ffd83dbSDimitry Andric         }
7185ffd83dbSDimitry Andric       } else {
7195ffd83dbSDimitry Andric         error.SetErrorString("We don't support returning longer than 128 bit "
7205ffd83dbSDimitry Andric                              "integer values at present.");
7215ffd83dbSDimitry Andric       }
7225ffd83dbSDimitry Andric     } else if (type_flags & eTypeIsFloat) {
7235ffd83dbSDimitry Andric       error.SetErrorString("TODO: Handle Float Types.");
7245ffd83dbSDimitry Andric     }
7255ffd83dbSDimitry Andric   } else if (type_flags & eTypeIsVector) {
7265ffd83dbSDimitry Andric     error.SetErrorString("returning vector values are not supported");
7275ffd83dbSDimitry Andric   }
7285ffd83dbSDimitry Andric 
7295ffd83dbSDimitry Andric   return error;
7305ffd83dbSDimitry Andric }
7315ffd83dbSDimitry Andric 
GetReturnValueObjectSimple(Thread & thread,CompilerType & return_compiler_type) const7325ffd83dbSDimitry Andric ValueObjectSP ABISysV_mips64::GetReturnValueObjectSimple(
7335ffd83dbSDimitry Andric     Thread &thread, CompilerType &return_compiler_type) const {
7345ffd83dbSDimitry Andric   ValueObjectSP return_valobj_sp;
7355ffd83dbSDimitry Andric   return return_valobj_sp;
7365ffd83dbSDimitry Andric }
7375ffd83dbSDimitry Andric 
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const7385ffd83dbSDimitry Andric ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
7395ffd83dbSDimitry Andric     Thread &thread, CompilerType &return_compiler_type) const {
7405ffd83dbSDimitry Andric   ValueObjectSP return_valobj_sp;
7415ffd83dbSDimitry Andric   Value value;
7425ffd83dbSDimitry Andric   Status error;
7435ffd83dbSDimitry Andric 
7445ffd83dbSDimitry Andric   ExecutionContext exe_ctx(thread.shared_from_this());
7455ffd83dbSDimitry Andric   if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
7465ffd83dbSDimitry Andric     return return_valobj_sp;
7475ffd83dbSDimitry Andric 
7485ffd83dbSDimitry Andric   value.SetCompilerType(return_compiler_type);
7495ffd83dbSDimitry Andric 
7505ffd83dbSDimitry Andric   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
7515ffd83dbSDimitry Andric   if (!reg_ctx)
7525ffd83dbSDimitry Andric     return return_valobj_sp;
7535ffd83dbSDimitry Andric 
7545ffd83dbSDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
7555ffd83dbSDimitry Andric   const ArchSpec target_arch = target->GetArchitecture();
7565ffd83dbSDimitry Andric   ByteOrder target_byte_order = target_arch.GetByteOrder();
757bdd1243dSDimitry Andric   std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread);
7585ffd83dbSDimitry Andric   if (!byte_size)
7595ffd83dbSDimitry Andric     return return_valobj_sp;
7605ffd83dbSDimitry Andric   const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
7615ffd83dbSDimitry Andric   uint32_t fp_flag =
7625ffd83dbSDimitry Andric       target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
7635ffd83dbSDimitry Andric 
7645ffd83dbSDimitry Andric   const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
7655ffd83dbSDimitry Andric   const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
766bdd1243dSDimitry Andric   assert(r2_info && r3_info && "Basic registers should always be present.");
7675ffd83dbSDimitry Andric 
7685ffd83dbSDimitry Andric   if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
769fe6060f1SDimitry Andric     value.SetValueType(Value::ValueType::Scalar);
7705ffd83dbSDimitry Andric 
7715ffd83dbSDimitry Andric     bool success = false;
7725ffd83dbSDimitry Andric     if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
7735ffd83dbSDimitry Andric       // Extract the register context so we can read arguments from registers
7745ffd83dbSDimitry Andric       // In MIPS register "r2" (v0) holds the integer function return values
7755ffd83dbSDimitry Andric 
7765ffd83dbSDimitry Andric       uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
7775ffd83dbSDimitry Andric 
7785ffd83dbSDimitry Andric       const bool is_signed = (type_flags & eTypeIsSigned) != 0;
7795ffd83dbSDimitry Andric       switch (*byte_size) {
7805ffd83dbSDimitry Andric       default:
7815ffd83dbSDimitry Andric         break;
7825ffd83dbSDimitry Andric 
7835ffd83dbSDimitry Andric       case sizeof(uint64_t):
7845ffd83dbSDimitry Andric         if (is_signed)
7855ffd83dbSDimitry Andric           value.GetScalar() = (int64_t)(raw_value);
7865ffd83dbSDimitry Andric         else
7875ffd83dbSDimitry Andric           value.GetScalar() = (uint64_t)(raw_value);
7885ffd83dbSDimitry Andric         success = true;
7895ffd83dbSDimitry Andric         break;
7905ffd83dbSDimitry Andric 
7915ffd83dbSDimitry Andric       case sizeof(uint32_t):
7925ffd83dbSDimitry Andric         if (is_signed)
7935ffd83dbSDimitry Andric           value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
7945ffd83dbSDimitry Andric         else
7955ffd83dbSDimitry Andric           value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
7965ffd83dbSDimitry Andric         success = true;
7975ffd83dbSDimitry Andric         break;
7985ffd83dbSDimitry Andric 
7995ffd83dbSDimitry Andric       case sizeof(uint16_t):
8005ffd83dbSDimitry Andric         if (is_signed)
8015ffd83dbSDimitry Andric           value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
8025ffd83dbSDimitry Andric         else
8035ffd83dbSDimitry Andric           value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
8045ffd83dbSDimitry Andric         success = true;
8055ffd83dbSDimitry Andric         break;
8065ffd83dbSDimitry Andric 
8075ffd83dbSDimitry Andric       case sizeof(uint8_t):
8085ffd83dbSDimitry Andric         if (is_signed)
8095ffd83dbSDimitry Andric           value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
8105ffd83dbSDimitry Andric         else
8115ffd83dbSDimitry Andric           value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
8125ffd83dbSDimitry Andric         success = true;
8135ffd83dbSDimitry Andric         break;
8145ffd83dbSDimitry Andric       }
8155ffd83dbSDimitry Andric     } else if (type_flags & eTypeIsFloat) {
8165ffd83dbSDimitry Andric       if (type_flags & eTypeIsComplex) {
8175ffd83dbSDimitry Andric         // Don't handle complex yet.
8185ffd83dbSDimitry Andric       } else if (IsSoftFloat(fp_flag)) {
8195ffd83dbSDimitry Andric         uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
8205ffd83dbSDimitry Andric         switch (*byte_size) {
8215ffd83dbSDimitry Andric         case 4:
8225ffd83dbSDimitry Andric           value.GetScalar() = *((float *)(&raw_value));
8235ffd83dbSDimitry Andric           success = true;
8245ffd83dbSDimitry Andric           break;
8255ffd83dbSDimitry Andric         case 8:
8265ffd83dbSDimitry Andric           value.GetScalar() = *((double *)(&raw_value));
8275ffd83dbSDimitry Andric           success = true;
8285ffd83dbSDimitry Andric           break;
8295ffd83dbSDimitry Andric         case 16:
8305ffd83dbSDimitry Andric           uint64_t result[2];
8315ffd83dbSDimitry Andric           if (target_byte_order == eByteOrderLittle) {
8325ffd83dbSDimitry Andric             result[0] = raw_value;
8335ffd83dbSDimitry Andric             result[1] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);
8345ffd83dbSDimitry Andric             value.GetScalar() = *((long double *)(result));
8355ffd83dbSDimitry Andric           } else {
8365ffd83dbSDimitry Andric             result[0] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);
8375ffd83dbSDimitry Andric             result[1] = raw_value;
8385ffd83dbSDimitry Andric             value.GetScalar() = *((long double *)(result));
8395ffd83dbSDimitry Andric           }
8405ffd83dbSDimitry Andric           success = true;
8415ffd83dbSDimitry Andric           break;
8425ffd83dbSDimitry Andric         }
8435ffd83dbSDimitry Andric 
8445ffd83dbSDimitry Andric       } else {
8455ffd83dbSDimitry Andric         if (*byte_size <= sizeof(long double)) {
8465ffd83dbSDimitry Andric           const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
8475ffd83dbSDimitry Andric 
8485ffd83dbSDimitry Andric           RegisterValue f0_value;
8495ffd83dbSDimitry Andric           DataExtractor f0_data;
8505ffd83dbSDimitry Andric 
8515ffd83dbSDimitry Andric           reg_ctx->ReadRegister(f0_info, f0_value);
8525ffd83dbSDimitry Andric 
8535ffd83dbSDimitry Andric           f0_value.GetData(f0_data);
8545ffd83dbSDimitry Andric 
8555ffd83dbSDimitry Andric           lldb::offset_t offset = 0;
8565ffd83dbSDimitry Andric           if (*byte_size == sizeof(float)) {
8575ffd83dbSDimitry Andric             value.GetScalar() = (float)f0_data.GetFloat(&offset);
8585ffd83dbSDimitry Andric             success = true;
8595ffd83dbSDimitry Andric           } else if (*byte_size == sizeof(double)) {
8605ffd83dbSDimitry Andric             value.GetScalar() = (double)f0_data.GetDouble(&offset);
8615ffd83dbSDimitry Andric             success = true;
8625ffd83dbSDimitry Andric           } else if (*byte_size == sizeof(long double)) {
8635ffd83dbSDimitry Andric             const RegisterInfo *f2_info =
8645ffd83dbSDimitry Andric                 reg_ctx->GetRegisterInfoByName("f2", 0);
8655ffd83dbSDimitry Andric             RegisterValue f2_value;
8665ffd83dbSDimitry Andric             DataExtractor f2_data;
8675ffd83dbSDimitry Andric             reg_ctx->ReadRegister(f2_info, f2_value);
8685ffd83dbSDimitry Andric             DataExtractor *copy_from_extractor = nullptr;
86981ad6265SDimitry Andric             WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
8705ffd83dbSDimitry Andric             DataExtractor return_ext(
8715ffd83dbSDimitry Andric                 data_sp, target_byte_order,
8725ffd83dbSDimitry Andric                 target->GetArchitecture().GetAddressByteSize());
8735ffd83dbSDimitry Andric 
8745ffd83dbSDimitry Andric             if (target_byte_order == eByteOrderLittle) {
8755ffd83dbSDimitry Andric               copy_from_extractor = &f0_data;
8765ffd83dbSDimitry Andric               copy_from_extractor->CopyByteOrderedData(
8775ffd83dbSDimitry Andric                   0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
8785ffd83dbSDimitry Andric               f2_value.GetData(f2_data);
8795ffd83dbSDimitry Andric               copy_from_extractor = &f2_data;
8805ffd83dbSDimitry Andric               copy_from_extractor->CopyByteOrderedData(
8815ffd83dbSDimitry Andric                   0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
8825ffd83dbSDimitry Andric                   target_byte_order);
8835ffd83dbSDimitry Andric             } else {
8845ffd83dbSDimitry Andric               copy_from_extractor = &f0_data;
8855ffd83dbSDimitry Andric               copy_from_extractor->CopyByteOrderedData(
8865ffd83dbSDimitry Andric                   0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
8875ffd83dbSDimitry Andric                   target_byte_order);
8885ffd83dbSDimitry Andric               f2_value.GetData(f2_data);
8895ffd83dbSDimitry Andric               copy_from_extractor = &f2_data;
8905ffd83dbSDimitry Andric               copy_from_extractor->CopyByteOrderedData(
8915ffd83dbSDimitry Andric                   0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
8925ffd83dbSDimitry Andric             }
8935ffd83dbSDimitry Andric 
8945ffd83dbSDimitry Andric             return_valobj_sp = ValueObjectConstResult::Create(
8955ffd83dbSDimitry Andric                 &thread, return_compiler_type, ConstString(""), return_ext);
8965ffd83dbSDimitry Andric             return return_valobj_sp;
8975ffd83dbSDimitry Andric           }
8985ffd83dbSDimitry Andric         }
8995ffd83dbSDimitry Andric       }
9005ffd83dbSDimitry Andric     }
9015ffd83dbSDimitry Andric 
9025ffd83dbSDimitry Andric     if (success)
9035ffd83dbSDimitry Andric       return_valobj_sp = ValueObjectConstResult::Create(
9045ffd83dbSDimitry Andric           thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
9055ffd83dbSDimitry Andric   } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass ||
9065ffd83dbSDimitry Andric              type_flags & eTypeIsVector) {
9075ffd83dbSDimitry Andric     // Any structure of up to 16 bytes in size is returned in the registers.
9085ffd83dbSDimitry Andric     if (*byte_size <= 16) {
90981ad6265SDimitry Andric       WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
9105ffd83dbSDimitry Andric       DataExtractor return_ext(data_sp, target_byte_order,
9115ffd83dbSDimitry Andric                                target->GetArchitecture().GetAddressByteSize());
9125ffd83dbSDimitry Andric 
9135ffd83dbSDimitry Andric       RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value;
9145ffd83dbSDimitry Andric       // Tracks how much bytes of r2 and r3 registers we've consumed so far
9155ffd83dbSDimitry Andric       uint32_t integer_bytes = 0;
9165ffd83dbSDimitry Andric 
9175ffd83dbSDimitry Andric       // True if return values are in FP return registers.
9185ffd83dbSDimitry Andric       bool use_fp_regs = false;
9195ffd83dbSDimitry Andric       // True if we found any non floating point field in structure.
9205ffd83dbSDimitry Andric       bool found_non_fp_field = false;
9215ffd83dbSDimitry Andric       // True if return values are in r2 register.
9225ffd83dbSDimitry Andric       bool use_r2 = false;
9235ffd83dbSDimitry Andric       // True if return values are in r3 register.
9245ffd83dbSDimitry Andric       bool use_r3 = false;
9255ffd83dbSDimitry Andric       // True if the result is copied into our data buffer
9265ffd83dbSDimitry Andric       bool sucess = false;
9275ffd83dbSDimitry Andric       std::string name;
9285ffd83dbSDimitry Andric       bool is_complex;
9295ffd83dbSDimitry Andric       uint32_t count;
9305ffd83dbSDimitry Andric       const uint32_t num_children = return_compiler_type.GetNumFields();
9315ffd83dbSDimitry Andric 
9325ffd83dbSDimitry Andric       // A structure consisting of one or two FP values (and nothing else) will
9335ffd83dbSDimitry Andric       // be returned in the two FP return-value registers i.e fp0 and fp2.
9345ffd83dbSDimitry Andric       if (num_children <= 2) {
9355ffd83dbSDimitry Andric         uint64_t field_bit_offset = 0;
9365ffd83dbSDimitry Andric 
9375ffd83dbSDimitry Andric         // Check if this structure contains only floating point fields
9385ffd83dbSDimitry Andric         for (uint32_t idx = 0; idx < num_children; idx++) {
9395ffd83dbSDimitry Andric           CompilerType field_compiler_type =
9405ffd83dbSDimitry Andric               return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset,
9415ffd83dbSDimitry Andric                                                    nullptr, nullptr);
9425ffd83dbSDimitry Andric 
9435ffd83dbSDimitry Andric           if (field_compiler_type.IsFloatingPointType(count, is_complex))
9445ffd83dbSDimitry Andric             use_fp_regs = true;
9455ffd83dbSDimitry Andric           else
9465ffd83dbSDimitry Andric             found_non_fp_field = true;
9475ffd83dbSDimitry Andric         }
9485ffd83dbSDimitry Andric 
9495ffd83dbSDimitry Andric         if (use_fp_regs && !found_non_fp_field) {
9505ffd83dbSDimitry Andric           // We have one or two FP-only values in this structure. Get it from
9515ffd83dbSDimitry Andric           // f0/f2 registers.
9525ffd83dbSDimitry Andric           DataExtractor f0_data, f1_data, f2_data;
9535ffd83dbSDimitry Andric           const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
9545ffd83dbSDimitry Andric           const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
9555ffd83dbSDimitry Andric           const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0);
9565ffd83dbSDimitry Andric 
9575ffd83dbSDimitry Andric           reg_ctx->ReadRegister(f0_info, f0_value);
9585ffd83dbSDimitry Andric           reg_ctx->ReadRegister(f2_info, f2_value);
9595ffd83dbSDimitry Andric 
9605ffd83dbSDimitry Andric           f0_value.GetData(f0_data);
9615ffd83dbSDimitry Andric 
9625ffd83dbSDimitry Andric           for (uint32_t idx = 0; idx < num_children; idx++) {
9635ffd83dbSDimitry Andric             CompilerType field_compiler_type =
9645ffd83dbSDimitry Andric                 return_compiler_type.GetFieldAtIndex(
9655ffd83dbSDimitry Andric                     idx, name, &field_bit_offset, nullptr, nullptr);
966bdd1243dSDimitry Andric             std::optional<uint64_t> field_byte_width =
967e8d8bef9SDimitry Andric                 field_compiler_type.GetByteSize(&thread);
9685ffd83dbSDimitry Andric             if (!field_byte_width)
9695ffd83dbSDimitry Andric               return return_valobj_sp;
9705ffd83dbSDimitry Andric 
9715ffd83dbSDimitry Andric             DataExtractor *copy_from_extractor = nullptr;
9725ffd83dbSDimitry Andric             uint64_t return_value[2];
9735ffd83dbSDimitry Andric             offset_t offset = 0;
9745ffd83dbSDimitry Andric 
9755ffd83dbSDimitry Andric             if (idx == 0) {
9765ffd83dbSDimitry Andric               // This case is for long double type.
9775ffd83dbSDimitry Andric               if (*field_byte_width == 16) {
9785ffd83dbSDimitry Andric 
9795ffd83dbSDimitry Andric                 // If structure contains long double type, then it is returned
9805ffd83dbSDimitry Andric                 // in fp0/fp1 registers.
9815ffd83dbSDimitry Andric                 if (target_byte_order == eByteOrderLittle) {
9825ffd83dbSDimitry Andric                   return_value[0] = f0_data.GetU64(&offset);
9835ffd83dbSDimitry Andric                   reg_ctx->ReadRegister(f1_info, f1_value);
9845ffd83dbSDimitry Andric                   f1_value.GetData(f1_data);
9855ffd83dbSDimitry Andric                   offset = 0;
9865ffd83dbSDimitry Andric                   return_value[1] = f1_data.GetU64(&offset);
9875ffd83dbSDimitry Andric                 } else {
9885ffd83dbSDimitry Andric                   return_value[1] = f0_data.GetU64(&offset);
9895ffd83dbSDimitry Andric                   reg_ctx->ReadRegister(f1_info, f1_value);
9905ffd83dbSDimitry Andric                   f1_value.GetData(f1_data);
9915ffd83dbSDimitry Andric                   offset = 0;
9925ffd83dbSDimitry Andric                   return_value[0] = f1_data.GetU64(&offset);
9935ffd83dbSDimitry Andric                 }
9945ffd83dbSDimitry Andric 
9955ffd83dbSDimitry Andric                 f0_data.SetData(return_value, *field_byte_width,
9965ffd83dbSDimitry Andric                                 target_byte_order);
9975ffd83dbSDimitry Andric               }
9985ffd83dbSDimitry Andric               copy_from_extractor = &f0_data; // This is in f0, copy from
9995ffd83dbSDimitry Andric                                               // register to our result
10005ffd83dbSDimitry Andric                                               // structure
10015ffd83dbSDimitry Andric             } else {
10025ffd83dbSDimitry Andric               f2_value.GetData(f2_data);
10035ffd83dbSDimitry Andric               // This is in f2, copy from register to our result structure
10045ffd83dbSDimitry Andric               copy_from_extractor = &f2_data;
10055ffd83dbSDimitry Andric             }
10065ffd83dbSDimitry Andric 
10075ffd83dbSDimitry Andric             // Sanity check to avoid crash
10085ffd83dbSDimitry Andric             if (!copy_from_extractor ||
10095ffd83dbSDimitry Andric                 *field_byte_width > copy_from_extractor->GetByteSize())
10105ffd83dbSDimitry Andric               return return_valobj_sp;
10115ffd83dbSDimitry Andric 
10125ffd83dbSDimitry Andric             // copy the register contents into our data buffer
10135ffd83dbSDimitry Andric             copy_from_extractor->CopyByteOrderedData(
10145ffd83dbSDimitry Andric                 0, *field_byte_width,
10155ffd83dbSDimitry Andric                 data_sp->GetBytes() + (field_bit_offset / 8), *field_byte_width,
10165ffd83dbSDimitry Andric                 target_byte_order);
10175ffd83dbSDimitry Andric           }
10185ffd83dbSDimitry Andric 
10195ffd83dbSDimitry Andric           // The result is in our data buffer.  Create a variable object out of
10205ffd83dbSDimitry Andric           // it
10215ffd83dbSDimitry Andric           return_valobj_sp = ValueObjectConstResult::Create(
10225ffd83dbSDimitry Andric               &thread, return_compiler_type, ConstString(""), return_ext);
10235ffd83dbSDimitry Andric 
10245ffd83dbSDimitry Andric           return return_valobj_sp;
10255ffd83dbSDimitry Andric         }
10265ffd83dbSDimitry Andric       }
10275ffd83dbSDimitry Andric 
10285ffd83dbSDimitry Andric       // If we reach here, it means this structure either contains more than
10295ffd83dbSDimitry Andric       // two fields or it contains at least one non floating point type. In
10305ffd83dbSDimitry Andric       // that case, all fields are returned in GP return registers.
10315ffd83dbSDimitry Andric       for (uint32_t idx = 0; idx < num_children; idx++) {
10325ffd83dbSDimitry Andric         uint64_t field_bit_offset = 0;
10335ffd83dbSDimitry Andric         bool is_signed;
10345ffd83dbSDimitry Andric         uint32_t padding;
10355ffd83dbSDimitry Andric 
10365ffd83dbSDimitry Andric         CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
10375ffd83dbSDimitry Andric             idx, name, &field_bit_offset, nullptr, nullptr);
1038bdd1243dSDimitry Andric         std::optional<uint64_t> field_byte_width =
1039e8d8bef9SDimitry Andric             field_compiler_type.GetByteSize(&thread);
10405ffd83dbSDimitry Andric 
10415ffd83dbSDimitry Andric         // if we don't know the size of the field (e.g. invalid type), just
10425ffd83dbSDimitry Andric         // bail out
10435ffd83dbSDimitry Andric         if (!field_byte_width || *field_byte_width == 0)
10445ffd83dbSDimitry Andric           break;
10455ffd83dbSDimitry Andric 
10465ffd83dbSDimitry Andric         uint32_t field_byte_offset = field_bit_offset / 8;
10475ffd83dbSDimitry Andric 
10485ffd83dbSDimitry Andric         if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
10495ffd83dbSDimitry Andric             field_compiler_type.IsPointerType() ||
10505ffd83dbSDimitry Andric             field_compiler_type.IsFloatingPointType(count, is_complex)) {
10515ffd83dbSDimitry Andric           padding = field_byte_offset - integer_bytes;
10525ffd83dbSDimitry Andric 
10535ffd83dbSDimitry Andric           if (integer_bytes < 8) {
10545ffd83dbSDimitry Andric             // We have not yet consumed r2 completely.
10555ffd83dbSDimitry Andric             if (integer_bytes + *field_byte_width + padding <= 8) {
10565ffd83dbSDimitry Andric               // This field fits in r2, copy its value from r2 to our result
10575ffd83dbSDimitry Andric               // structure
10585ffd83dbSDimitry Andric               integer_bytes = integer_bytes + *field_byte_width +
10595ffd83dbSDimitry Andric                               padding; // Increase the consumed bytes.
10605ffd83dbSDimitry Andric               use_r2 = true;
10615ffd83dbSDimitry Andric             } else {
10625ffd83dbSDimitry Andric               // There isn't enough space left in r2 for this field, so this
10635ffd83dbSDimitry Andric               // will be in r3.
10645ffd83dbSDimitry Andric               integer_bytes = integer_bytes + *field_byte_width +
10655ffd83dbSDimitry Andric                               padding; // Increase the consumed bytes.
10665ffd83dbSDimitry Andric               use_r3 = true;
10675ffd83dbSDimitry Andric             }
10685ffd83dbSDimitry Andric           }
10695ffd83dbSDimitry Andric           // We already have consumed at-least 8 bytes that means r2 is done,
10705ffd83dbSDimitry Andric           // and this field will be in r3. Check if this field can fit in r3.
10715ffd83dbSDimitry Andric           else if (integer_bytes + *field_byte_width + padding <= 16) {
10725ffd83dbSDimitry Andric             integer_bytes = integer_bytes + *field_byte_width + padding;
10735ffd83dbSDimitry Andric             use_r3 = true;
10745ffd83dbSDimitry Andric           } else {
10755ffd83dbSDimitry Andric             // There isn't any space left for this field, this should not
10765ffd83dbSDimitry Andric             // happen as we have already checked the overall size is not
10775ffd83dbSDimitry Andric             // greater than 16 bytes. For now, return a nullptr return value
10785ffd83dbSDimitry Andric             // object.
10795ffd83dbSDimitry Andric             return return_valobj_sp;
10805ffd83dbSDimitry Andric           }
10815ffd83dbSDimitry Andric         }
10825ffd83dbSDimitry Andric       }
10835ffd83dbSDimitry Andric       // Vector types up to 16 bytes are returned in GP return registers
10845ffd83dbSDimitry Andric       if (type_flags & eTypeIsVector) {
10855ffd83dbSDimitry Andric         if (*byte_size <= 8)
10865ffd83dbSDimitry Andric           use_r2 = true;
10875ffd83dbSDimitry Andric         else {
10885ffd83dbSDimitry Andric           use_r2 = true;
10895ffd83dbSDimitry Andric           use_r3 = true;
10905ffd83dbSDimitry Andric         }
10915ffd83dbSDimitry Andric       }
10925ffd83dbSDimitry Andric 
10935ffd83dbSDimitry Andric       if (use_r2) {
10945ffd83dbSDimitry Andric         reg_ctx->ReadRegister(r2_info, r2_value);
10955ffd83dbSDimitry Andric 
10965ffd83dbSDimitry Andric         const size_t bytes_copied = r2_value.GetAsMemoryData(
1097bdd1243dSDimitry Andric             *r2_info, data_sp->GetBytes(), r2_info->byte_size,
1098bdd1243dSDimitry Andric             target_byte_order, error);
10995ffd83dbSDimitry Andric         if (bytes_copied != r2_info->byte_size)
11005ffd83dbSDimitry Andric           return return_valobj_sp;
11015ffd83dbSDimitry Andric         sucess = true;
11025ffd83dbSDimitry Andric       }
11035ffd83dbSDimitry Andric       if (use_r3) {
11045ffd83dbSDimitry Andric         reg_ctx->ReadRegister(r3_info, r3_value);
11055ffd83dbSDimitry Andric         const size_t bytes_copied = r3_value.GetAsMemoryData(
1106bdd1243dSDimitry Andric             *r3_info, data_sp->GetBytes() + r2_info->byte_size,
11075ffd83dbSDimitry Andric             r3_info->byte_size, target_byte_order, error);
11085ffd83dbSDimitry Andric 
11095ffd83dbSDimitry Andric         if (bytes_copied != r3_info->byte_size)
11105ffd83dbSDimitry Andric           return return_valobj_sp;
11115ffd83dbSDimitry Andric         sucess = true;
11125ffd83dbSDimitry Andric       }
11135ffd83dbSDimitry Andric       if (sucess) {
11145ffd83dbSDimitry Andric         // The result is in our data buffer.  Create a variable object out of
11155ffd83dbSDimitry Andric         // it
11165ffd83dbSDimitry Andric         return_valobj_sp = ValueObjectConstResult::Create(
11175ffd83dbSDimitry Andric             &thread, return_compiler_type, ConstString(""), return_ext);
11185ffd83dbSDimitry Andric       }
11195ffd83dbSDimitry Andric       return return_valobj_sp;
11205ffd83dbSDimitry Andric     }
11215ffd83dbSDimitry Andric 
11225ffd83dbSDimitry Andric     // Any structure/vector greater than 16 bytes in size is returned in
11235ffd83dbSDimitry Andric     // memory. The pointer to that memory is returned in r2.
11245ffd83dbSDimitry Andric     uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
11255ffd83dbSDimitry Andric         reg_ctx->GetRegisterInfoByName("r2", 0), 0);
11265ffd83dbSDimitry Andric 
11275ffd83dbSDimitry Andric     // We have got the address. Create a memory object out of it
11285ffd83dbSDimitry Andric     return_valobj_sp = ValueObjectMemory::Create(
11295ffd83dbSDimitry Andric         &thread, "", Address(mem_address, nullptr), return_compiler_type);
11305ffd83dbSDimitry Andric   }
11315ffd83dbSDimitry Andric   return return_valobj_sp;
11325ffd83dbSDimitry Andric }
11335ffd83dbSDimitry Andric 
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)11345ffd83dbSDimitry Andric bool ABISysV_mips64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
11355ffd83dbSDimitry Andric   unwind_plan.Clear();
11365ffd83dbSDimitry Andric   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
11375ffd83dbSDimitry Andric 
11385ffd83dbSDimitry Andric   UnwindPlan::RowSP row(new UnwindPlan::Row);
11395ffd83dbSDimitry Andric 
11405ffd83dbSDimitry Andric   // Our Call Frame Address is the stack pointer value
11415ffd83dbSDimitry Andric   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
11425ffd83dbSDimitry Andric 
11435ffd83dbSDimitry Andric   // The previous PC is in the RA
11445ffd83dbSDimitry Andric   row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
11455ffd83dbSDimitry Andric   unwind_plan.AppendRow(row);
11465ffd83dbSDimitry Andric 
11475ffd83dbSDimitry Andric   // All other registers are the same.
11485ffd83dbSDimitry Andric 
11495ffd83dbSDimitry Andric   unwind_plan.SetSourceName("mips64 at-func-entry default");
11505ffd83dbSDimitry Andric   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
11515ffd83dbSDimitry Andric   unwind_plan.SetReturnAddressRegister(dwarf_r31);
11525ffd83dbSDimitry Andric   return true;
11535ffd83dbSDimitry Andric }
11545ffd83dbSDimitry Andric 
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)11555ffd83dbSDimitry Andric bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
11565ffd83dbSDimitry Andric   unwind_plan.Clear();
11575ffd83dbSDimitry Andric   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
11585ffd83dbSDimitry Andric 
11595ffd83dbSDimitry Andric   UnwindPlan::RowSP row(new UnwindPlan::Row);
11605ffd83dbSDimitry Andric 
1161fe6060f1SDimitry Andric   row->SetUnspecifiedRegistersAreUndefined(true);
11625ffd83dbSDimitry Andric   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
11635ffd83dbSDimitry Andric 
11645ffd83dbSDimitry Andric   row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
11655ffd83dbSDimitry Andric 
11665ffd83dbSDimitry Andric   unwind_plan.AppendRow(row);
11675ffd83dbSDimitry Andric   unwind_plan.SetSourceName("mips64 default unwind plan");
11685ffd83dbSDimitry Andric   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
11695ffd83dbSDimitry Andric   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
11705ffd83dbSDimitry Andric   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
11715ffd83dbSDimitry Andric   return true;
11725ffd83dbSDimitry Andric }
11735ffd83dbSDimitry Andric 
RegisterIsVolatile(const RegisterInfo * reg_info)11745ffd83dbSDimitry Andric bool ABISysV_mips64::RegisterIsVolatile(const RegisterInfo *reg_info) {
11755ffd83dbSDimitry Andric   return !RegisterIsCalleeSaved(reg_info);
11765ffd83dbSDimitry Andric }
11775ffd83dbSDimitry Andric 
IsSoftFloat(uint32_t fp_flag) const11785ffd83dbSDimitry Andric bool ABISysV_mips64::IsSoftFloat(uint32_t fp_flag) const {
11795ffd83dbSDimitry Andric   return (fp_flag == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
11805ffd83dbSDimitry Andric }
11815ffd83dbSDimitry Andric 
RegisterIsCalleeSaved(const RegisterInfo * reg_info)11825ffd83dbSDimitry Andric bool ABISysV_mips64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
11835ffd83dbSDimitry Andric   if (reg_info) {
11845ffd83dbSDimitry Andric     // Preserved registers are :
11855ffd83dbSDimitry Andric     // r16-r23, r28, r29, r30, r31
11865ffd83dbSDimitry Andric 
11875ffd83dbSDimitry Andric     int reg = ((reg_info->byte_offset) / 8);
11885ffd83dbSDimitry Andric 
11895ffd83dbSDimitry Andric     bool save = (reg >= 16) && (reg <= 23);
11905ffd83dbSDimitry Andric     save |= (reg >= 28) && (reg <= 31);
11915ffd83dbSDimitry Andric 
11925ffd83dbSDimitry Andric     return save;
11935ffd83dbSDimitry Andric   }
11945ffd83dbSDimitry Andric   return false;
11955ffd83dbSDimitry Andric }
11965ffd83dbSDimitry Andric 
Initialize()11975ffd83dbSDimitry Andric void ABISysV_mips64::Initialize() {
11985ffd83dbSDimitry Andric   PluginManager::RegisterPlugin(
11995ffd83dbSDimitry Andric       GetPluginNameStatic(), "System V ABI for mips64 targets", CreateInstance);
12005ffd83dbSDimitry Andric }
12015ffd83dbSDimitry Andric 
Terminate()12025ffd83dbSDimitry Andric void ABISysV_mips64::Terminate() {
12035ffd83dbSDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
12045ffd83dbSDimitry Andric }
1205