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