15ffd83dbSDimitry Andric //===-- ABISysV_mips.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_mips.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_mips)
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[] = {
815ffd83dbSDimitry Andric // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME
825ffd83dbSDimitry Andric // DWARF GENERIC PROCESS PLUGINS
835ffd83dbSDimitry Andric // LLDB NATIVE VALUE REGS INVALIDATE REGS
845ffd83dbSDimitry Andric // ======== ====== == === ============= =========== ============
855ffd83dbSDimitry Andric // ============== ============ =================
865ffd83dbSDimitry Andric // =================== ========== =================
875ffd83dbSDimitry Andric {"r0",
885ffd83dbSDimitry Andric "zero",
895ffd83dbSDimitry Andric 4,
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 4,
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,
110349cc55cSDimitry Andric },
1115ffd83dbSDimitry Andric {"r2",
1125ffd83dbSDimitry Andric "v0",
1135ffd83dbSDimitry Andric 4,
1145ffd83dbSDimitry Andric 0,
1155ffd83dbSDimitry Andric eEncodingUint,
1165ffd83dbSDimitry Andric eFormatHex,
1175ffd83dbSDimitry Andric {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
1185ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
1195ffd83dbSDimitry Andric nullptr,
1205ffd83dbSDimitry Andric nullptr,
121*06c3fb27SDimitry Andric nullptr,
122349cc55cSDimitry Andric },
1235ffd83dbSDimitry Andric {"r3",
1245ffd83dbSDimitry Andric "v1",
1255ffd83dbSDimitry Andric 4,
1265ffd83dbSDimitry Andric 0,
1275ffd83dbSDimitry Andric eEncodingUint,
1285ffd83dbSDimitry Andric eFormatHex,
1295ffd83dbSDimitry Andric {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
1305ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
1315ffd83dbSDimitry Andric nullptr,
1325ffd83dbSDimitry Andric nullptr,
133*06c3fb27SDimitry Andric nullptr,
134349cc55cSDimitry Andric },
1355ffd83dbSDimitry Andric {"r4",
136349cc55cSDimitry Andric nullptr,
1375ffd83dbSDimitry Andric 4,
1385ffd83dbSDimitry Andric 0,
1395ffd83dbSDimitry Andric eEncodingUint,
1405ffd83dbSDimitry Andric eFormatHex,
1415ffd83dbSDimitry Andric {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
1425ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
1435ffd83dbSDimitry Andric nullptr,
1445ffd83dbSDimitry Andric nullptr,
145*06c3fb27SDimitry Andric nullptr,
146349cc55cSDimitry Andric },
1475ffd83dbSDimitry Andric {"r5",
148349cc55cSDimitry Andric nullptr,
1495ffd83dbSDimitry Andric 4,
1505ffd83dbSDimitry Andric 0,
1515ffd83dbSDimitry Andric eEncodingUint,
1525ffd83dbSDimitry Andric eFormatHex,
1535ffd83dbSDimitry Andric {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
1545ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
1555ffd83dbSDimitry Andric nullptr,
1565ffd83dbSDimitry Andric nullptr,
157*06c3fb27SDimitry Andric nullptr,
158349cc55cSDimitry Andric },
1595ffd83dbSDimitry Andric {"r6",
160349cc55cSDimitry Andric nullptr,
1615ffd83dbSDimitry Andric 4,
1625ffd83dbSDimitry Andric 0,
1635ffd83dbSDimitry Andric eEncodingUint,
1645ffd83dbSDimitry Andric eFormatHex,
1655ffd83dbSDimitry Andric {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
1665ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
1675ffd83dbSDimitry Andric nullptr,
1685ffd83dbSDimitry Andric nullptr,
169*06c3fb27SDimitry Andric nullptr,
170349cc55cSDimitry Andric },
1715ffd83dbSDimitry Andric {"r7",
172349cc55cSDimitry Andric nullptr,
1735ffd83dbSDimitry Andric 4,
1745ffd83dbSDimitry Andric 0,
1755ffd83dbSDimitry Andric eEncodingUint,
1765ffd83dbSDimitry Andric eFormatHex,
1775ffd83dbSDimitry Andric {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
1785ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
1795ffd83dbSDimitry Andric nullptr,
1805ffd83dbSDimitry Andric nullptr,
181*06c3fb27SDimitry Andric nullptr,
182349cc55cSDimitry Andric },
1835ffd83dbSDimitry Andric {"r8",
1845ffd83dbSDimitry Andric "arg5",
1855ffd83dbSDimitry Andric 4,
1865ffd83dbSDimitry Andric 0,
1875ffd83dbSDimitry Andric eEncodingUint,
1885ffd83dbSDimitry Andric eFormatHex,
1895ffd83dbSDimitry Andric {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
1905ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
1915ffd83dbSDimitry Andric nullptr,
1925ffd83dbSDimitry Andric nullptr,
193*06c3fb27SDimitry Andric nullptr,
194349cc55cSDimitry Andric },
1955ffd83dbSDimitry Andric {"r9",
1965ffd83dbSDimitry Andric "arg6",
1975ffd83dbSDimitry Andric 4,
1985ffd83dbSDimitry Andric 0,
1995ffd83dbSDimitry Andric eEncodingUint,
2005ffd83dbSDimitry Andric eFormatHex,
2015ffd83dbSDimitry Andric {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2025ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
2035ffd83dbSDimitry Andric nullptr,
2045ffd83dbSDimitry Andric nullptr,
205*06c3fb27SDimitry Andric nullptr,
206349cc55cSDimitry Andric },
2075ffd83dbSDimitry Andric {"r10",
2085ffd83dbSDimitry Andric "arg7",
2095ffd83dbSDimitry Andric 4,
2105ffd83dbSDimitry Andric 0,
2115ffd83dbSDimitry Andric eEncodingUint,
2125ffd83dbSDimitry Andric eFormatHex,
2135ffd83dbSDimitry Andric {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2145ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
2155ffd83dbSDimitry Andric nullptr,
2165ffd83dbSDimitry Andric nullptr,
217*06c3fb27SDimitry Andric nullptr,
218349cc55cSDimitry Andric },
2195ffd83dbSDimitry Andric {"r11",
2205ffd83dbSDimitry Andric "arg8",
2215ffd83dbSDimitry Andric 4,
2225ffd83dbSDimitry Andric 0,
2235ffd83dbSDimitry Andric eEncodingUint,
2245ffd83dbSDimitry Andric eFormatHex,
2255ffd83dbSDimitry Andric {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2265ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
2275ffd83dbSDimitry Andric nullptr,
2285ffd83dbSDimitry Andric nullptr,
229*06c3fb27SDimitry Andric nullptr,
230349cc55cSDimitry Andric },
2315ffd83dbSDimitry Andric {"r12",
2325ffd83dbSDimitry Andric nullptr,
2335ffd83dbSDimitry Andric 4,
2345ffd83dbSDimitry Andric 0,
2355ffd83dbSDimitry Andric eEncodingUint,
2365ffd83dbSDimitry Andric eFormatHex,
2375ffd83dbSDimitry Andric {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2385ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
2395ffd83dbSDimitry Andric nullptr,
2405ffd83dbSDimitry Andric nullptr,
241*06c3fb27SDimitry Andric nullptr,
242349cc55cSDimitry Andric },
2435ffd83dbSDimitry Andric {"r13",
2445ffd83dbSDimitry Andric nullptr,
2455ffd83dbSDimitry Andric 4,
2465ffd83dbSDimitry Andric 0,
2475ffd83dbSDimitry Andric eEncodingUint,
2485ffd83dbSDimitry Andric eFormatHex,
2495ffd83dbSDimitry Andric {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2505ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
2515ffd83dbSDimitry Andric nullptr,
2525ffd83dbSDimitry Andric nullptr,
253*06c3fb27SDimitry Andric nullptr,
254349cc55cSDimitry Andric },
2555ffd83dbSDimitry Andric {"r14",
2565ffd83dbSDimitry Andric nullptr,
2575ffd83dbSDimitry Andric 4,
2585ffd83dbSDimitry Andric 0,
2595ffd83dbSDimitry Andric eEncodingUint,
2605ffd83dbSDimitry Andric eFormatHex,
2615ffd83dbSDimitry Andric {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2625ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
2635ffd83dbSDimitry Andric nullptr,
2645ffd83dbSDimitry Andric nullptr,
265*06c3fb27SDimitry Andric nullptr,
266349cc55cSDimitry Andric },
2675ffd83dbSDimitry Andric {"r15",
2685ffd83dbSDimitry Andric nullptr,
2695ffd83dbSDimitry Andric 4,
2705ffd83dbSDimitry Andric 0,
2715ffd83dbSDimitry Andric eEncodingUint,
2725ffd83dbSDimitry Andric eFormatHex,
2735ffd83dbSDimitry Andric {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2745ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
2755ffd83dbSDimitry Andric nullptr,
2765ffd83dbSDimitry Andric nullptr,
277*06c3fb27SDimitry Andric nullptr,
278349cc55cSDimitry Andric },
2795ffd83dbSDimitry Andric {"r16",
2805ffd83dbSDimitry Andric nullptr,
2815ffd83dbSDimitry Andric 4,
2825ffd83dbSDimitry Andric 0,
2835ffd83dbSDimitry Andric eEncodingUint,
2845ffd83dbSDimitry Andric eFormatHex,
2855ffd83dbSDimitry Andric {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2865ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
2875ffd83dbSDimitry Andric nullptr,
2885ffd83dbSDimitry Andric nullptr,
289*06c3fb27SDimitry Andric nullptr,
290349cc55cSDimitry Andric },
2915ffd83dbSDimitry Andric {"r17",
2925ffd83dbSDimitry Andric nullptr,
2935ffd83dbSDimitry Andric 4,
2945ffd83dbSDimitry Andric 0,
2955ffd83dbSDimitry Andric eEncodingUint,
2965ffd83dbSDimitry Andric eFormatHex,
2975ffd83dbSDimitry Andric {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
2985ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
2995ffd83dbSDimitry Andric nullptr,
3005ffd83dbSDimitry Andric nullptr,
301*06c3fb27SDimitry Andric nullptr,
302349cc55cSDimitry Andric },
3035ffd83dbSDimitry Andric {"r18",
3045ffd83dbSDimitry Andric nullptr,
3055ffd83dbSDimitry Andric 4,
3065ffd83dbSDimitry Andric 0,
3075ffd83dbSDimitry Andric eEncodingUint,
3085ffd83dbSDimitry Andric eFormatHex,
3095ffd83dbSDimitry Andric {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3105ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
3115ffd83dbSDimitry Andric nullptr,
3125ffd83dbSDimitry Andric nullptr,
313*06c3fb27SDimitry Andric nullptr,
314349cc55cSDimitry Andric },
3155ffd83dbSDimitry Andric {"r19",
3165ffd83dbSDimitry Andric nullptr,
3175ffd83dbSDimitry Andric 4,
3185ffd83dbSDimitry Andric 0,
3195ffd83dbSDimitry Andric eEncodingUint,
3205ffd83dbSDimitry Andric eFormatHex,
3215ffd83dbSDimitry Andric {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3225ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
3235ffd83dbSDimitry Andric nullptr,
3245ffd83dbSDimitry Andric nullptr,
325*06c3fb27SDimitry Andric nullptr,
326349cc55cSDimitry Andric },
3275ffd83dbSDimitry Andric {"r20",
3285ffd83dbSDimitry Andric nullptr,
3295ffd83dbSDimitry Andric 4,
3305ffd83dbSDimitry Andric 0,
3315ffd83dbSDimitry Andric eEncodingUint,
3325ffd83dbSDimitry Andric eFormatHex,
3335ffd83dbSDimitry Andric {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3345ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
3355ffd83dbSDimitry Andric nullptr,
3365ffd83dbSDimitry Andric nullptr,
337*06c3fb27SDimitry Andric nullptr,
338349cc55cSDimitry Andric },
3395ffd83dbSDimitry Andric {"r21",
3405ffd83dbSDimitry Andric nullptr,
3415ffd83dbSDimitry Andric 4,
3425ffd83dbSDimitry Andric 0,
3435ffd83dbSDimitry Andric eEncodingUint,
3445ffd83dbSDimitry Andric eFormatHex,
3455ffd83dbSDimitry Andric {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3465ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
3475ffd83dbSDimitry Andric nullptr,
3485ffd83dbSDimitry Andric nullptr,
349*06c3fb27SDimitry Andric nullptr,
350349cc55cSDimitry Andric },
3515ffd83dbSDimitry Andric {"r22",
3525ffd83dbSDimitry Andric nullptr,
3535ffd83dbSDimitry Andric 4,
3545ffd83dbSDimitry Andric 0,
3555ffd83dbSDimitry Andric eEncodingUint,
3565ffd83dbSDimitry Andric eFormatHex,
3575ffd83dbSDimitry Andric {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3585ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
3595ffd83dbSDimitry Andric nullptr,
3605ffd83dbSDimitry Andric nullptr,
361*06c3fb27SDimitry Andric nullptr,
362349cc55cSDimitry Andric },
3635ffd83dbSDimitry Andric {"r23",
3645ffd83dbSDimitry Andric nullptr,
3655ffd83dbSDimitry Andric 4,
3665ffd83dbSDimitry Andric 0,
3675ffd83dbSDimitry Andric eEncodingUint,
3685ffd83dbSDimitry Andric eFormatHex,
3695ffd83dbSDimitry Andric {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3705ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
3715ffd83dbSDimitry Andric nullptr,
3725ffd83dbSDimitry Andric nullptr,
373*06c3fb27SDimitry Andric nullptr,
374349cc55cSDimitry Andric },
3755ffd83dbSDimitry Andric {"r24",
3765ffd83dbSDimitry Andric nullptr,
3775ffd83dbSDimitry Andric 4,
3785ffd83dbSDimitry Andric 0,
3795ffd83dbSDimitry Andric eEncodingUint,
3805ffd83dbSDimitry Andric eFormatHex,
3815ffd83dbSDimitry Andric {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3825ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
3835ffd83dbSDimitry Andric nullptr,
3845ffd83dbSDimitry Andric nullptr,
385*06c3fb27SDimitry Andric nullptr,
386349cc55cSDimitry Andric },
3875ffd83dbSDimitry Andric {"r25",
3885ffd83dbSDimitry Andric nullptr,
3895ffd83dbSDimitry Andric 4,
3905ffd83dbSDimitry Andric 0,
3915ffd83dbSDimitry Andric eEncodingUint,
3925ffd83dbSDimitry Andric eFormatHex,
3935ffd83dbSDimitry Andric {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
3945ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
3955ffd83dbSDimitry Andric nullptr,
3965ffd83dbSDimitry Andric nullptr,
397*06c3fb27SDimitry Andric nullptr,
398349cc55cSDimitry Andric },
3995ffd83dbSDimitry Andric {"r26",
4005ffd83dbSDimitry Andric nullptr,
4015ffd83dbSDimitry Andric 4,
4025ffd83dbSDimitry Andric 0,
4035ffd83dbSDimitry Andric eEncodingUint,
4045ffd83dbSDimitry Andric eFormatHex,
4055ffd83dbSDimitry Andric {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
4065ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
4075ffd83dbSDimitry Andric nullptr,
4085ffd83dbSDimitry Andric nullptr,
409*06c3fb27SDimitry Andric nullptr,
410349cc55cSDimitry Andric },
4115ffd83dbSDimitry Andric {"r27",
4125ffd83dbSDimitry Andric nullptr,
4135ffd83dbSDimitry Andric 4,
4145ffd83dbSDimitry Andric 0,
4155ffd83dbSDimitry Andric eEncodingUint,
4165ffd83dbSDimitry Andric eFormatHex,
4175ffd83dbSDimitry Andric {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
4185ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
4195ffd83dbSDimitry Andric nullptr,
4205ffd83dbSDimitry Andric nullptr,
421*06c3fb27SDimitry Andric nullptr,
422349cc55cSDimitry Andric },
4235ffd83dbSDimitry Andric {"r28",
4245ffd83dbSDimitry Andric "gp",
4255ffd83dbSDimitry Andric 4,
4265ffd83dbSDimitry Andric 0,
4275ffd83dbSDimitry Andric eEncodingUint,
4285ffd83dbSDimitry Andric eFormatHex,
4295ffd83dbSDimitry Andric {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
4305ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
4315ffd83dbSDimitry Andric nullptr,
4325ffd83dbSDimitry Andric nullptr,
433*06c3fb27SDimitry Andric nullptr,
434349cc55cSDimitry Andric },
4355ffd83dbSDimitry Andric {"r29",
436349cc55cSDimitry Andric nullptr,
4375ffd83dbSDimitry Andric 4,
4385ffd83dbSDimitry Andric 0,
4395ffd83dbSDimitry Andric eEncodingUint,
4405ffd83dbSDimitry Andric eFormatHex,
4415ffd83dbSDimitry Andric {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
4425ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
4435ffd83dbSDimitry Andric nullptr,
4445ffd83dbSDimitry Andric nullptr,
445*06c3fb27SDimitry Andric nullptr,
446349cc55cSDimitry Andric },
4475ffd83dbSDimitry Andric {"r30",
448349cc55cSDimitry Andric nullptr,
4495ffd83dbSDimitry Andric 4,
4505ffd83dbSDimitry Andric 0,
4515ffd83dbSDimitry Andric eEncodingUint,
4525ffd83dbSDimitry Andric eFormatHex,
4535ffd83dbSDimitry Andric {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
4545ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
4555ffd83dbSDimitry Andric nullptr,
4565ffd83dbSDimitry Andric nullptr,
457*06c3fb27SDimitry Andric nullptr,
458349cc55cSDimitry Andric },
4595ffd83dbSDimitry Andric {"r31",
460349cc55cSDimitry Andric nullptr,
4615ffd83dbSDimitry Andric 4,
4625ffd83dbSDimitry Andric 0,
4635ffd83dbSDimitry Andric eEncodingUint,
4645ffd83dbSDimitry Andric eFormatHex,
4655ffd83dbSDimitry Andric {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
4665ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
4675ffd83dbSDimitry Andric nullptr,
4685ffd83dbSDimitry Andric nullptr,
469*06c3fb27SDimitry Andric nullptr,
470349cc55cSDimitry Andric },
4715ffd83dbSDimitry Andric {"sr",
4725ffd83dbSDimitry Andric nullptr,
4735ffd83dbSDimitry Andric 4,
4745ffd83dbSDimitry Andric 0,
4755ffd83dbSDimitry Andric eEncodingUint,
4765ffd83dbSDimitry Andric eFormatHex,
4775ffd83dbSDimitry Andric {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
4785ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
4795ffd83dbSDimitry Andric nullptr,
4805ffd83dbSDimitry Andric nullptr,
481*06c3fb27SDimitry Andric nullptr,
482349cc55cSDimitry Andric },
4835ffd83dbSDimitry Andric {"lo",
4845ffd83dbSDimitry Andric nullptr,
4855ffd83dbSDimitry Andric 4,
4865ffd83dbSDimitry Andric 0,
4875ffd83dbSDimitry Andric eEncodingUint,
4885ffd83dbSDimitry Andric eFormatHex,
4895ffd83dbSDimitry Andric {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
4905ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
4915ffd83dbSDimitry Andric nullptr,
4925ffd83dbSDimitry Andric nullptr,
493*06c3fb27SDimitry Andric nullptr,
494349cc55cSDimitry Andric },
4955ffd83dbSDimitry Andric {"hi",
4965ffd83dbSDimitry Andric nullptr,
4975ffd83dbSDimitry Andric 4,
4985ffd83dbSDimitry Andric 0,
4995ffd83dbSDimitry Andric eEncodingUint,
5005ffd83dbSDimitry Andric eFormatHex,
5015ffd83dbSDimitry Andric {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
5025ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
5035ffd83dbSDimitry Andric nullptr,
5045ffd83dbSDimitry Andric nullptr,
505*06c3fb27SDimitry Andric nullptr,
506349cc55cSDimitry Andric },
5075ffd83dbSDimitry Andric {"bad",
5085ffd83dbSDimitry Andric nullptr,
5095ffd83dbSDimitry Andric 4,
5105ffd83dbSDimitry Andric 0,
5115ffd83dbSDimitry Andric eEncodingUint,
5125ffd83dbSDimitry Andric eFormatHex,
5135ffd83dbSDimitry Andric {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
5145ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
5155ffd83dbSDimitry Andric nullptr,
5165ffd83dbSDimitry Andric nullptr,
517*06c3fb27SDimitry Andric nullptr,
518349cc55cSDimitry Andric },
5195ffd83dbSDimitry Andric {"cause",
5205ffd83dbSDimitry Andric nullptr,
5215ffd83dbSDimitry Andric 4,
5225ffd83dbSDimitry Andric 0,
5235ffd83dbSDimitry Andric eEncodingUint,
5245ffd83dbSDimitry Andric eFormatHex,
5255ffd83dbSDimitry Andric {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
5265ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
5275ffd83dbSDimitry Andric nullptr,
5285ffd83dbSDimitry Andric nullptr,
529*06c3fb27SDimitry Andric nullptr,
530349cc55cSDimitry Andric },
5315ffd83dbSDimitry Andric {"pc",
5325ffd83dbSDimitry Andric nullptr,
5335ffd83dbSDimitry Andric 4,
5345ffd83dbSDimitry Andric 0,
5355ffd83dbSDimitry Andric eEncodingUint,
5365ffd83dbSDimitry Andric eFormatHex,
5375ffd83dbSDimitry Andric {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
5385ffd83dbSDimitry Andric LLDB_INVALID_REGNUM},
5395ffd83dbSDimitry Andric nullptr,
5405ffd83dbSDimitry Andric nullptr,
541*06c3fb27SDimitry Andric nullptr,
542349cc55cSDimitry Andric },
5435ffd83dbSDimitry Andric };
5445ffd83dbSDimitry Andric
545bdd1243dSDimitry Andric static const uint32_t k_num_register_infos = std::size(g_register_infos);
5465ffd83dbSDimitry Andric
5475ffd83dbSDimitry Andric const lldb_private::RegisterInfo *
GetRegisterInfoArray(uint32_t & count)5485ffd83dbSDimitry Andric ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
5495ffd83dbSDimitry Andric count = k_num_register_infos;
5505ffd83dbSDimitry Andric return g_register_infos;
5515ffd83dbSDimitry Andric }
5525ffd83dbSDimitry Andric
GetRedZoneSize() const5535ffd83dbSDimitry Andric size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
5545ffd83dbSDimitry Andric
5555ffd83dbSDimitry Andric // Static Functions
5565ffd83dbSDimitry Andric
5575ffd83dbSDimitry Andric ABISP
CreateInstance(lldb::ProcessSP process_sp,const ArchSpec & arch)5585ffd83dbSDimitry Andric ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
5595ffd83dbSDimitry Andric const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
5605ffd83dbSDimitry Andric if ((arch_type == llvm::Triple::mips) ||
5615ffd83dbSDimitry Andric (arch_type == llvm::Triple::mipsel)) {
5625ffd83dbSDimitry Andric return ABISP(
5635ffd83dbSDimitry Andric new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch)));
5645ffd83dbSDimitry Andric }
5655ffd83dbSDimitry Andric return ABISP();
5665ffd83dbSDimitry Andric }
5675ffd83dbSDimitry Andric
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,llvm::ArrayRef<addr_t> args) const5685ffd83dbSDimitry Andric bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
5695ffd83dbSDimitry Andric addr_t func_addr, addr_t return_addr,
5705ffd83dbSDimitry Andric llvm::ArrayRef<addr_t> args) const {
57181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Expressions);
5725ffd83dbSDimitry Andric
5735ffd83dbSDimitry Andric if (log) {
5745ffd83dbSDimitry Andric StreamString s;
5755ffd83dbSDimitry Andric s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
5765ffd83dbSDimitry Andric ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
5775ffd83dbSDimitry Andric ", return_addr = 0x%" PRIx64,
5785ffd83dbSDimitry Andric thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
5795ffd83dbSDimitry Andric (uint64_t)return_addr);
5805ffd83dbSDimitry Andric
5815ffd83dbSDimitry Andric for (size_t i = 0; i < args.size(); ++i)
5825ffd83dbSDimitry Andric s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
5835ffd83dbSDimitry Andric s.PutCString(")");
5845ffd83dbSDimitry Andric log->PutString(s.GetString());
5855ffd83dbSDimitry Andric }
5865ffd83dbSDimitry Andric
5875ffd83dbSDimitry Andric RegisterContext *reg_ctx = thread.GetRegisterContext().get();
5885ffd83dbSDimitry Andric if (!reg_ctx)
5895ffd83dbSDimitry Andric return false;
5905ffd83dbSDimitry Andric
5915ffd83dbSDimitry Andric const RegisterInfo *reg_info = nullptr;
5925ffd83dbSDimitry Andric
5935ffd83dbSDimitry Andric RegisterValue reg_value;
5945ffd83dbSDimitry Andric
5955ffd83dbSDimitry Andric // Argument registers
5965ffd83dbSDimitry Andric const char *reg_names[] = {"r4", "r5", "r6", "r7"};
5975ffd83dbSDimitry Andric
5985ffd83dbSDimitry Andric llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
5995ffd83dbSDimitry Andric
6005ffd83dbSDimitry Andric // Write arguments to registers
601bdd1243dSDimitry Andric for (size_t i = 0; i < std::size(reg_names); ++i) {
6025ffd83dbSDimitry Andric if (ai == ae)
6035ffd83dbSDimitry Andric break;
6045ffd83dbSDimitry Andric
6055ffd83dbSDimitry Andric reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
6065ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_ARG1 + i);
6075ffd83dbSDimitry Andric LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
6085ffd83dbSDimitry Andric args[i], reg_info->name);
6095ffd83dbSDimitry Andric
6105ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
6115ffd83dbSDimitry Andric return false;
6125ffd83dbSDimitry Andric
6135ffd83dbSDimitry Andric ++ai;
6145ffd83dbSDimitry Andric }
6155ffd83dbSDimitry Andric
6165ffd83dbSDimitry Andric // If we have more than 4 arguments --Spill onto the stack
6175ffd83dbSDimitry Andric if (ai != ae) {
6185ffd83dbSDimitry Andric // No of arguments to go on stack
6195ffd83dbSDimitry Andric size_t num_stack_regs = args.size();
6205ffd83dbSDimitry Andric
6215ffd83dbSDimitry Andric // Allocate needed space for args on the stack
6225ffd83dbSDimitry Andric sp -= (num_stack_regs * 4);
6235ffd83dbSDimitry Andric
6245ffd83dbSDimitry Andric // Keep the stack 8 byte aligned
6255ffd83dbSDimitry Andric sp &= ~(8ull - 1ull);
6265ffd83dbSDimitry Andric
6275ffd83dbSDimitry Andric // just using arg1 to get the right size
6285ffd83dbSDimitry Andric const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
6295ffd83dbSDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
6305ffd83dbSDimitry Andric
6315ffd83dbSDimitry Andric addr_t arg_pos = sp + 16;
6325ffd83dbSDimitry Andric
6335ffd83dbSDimitry Andric size_t i = 4;
6345ffd83dbSDimitry Andric for (; ai != ae; ++ai) {
6355ffd83dbSDimitry Andric reg_value.SetUInt32(*ai);
6365ffd83dbSDimitry Andric LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
6375ffd83dbSDimitry Andric i + 1, args[i], arg_pos);
6385ffd83dbSDimitry Andric
6395ffd83dbSDimitry Andric if (reg_ctx
6405ffd83dbSDimitry Andric ->WriteRegisterValueToMemory(reg_info, arg_pos,
6415ffd83dbSDimitry Andric reg_info->byte_size, reg_value)
6425ffd83dbSDimitry Andric .Fail())
6435ffd83dbSDimitry Andric return false;
6445ffd83dbSDimitry Andric arg_pos += reg_info->byte_size;
6455ffd83dbSDimitry Andric i++;
6465ffd83dbSDimitry Andric }
6475ffd83dbSDimitry Andric }
6485ffd83dbSDimitry Andric
6495ffd83dbSDimitry Andric Status error;
6505ffd83dbSDimitry Andric const RegisterInfo *pc_reg_info =
6515ffd83dbSDimitry Andric reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6525ffd83dbSDimitry Andric const RegisterInfo *sp_reg_info =
6535ffd83dbSDimitry Andric reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
6545ffd83dbSDimitry Andric const RegisterInfo *ra_reg_info =
6555ffd83dbSDimitry Andric reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
6565ffd83dbSDimitry Andric const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
6575ffd83dbSDimitry Andric const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
6585ffd83dbSDimitry Andric
6595ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
6605ffd83dbSDimitry Andric
6615ffd83dbSDimitry Andric /* Write r0 with 0, in case we are stopped in syscall,
6625ffd83dbSDimitry Andric * such setting prevents automatic decrement of the PC.
6635ffd83dbSDimitry Andric * This clears the bug 23659 for MIPS.
6645ffd83dbSDimitry Andric */
6655ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
6665ffd83dbSDimitry Andric return false;
6675ffd83dbSDimitry Andric
6685ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
6695ffd83dbSDimitry Andric
6705ffd83dbSDimitry Andric // Set "sp" to the requested value
6715ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
6725ffd83dbSDimitry Andric return false;
6735ffd83dbSDimitry Andric
6745ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
6755ffd83dbSDimitry Andric
6765ffd83dbSDimitry Andric // Set "ra" to the return address
6775ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
6785ffd83dbSDimitry Andric return false;
6795ffd83dbSDimitry Andric
6805ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
6815ffd83dbSDimitry Andric
6825ffd83dbSDimitry Andric // Set pc to the address of the called function.
6835ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
6845ffd83dbSDimitry Andric return false;
6855ffd83dbSDimitry Andric
6865ffd83dbSDimitry Andric LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
6875ffd83dbSDimitry Andric
6885ffd83dbSDimitry Andric // All callers of position independent functions must place the address of
6895ffd83dbSDimitry Andric // the called function in t9 (r25)
6905ffd83dbSDimitry Andric if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
6915ffd83dbSDimitry Andric return false;
6925ffd83dbSDimitry Andric
6935ffd83dbSDimitry Andric return true;
6945ffd83dbSDimitry Andric }
6955ffd83dbSDimitry Andric
GetArgumentValues(Thread & thread,ValueList & values) const6965ffd83dbSDimitry Andric bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
6975ffd83dbSDimitry Andric return false;
6985ffd83dbSDimitry Andric }
6995ffd83dbSDimitry Andric
SetReturnValueObject(lldb::StackFrameSP & frame_sp,lldb::ValueObjectSP & new_value_sp)7005ffd83dbSDimitry Andric Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
7015ffd83dbSDimitry Andric lldb::ValueObjectSP &new_value_sp) {
7025ffd83dbSDimitry Andric Status error;
7035ffd83dbSDimitry Andric if (!new_value_sp) {
7045ffd83dbSDimitry Andric error.SetErrorString("Empty value object for return value.");
7055ffd83dbSDimitry Andric return error;
7065ffd83dbSDimitry Andric }
7075ffd83dbSDimitry Andric
7085ffd83dbSDimitry Andric CompilerType compiler_type = new_value_sp->GetCompilerType();
7095ffd83dbSDimitry Andric if (!compiler_type) {
7105ffd83dbSDimitry Andric error.SetErrorString("Null clang type for return value.");
7115ffd83dbSDimitry Andric return error;
7125ffd83dbSDimitry Andric }
7135ffd83dbSDimitry Andric
7145ffd83dbSDimitry Andric Thread *thread = frame_sp->GetThread().get();
7155ffd83dbSDimitry Andric
7165ffd83dbSDimitry Andric bool is_signed;
7175ffd83dbSDimitry Andric uint32_t count;
7185ffd83dbSDimitry Andric bool is_complex;
7195ffd83dbSDimitry Andric
7205ffd83dbSDimitry Andric RegisterContext *reg_ctx = thread->GetRegisterContext().get();
7215ffd83dbSDimitry Andric
7225ffd83dbSDimitry Andric bool set_it_simple = false;
7235ffd83dbSDimitry Andric if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
7245ffd83dbSDimitry Andric compiler_type.IsPointerType()) {
7255ffd83dbSDimitry Andric DataExtractor data;
7265ffd83dbSDimitry Andric Status data_error;
7275ffd83dbSDimitry Andric size_t num_bytes = new_value_sp->GetData(data, data_error);
7285ffd83dbSDimitry Andric if (data_error.Fail()) {
7295ffd83dbSDimitry Andric error.SetErrorStringWithFormat(
7305ffd83dbSDimitry Andric "Couldn't convert return value to raw data: %s",
7315ffd83dbSDimitry Andric data_error.AsCString());
7325ffd83dbSDimitry Andric return error;
7335ffd83dbSDimitry Andric }
7345ffd83dbSDimitry Andric
7355ffd83dbSDimitry Andric lldb::offset_t offset = 0;
7365ffd83dbSDimitry Andric if (num_bytes <= 8) {
7375ffd83dbSDimitry Andric const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
7385ffd83dbSDimitry Andric if (num_bytes <= 4) {
7395ffd83dbSDimitry Andric uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
7405ffd83dbSDimitry Andric
7415ffd83dbSDimitry Andric if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
7425ffd83dbSDimitry Andric set_it_simple = true;
7435ffd83dbSDimitry Andric } else {
7445ffd83dbSDimitry Andric uint32_t raw_value = data.GetMaxU32(&offset, 4);
7455ffd83dbSDimitry Andric
7465ffd83dbSDimitry Andric if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
7475ffd83dbSDimitry Andric const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
7485ffd83dbSDimitry Andric uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
7495ffd83dbSDimitry Andric
7505ffd83dbSDimitry Andric if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
7515ffd83dbSDimitry Andric set_it_simple = true;
7525ffd83dbSDimitry Andric }
7535ffd83dbSDimitry Andric }
7545ffd83dbSDimitry Andric } else {
7555ffd83dbSDimitry Andric error.SetErrorString("We don't support returning longer than 64 bit "
7565ffd83dbSDimitry Andric "integer values at present.");
7575ffd83dbSDimitry Andric }
7585ffd83dbSDimitry Andric } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
7595ffd83dbSDimitry Andric if (is_complex)
7605ffd83dbSDimitry Andric error.SetErrorString(
7615ffd83dbSDimitry Andric "We don't support returning complex values at present");
7625ffd83dbSDimitry Andric else
7635ffd83dbSDimitry Andric error.SetErrorString(
7645ffd83dbSDimitry Andric "We don't support returning float values at present");
7655ffd83dbSDimitry Andric }
7665ffd83dbSDimitry Andric
7675ffd83dbSDimitry Andric if (!set_it_simple)
7685ffd83dbSDimitry Andric error.SetErrorString(
7695ffd83dbSDimitry Andric "We only support setting simple integer return types at present.");
7705ffd83dbSDimitry Andric
7715ffd83dbSDimitry Andric return error;
7725ffd83dbSDimitry Andric }
7735ffd83dbSDimitry Andric
GetReturnValueObjectSimple(Thread & thread,CompilerType & return_compiler_type) const7745ffd83dbSDimitry Andric ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
7755ffd83dbSDimitry Andric Thread &thread, CompilerType &return_compiler_type) const {
7765ffd83dbSDimitry Andric ValueObjectSP return_valobj_sp;
7775ffd83dbSDimitry Andric return return_valobj_sp;
7785ffd83dbSDimitry Andric }
7795ffd83dbSDimitry Andric
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const7805ffd83dbSDimitry Andric ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
7815ffd83dbSDimitry Andric Thread &thread, CompilerType &return_compiler_type) const {
7825ffd83dbSDimitry Andric ValueObjectSP return_valobj_sp;
7835ffd83dbSDimitry Andric Value value;
7845ffd83dbSDimitry Andric
7855ffd83dbSDimitry Andric if (!return_compiler_type)
7865ffd83dbSDimitry Andric return return_valobj_sp;
7875ffd83dbSDimitry Andric
7885ffd83dbSDimitry Andric ExecutionContext exe_ctx(thread.shared_from_this());
7895ffd83dbSDimitry Andric if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
7905ffd83dbSDimitry Andric return return_valobj_sp;
7915ffd83dbSDimitry Andric
7925ffd83dbSDimitry Andric Target *target = exe_ctx.GetTargetPtr();
7935ffd83dbSDimitry Andric const ArchSpec target_arch = target->GetArchitecture();
7945ffd83dbSDimitry Andric ByteOrder target_byte_order = target_arch.GetByteOrder();
7955ffd83dbSDimitry Andric value.SetCompilerType(return_compiler_type);
7965ffd83dbSDimitry Andric uint32_t fp_flag =
7975ffd83dbSDimitry Andric target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
7985ffd83dbSDimitry Andric
7995ffd83dbSDimitry Andric RegisterContext *reg_ctx = thread.GetRegisterContext().get();
8005ffd83dbSDimitry Andric if (!reg_ctx)
8015ffd83dbSDimitry Andric return return_valobj_sp;
8025ffd83dbSDimitry Andric
8035ffd83dbSDimitry Andric bool is_signed = false;
8045ffd83dbSDimitry Andric bool is_complex = false;
8055ffd83dbSDimitry Andric uint32_t count = 0;
8065ffd83dbSDimitry Andric
8075ffd83dbSDimitry Andric // In MIPS register "r2" (v0) holds the integer function return values
8085ffd83dbSDimitry Andric const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
809bdd1243dSDimitry Andric std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
8105ffd83dbSDimitry Andric if (!bit_width)
8115ffd83dbSDimitry Andric return return_valobj_sp;
8125ffd83dbSDimitry Andric if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
8135ffd83dbSDimitry Andric switch (*bit_width) {
8145ffd83dbSDimitry Andric default:
8155ffd83dbSDimitry Andric return return_valobj_sp;
8165ffd83dbSDimitry Andric case 64: {
8175ffd83dbSDimitry Andric const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
8185ffd83dbSDimitry Andric uint64_t raw_value;
8195ffd83dbSDimitry Andric raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
8205ffd83dbSDimitry Andric raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
8215ffd83dbSDimitry Andric UINT32_MAX))
8225ffd83dbSDimitry Andric << 32;
8235ffd83dbSDimitry Andric if (is_signed)
8245ffd83dbSDimitry Andric value.GetScalar() = (int64_t)raw_value;
8255ffd83dbSDimitry Andric else
8265ffd83dbSDimitry Andric value.GetScalar() = (uint64_t)raw_value;
8275ffd83dbSDimitry Andric } break;
8285ffd83dbSDimitry Andric case 32:
8295ffd83dbSDimitry Andric if (is_signed)
8305ffd83dbSDimitry Andric value.GetScalar() = (int32_t)(
8315ffd83dbSDimitry Andric reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
8325ffd83dbSDimitry Andric else
8335ffd83dbSDimitry Andric value.GetScalar() = (uint32_t)(
8345ffd83dbSDimitry Andric reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
8355ffd83dbSDimitry Andric break;
8365ffd83dbSDimitry Andric case 16:
8375ffd83dbSDimitry Andric if (is_signed)
8385ffd83dbSDimitry Andric value.GetScalar() = (int16_t)(
8395ffd83dbSDimitry Andric reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
8405ffd83dbSDimitry Andric else
8415ffd83dbSDimitry Andric value.GetScalar() = (uint16_t)(
8425ffd83dbSDimitry Andric reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
8435ffd83dbSDimitry Andric break;
8445ffd83dbSDimitry Andric case 8:
8455ffd83dbSDimitry Andric if (is_signed)
8465ffd83dbSDimitry Andric value.GetScalar() = (int8_t)(
8475ffd83dbSDimitry Andric reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
8485ffd83dbSDimitry Andric else
8495ffd83dbSDimitry Andric value.GetScalar() = (uint8_t)(
8505ffd83dbSDimitry Andric reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
8515ffd83dbSDimitry Andric break;
8525ffd83dbSDimitry Andric }
8535ffd83dbSDimitry Andric } else if (return_compiler_type.IsPointerType()) {
8545ffd83dbSDimitry Andric uint32_t ptr =
8555ffd83dbSDimitry Andric thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
8565ffd83dbSDimitry Andric UINT32_MAX;
8575ffd83dbSDimitry Andric value.GetScalar() = ptr;
8585ffd83dbSDimitry Andric } else if (return_compiler_type.IsAggregateType()) {
8595ffd83dbSDimitry Andric // Structure/Vector is always passed in memory and pointer to that memory
8605ffd83dbSDimitry Andric // is passed in r2.
8615ffd83dbSDimitry Andric uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
8625ffd83dbSDimitry Andric reg_ctx->GetRegisterInfoByName("r2", 0), 0);
8635ffd83dbSDimitry Andric // We have got the address. Create a memory object out of it
8645ffd83dbSDimitry Andric return_valobj_sp = ValueObjectMemory::Create(
8655ffd83dbSDimitry Andric &thread, "", Address(mem_address, nullptr), return_compiler_type);
8665ffd83dbSDimitry Andric return return_valobj_sp;
8675ffd83dbSDimitry Andric } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
8685ffd83dbSDimitry Andric if (IsSoftFloat(fp_flag)) {
8695ffd83dbSDimitry Andric uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
8705ffd83dbSDimitry Andric if (count != 1 && is_complex)
8715ffd83dbSDimitry Andric return return_valobj_sp;
8725ffd83dbSDimitry Andric switch (*bit_width) {
8735ffd83dbSDimitry Andric default:
8745ffd83dbSDimitry Andric return return_valobj_sp;
8755ffd83dbSDimitry Andric case 32:
876bdd1243dSDimitry Andric static_assert(sizeof(float) == sizeof(uint32_t));
8775ffd83dbSDimitry Andric value.GetScalar() = *((float *)(&raw_value));
8785ffd83dbSDimitry Andric break;
8795ffd83dbSDimitry Andric case 64:
880bdd1243dSDimitry Andric static_assert(sizeof(double) == sizeof(uint64_t));
8815ffd83dbSDimitry Andric const RegisterInfo *r3_reg_info =
8825ffd83dbSDimitry Andric reg_ctx->GetRegisterInfoByName("r3", 0);
8835ffd83dbSDimitry Andric if (target_byte_order == eByteOrderLittle)
8845ffd83dbSDimitry Andric raw_value =
8855ffd83dbSDimitry Andric ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
8865ffd83dbSDimitry Andric raw_value;
8875ffd83dbSDimitry Andric else
8885ffd83dbSDimitry Andric raw_value = (raw_value << 32) |
8895ffd83dbSDimitry Andric reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
8905ffd83dbSDimitry Andric value.GetScalar() = *((double *)(&raw_value));
8915ffd83dbSDimitry Andric break;
8925ffd83dbSDimitry Andric }
8935ffd83dbSDimitry Andric }
8945ffd83dbSDimitry Andric
8955ffd83dbSDimitry Andric else {
8965ffd83dbSDimitry Andric const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
8975ffd83dbSDimitry Andric RegisterValue f0_value;
8985ffd83dbSDimitry Andric DataExtractor f0_data;
8995ffd83dbSDimitry Andric reg_ctx->ReadRegister(f0_info, f0_value);
9005ffd83dbSDimitry Andric f0_value.GetData(f0_data);
9015ffd83dbSDimitry Andric lldb::offset_t offset = 0;
9025ffd83dbSDimitry Andric
9035ffd83dbSDimitry Andric if (count == 1 && !is_complex) {
9045ffd83dbSDimitry Andric switch (*bit_width) {
9055ffd83dbSDimitry Andric default:
9065ffd83dbSDimitry Andric return return_valobj_sp;
9075ffd83dbSDimitry Andric case 64: {
908bdd1243dSDimitry Andric static_assert(sizeof(double) == sizeof(uint64_t));
9095ffd83dbSDimitry Andric const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
9105ffd83dbSDimitry Andric RegisterValue f1_value;
9115ffd83dbSDimitry Andric DataExtractor f1_data;
9125ffd83dbSDimitry Andric reg_ctx->ReadRegister(f1_info, f1_value);
9135ffd83dbSDimitry Andric DataExtractor *copy_from_extractor = nullptr;
91481ad6265SDimitry Andric WritableDataBufferSP data_sp(new DataBufferHeap(8, 0));
9155ffd83dbSDimitry Andric DataExtractor return_ext(
9165ffd83dbSDimitry Andric data_sp, target_byte_order,
9175ffd83dbSDimitry Andric target->GetArchitecture().GetAddressByteSize());
9185ffd83dbSDimitry Andric
9195ffd83dbSDimitry Andric if (target_byte_order == eByteOrderLittle) {
9205ffd83dbSDimitry Andric copy_from_extractor = &f0_data;
9215ffd83dbSDimitry Andric copy_from_extractor->CopyByteOrderedData(
9225ffd83dbSDimitry Andric offset, 4, data_sp->GetBytes(), 4, target_byte_order);
9235ffd83dbSDimitry Andric f1_value.GetData(f1_data);
9245ffd83dbSDimitry Andric copy_from_extractor = &f1_data;
9255ffd83dbSDimitry Andric copy_from_extractor->CopyByteOrderedData(
9265ffd83dbSDimitry Andric offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
9275ffd83dbSDimitry Andric } else {
9285ffd83dbSDimitry Andric copy_from_extractor = &f0_data;
9295ffd83dbSDimitry Andric copy_from_extractor->CopyByteOrderedData(
9305ffd83dbSDimitry Andric offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
9315ffd83dbSDimitry Andric f1_value.GetData(f1_data);
9325ffd83dbSDimitry Andric copy_from_extractor = &f1_data;
9335ffd83dbSDimitry Andric copy_from_extractor->CopyByteOrderedData(
9345ffd83dbSDimitry Andric offset, 4, data_sp->GetBytes(), 4, target_byte_order);
9355ffd83dbSDimitry Andric }
9365ffd83dbSDimitry Andric value.GetScalar() = (double)return_ext.GetDouble(&offset);
9375ffd83dbSDimitry Andric break;
9385ffd83dbSDimitry Andric }
9395ffd83dbSDimitry Andric case 32: {
940bdd1243dSDimitry Andric static_assert(sizeof(float) == sizeof(uint32_t));
9415ffd83dbSDimitry Andric value.GetScalar() = (float)f0_data.GetFloat(&offset);
9425ffd83dbSDimitry Andric break;
9435ffd83dbSDimitry Andric }
9445ffd83dbSDimitry Andric }
9455ffd83dbSDimitry Andric } else {
9465ffd83dbSDimitry Andric // not handled yet
9475ffd83dbSDimitry Andric return return_valobj_sp;
9485ffd83dbSDimitry Andric }
9495ffd83dbSDimitry Andric }
9505ffd83dbSDimitry Andric } else {
9515ffd83dbSDimitry Andric // not handled yet
9525ffd83dbSDimitry Andric return return_valobj_sp;
9535ffd83dbSDimitry Andric }
9545ffd83dbSDimitry Andric
9555ffd83dbSDimitry Andric // If we get here, we have a valid Value, so make our ValueObject out of it:
9565ffd83dbSDimitry Andric
9575ffd83dbSDimitry Andric return_valobj_sp = ValueObjectConstResult::Create(
9585ffd83dbSDimitry Andric thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
9595ffd83dbSDimitry Andric return return_valobj_sp;
9605ffd83dbSDimitry Andric }
9615ffd83dbSDimitry Andric
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)9625ffd83dbSDimitry Andric bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
9635ffd83dbSDimitry Andric unwind_plan.Clear();
9645ffd83dbSDimitry Andric unwind_plan.SetRegisterKind(eRegisterKindDWARF);
9655ffd83dbSDimitry Andric
9665ffd83dbSDimitry Andric UnwindPlan::RowSP row(new UnwindPlan::Row);
9675ffd83dbSDimitry Andric
9685ffd83dbSDimitry Andric // Our Call Frame Address is the stack pointer value
9695ffd83dbSDimitry Andric row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
9705ffd83dbSDimitry Andric
9715ffd83dbSDimitry Andric // The previous PC is in the RA
9725ffd83dbSDimitry Andric row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
9735ffd83dbSDimitry Andric unwind_plan.AppendRow(row);
9745ffd83dbSDimitry Andric
9755ffd83dbSDimitry Andric // All other registers are the same.
9765ffd83dbSDimitry Andric
9775ffd83dbSDimitry Andric unwind_plan.SetSourceName("mips at-func-entry default");
9785ffd83dbSDimitry Andric unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
9795ffd83dbSDimitry Andric unwind_plan.SetReturnAddressRegister(dwarf_r31);
9805ffd83dbSDimitry Andric return true;
9815ffd83dbSDimitry Andric }
9825ffd83dbSDimitry Andric
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)9835ffd83dbSDimitry Andric bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
9845ffd83dbSDimitry Andric unwind_plan.Clear();
9855ffd83dbSDimitry Andric unwind_plan.SetRegisterKind(eRegisterKindDWARF);
9865ffd83dbSDimitry Andric
9875ffd83dbSDimitry Andric UnwindPlan::RowSP row(new UnwindPlan::Row);
9885ffd83dbSDimitry Andric
989fe6060f1SDimitry Andric row->SetUnspecifiedRegistersAreUndefined(true);
9905ffd83dbSDimitry Andric row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
9915ffd83dbSDimitry Andric
9925ffd83dbSDimitry Andric row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
9935ffd83dbSDimitry Andric
9945ffd83dbSDimitry Andric unwind_plan.AppendRow(row);
9955ffd83dbSDimitry Andric unwind_plan.SetSourceName("mips default unwind plan");
9965ffd83dbSDimitry Andric unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
9975ffd83dbSDimitry Andric unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
9985ffd83dbSDimitry Andric unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
9995ffd83dbSDimitry Andric return true;
10005ffd83dbSDimitry Andric }
10015ffd83dbSDimitry Andric
RegisterIsVolatile(const RegisterInfo * reg_info)10025ffd83dbSDimitry Andric bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
10035ffd83dbSDimitry Andric return !RegisterIsCalleeSaved(reg_info);
10045ffd83dbSDimitry Andric }
10055ffd83dbSDimitry Andric
IsSoftFloat(uint32_t fp_flags) const10065ffd83dbSDimitry Andric bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
10075ffd83dbSDimitry Andric return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
10085ffd83dbSDimitry Andric }
10095ffd83dbSDimitry Andric
RegisterIsCalleeSaved(const RegisterInfo * reg_info)10105ffd83dbSDimitry Andric bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
10115ffd83dbSDimitry Andric if (reg_info) {
10125ffd83dbSDimitry Andric // Preserved registers are :
10135ffd83dbSDimitry Andric // r16-r23, r28, r29, r30, r31
10145ffd83dbSDimitry Andric const char *name = reg_info->name;
10155ffd83dbSDimitry Andric
10165ffd83dbSDimitry Andric if (name[0] == 'r') {
10175ffd83dbSDimitry Andric switch (name[1]) {
10185ffd83dbSDimitry Andric case '1':
10195ffd83dbSDimitry Andric if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
10205ffd83dbSDimitry Andric name[2] == '9') // r16-r19
10215ffd83dbSDimitry Andric return name[3] == '\0';
10225ffd83dbSDimitry Andric break;
10235ffd83dbSDimitry Andric case '2':
10245ffd83dbSDimitry Andric if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
10255ffd83dbSDimitry Andric name[2] == '3' // r20-r23
10265ffd83dbSDimitry Andric || name[2] == '8' || name[2] == '9') // r28 and r29
10275ffd83dbSDimitry Andric return name[3] == '\0';
10285ffd83dbSDimitry Andric break;
10295ffd83dbSDimitry Andric case '3':
10305ffd83dbSDimitry Andric if (name[2] == '0' || name[2] == '1') // r30 and r31
10315ffd83dbSDimitry Andric return name[3] == '\0';
10325ffd83dbSDimitry Andric break;
10335ffd83dbSDimitry Andric }
10345ffd83dbSDimitry Andric
10355ffd83dbSDimitry Andric if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
10365ffd83dbSDimitry Andric return true;
10375ffd83dbSDimitry Andric if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
10385ffd83dbSDimitry Andric return true;
10395ffd83dbSDimitry Andric if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
10405ffd83dbSDimitry Andric return true;
10415ffd83dbSDimitry Andric if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
10425ffd83dbSDimitry Andric return true;
10435ffd83dbSDimitry Andric }
10445ffd83dbSDimitry Andric }
10455ffd83dbSDimitry Andric return false;
10465ffd83dbSDimitry Andric }
10475ffd83dbSDimitry Andric
Initialize()10485ffd83dbSDimitry Andric void ABISysV_mips::Initialize() {
10495ffd83dbSDimitry Andric PluginManager::RegisterPlugin(
10505ffd83dbSDimitry Andric GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
10515ffd83dbSDimitry Andric }
10525ffd83dbSDimitry Andric
Terminate()10535ffd83dbSDimitry Andric void ABISysV_mips::Terminate() {
10545ffd83dbSDimitry Andric PluginManager::UnregisterPlugin(CreateInstance);
10555ffd83dbSDimitry Andric }
1056