]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
Merge ^/head r293430 through r293685.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / ABI / SysV-mips / ABISysV_mips.cpp
1 //===-- ABISysV_mips.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "ABISysV_mips.h"
11
12 #include "lldb/Core/ConstString.h"
13 #include "lldb/Core/DataExtractor.h"
14 #include "lldb/Core/Error.h"
15 #include "lldb/Core/Log.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/RegisterValue.h"
19 #include "lldb/Core/Value.h"
20 #include "lldb/Core/ValueObjectConstResult.h"
21 #include "lldb/Core/ValueObjectRegister.h"
22 #include "lldb/Core/ValueObjectMemory.h"
23 #include "lldb/Symbol/UnwindPlan.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Process.h"
26 #include "lldb/Target/RegisterContext.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Thread.h"
29
30 #include "llvm/ADT/STLExtras.h"
31 #include "llvm/ADT/Triple.h"
32
33 using namespace lldb;
34 using namespace lldb_private;
35
36 enum dwarf_regnums
37 {
38     dwarf_r0 = 0,
39     dwarf_r1,
40     dwarf_r2,
41     dwarf_r3,
42     dwarf_r4,
43     dwarf_r5,
44     dwarf_r6,
45     dwarf_r7,
46     dwarf_r8,
47     dwarf_r9,
48     dwarf_r10,
49     dwarf_r11,
50     dwarf_r12,
51     dwarf_r13,
52     dwarf_r14,
53     dwarf_r15,
54     dwarf_r16,
55     dwarf_r17,
56     dwarf_r18,
57     dwarf_r19,
58     dwarf_r20,
59     dwarf_r21,
60     dwarf_r22,
61     dwarf_r23,
62     dwarf_r24,
63     dwarf_r25,
64     dwarf_r26,
65     dwarf_r27,
66     dwarf_r28,
67     dwarf_r29,
68     dwarf_r30,
69     dwarf_r31,
70     dwarf_sr,
71     dwarf_lo,
72     dwarf_hi,
73     dwarf_bad,
74     dwarf_cause,
75     dwarf_pc
76 };
77
78 static const RegisterInfo
79 g_register_infos[] =
80 {
81    //  NAME      ALT    SZ OFF ENCODING        FORMAT         EH_FRAME           DWARF                   GENERIC                     PROCESS PLUGINS         LLDB NATIVE            VALUE REGS  INVALIDATE REGS
82   //  ========  ======  == === =============  ===========    ============       ==============          ============                =================       ===================     ========== =================
83     { "r0"    , "zero", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r0,          dwarf_r0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
84     { "r1"    , "AT",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r1,          dwarf_r1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
85     { "r2"    , "v0",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r2,          dwarf_r2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
86     { "r3"    , "v1",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r3,          dwarf_r3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
87     { "r4"    , "arg1", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r4,          dwarf_r4,           LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
88     { "r5"    , "arg2", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r5,          dwarf_r5,           LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
89     { "r6"    , "arg3", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r6,          dwarf_r6,           LLDB_REGNUM_GENERIC_ARG3,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
90     { "r7"    , "arg4", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r7,          dwarf_r7,           LLDB_REGNUM_GENERIC_ARG4,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
91     { "r8"    , "arg5", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r8,          dwarf_r8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
92     { "r9"    , "arg6", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r9,          dwarf_r9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
93     { "r10"   , "arg7", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r10,         dwarf_r10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
94     { "r11"   , "arg8", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r11,         dwarf_r11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
95     { "r12"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r12,         dwarf_r12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
96     { "r13"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r13,         dwarf_r13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
97     { "r14"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r14,         dwarf_r14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
98     { "r15"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r15,         dwarf_r15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
99     { "r16"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r16,         dwarf_r16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
100     { "r17"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r17,         dwarf_r17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
101     { "r18"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r18,         dwarf_r18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
102     { "r19"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r19,         dwarf_r19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
103     { "r20"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r20,         dwarf_r20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
104     { "r21"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r21,         dwarf_r21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
105     { "r22"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r22,         dwarf_r22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
106     { "r23"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r23,         dwarf_r23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
107     { "r24"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r24,         dwarf_r24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
108     { "r25"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r25,         dwarf_r25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
109     { "r26"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r26,         dwarf_r26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
110     { "r27"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r27,         dwarf_r27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
111     { "r28"   , "gp",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r28,         dwarf_r28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
112     { "r29"   , "sp",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r29,         dwarf_r29,          LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
113     { "r30"   , "fp",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r30,         dwarf_r30,          LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
114     { "r31"   , "ra",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r31,         dwarf_r31,          LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
115     { "sr"    , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_sr,          dwarf_sr,           LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
116     { "lo"    , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_lo,          dwarf_lo,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
117     { "hi"    , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_hi,          dwarf_hi,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
118     { "bad"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_bad,         dwarf_bad,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
119     { "cause" , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_cause,       dwarf_cause,        LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
120     { "pc"    , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_pc,          dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},
121 };
122
123 static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
124
125 const lldb_private::RegisterInfo *
126 ABISysV_mips::GetRegisterInfoArray (uint32_t &count)
127 {
128     count = k_num_register_infos;
129     return g_register_infos;
130 }
131
132 size_t
133 ABISysV_mips::GetRedZoneSize () const
134 {
135     return 0;
136 }
137
138 //------------------------------------------------------------------
139 // Static Functions
140 //------------------------------------------------------------------
141 ABISP
142 ABISysV_mips::CreateInstance (const ArchSpec &arch)
143 {
144     static ABISP g_abi_sp;
145     const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
146     if ((arch_type == llvm::Triple::mips) ||
147         (arch_type == llvm::Triple::mipsel))
148     {
149         if (!g_abi_sp)
150             g_abi_sp.reset (new ABISysV_mips);
151         return g_abi_sp;
152     }
153     return ABISP();
154 }
155
156 bool
157 ABISysV_mips::PrepareTrivialCall (Thread &thread,
158                                   addr_t sp,
159                                   addr_t func_addr,
160                                   addr_t return_addr,
161                                   llvm::ArrayRef<addr_t> args) const
162 {
163     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
164
165     if (log)
166     {
167         StreamString s;
168         s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
169                     thread.GetID(),
170                     (uint64_t)sp,
171                     (uint64_t)func_addr,
172                     (uint64_t)return_addr);
173
174         for (size_t i = 0; i < args.size(); ++i)
175             s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
176         s.PutCString (")");
177         log->PutCString(s.GetString().c_str());
178     }
179
180     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
181     if (!reg_ctx)
182         return false;
183
184     const RegisterInfo *reg_info = NULL;
185
186     RegisterValue reg_value;
187
188     // Argument registers
189     const char *reg_names[] = { "r4", "r5", "r6", "r7" };
190
191     llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
192
193     // Write arguments to registers
194     for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i)
195     {
196         if (ai == ae)
197             break;
198
199         reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
200         if (log)
201             log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
202
203         if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
204             return false;
205
206         ++ai;
207     }
208
209     // If we have more than 4 arguments --Spill onto the stack
210     if (ai != ae)
211     {
212         // No of arguments to go on stack 
213         size_t num_stack_regs = args.size();
214
215         // Allocate needed space for args on the stack
216         sp -= (num_stack_regs * 4);
217
218         // Keep the stack 8 byte aligned
219         sp &= ~(8ull-1ull);
220
221         // just using arg1 to get the right size
222         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
223         
224         addr_t arg_pos = sp+16;
225         
226         size_t i = 4;
227         for (; ai != ae; ++ai)
228         {
229             reg_value.SetUInt32(*ai);
230             if (log)
231                 log->Printf("About to write arg%zd (0x%" PRIx64 ") at  0x%" PRIx64 "", i+1, args[i], arg_pos);
232             
233             if (reg_ctx->WriteRegisterValueToMemory(reg_info, arg_pos, reg_info->byte_size, reg_value).Fail())
234                 return false;
235             arg_pos += reg_info->byte_size;
236             i++;
237         }
238     }
239
240     Error error;
241     const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
242     const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
243     const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
244     const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
245
246     if (log)
247     log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
248
249     // Set "sp" to the requested value
250     if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
251         return false;
252
253     if (log)
254     log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
255
256     // Set "ra" to the return address
257     if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_info, return_addr))
258         return false;
259
260     if (log)
261         log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
262
263     // Set pc to the address of the called function.
264     if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
265         return false;
266     
267     if (log)
268         log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
269     
270     // All callers of position independent functions must place the address of the called function in t9 (r25)
271     if (!reg_ctx->WriteRegisterFromUnsigned (r25_info, func_addr))
272         return false;
273   
274     return true;
275 }
276
277 bool
278 ABISysV_mips::GetArgumentValues (Thread &thread, ValueList &values) const
279 {
280     return false;
281 }
282
283 Error
284 ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
285 {
286     Error error;
287     if (!new_value_sp)
288     {
289         error.SetErrorString("Empty value object for return value.");
290         return error;
291     }
292
293     CompilerType compiler_type = new_value_sp->GetCompilerType();
294     if (!compiler_type)
295     {
296         error.SetErrorString ("Null clang type for return value.");
297         return error;
298     }
299
300     Thread *thread = frame_sp->GetThread().get();
301
302     bool is_signed;
303     uint32_t count;
304     bool is_complex;
305
306     RegisterContext *reg_ctx = thread->GetRegisterContext().get();
307
308     bool set_it_simple = false;
309     if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
310     {
311         DataExtractor data;
312         Error data_error;
313         size_t num_bytes = new_value_sp->GetData(data, data_error);
314         if (data_error.Fail())
315         {
316             error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
317             return error;
318         }
319
320         lldb::offset_t offset = 0;
321         if (num_bytes <= 8)
322         {
323             const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
324             if (num_bytes <= 4)
325             {
326                 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
327
328                 if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
329                     set_it_simple = true;
330             }
331             else
332             {
333                 uint32_t raw_value = data.GetMaxU32(&offset, 4);
334
335                 if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
336                 {
337                     const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
338                     uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
339
340                     if (reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value))
341                         set_it_simple = true;
342                 }
343             }
344         }
345         else
346         {
347             error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
348         }
349     }
350     else if (compiler_type.IsFloatingPointType (count, is_complex))
351     {
352         if (is_complex)
353             error.SetErrorString ("We don't support returning complex values at present");
354         else
355             error.SetErrorString ("We don't support returning float values at present");
356     }
357
358     if (!set_it_simple)
359         error.SetErrorString ("We only support setting simple integer return types at present.");
360
361     return error;
362 }
363
364
365 ValueObjectSP
366 ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const
367 {
368     ValueObjectSP return_valobj_sp;
369     return return_valobj_sp;
370 }
371
372 ValueObjectSP
373 ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
374 {
375     ValueObjectSP return_valobj_sp;
376     Value value;
377
378     if (!return_compiler_type)
379         return return_valobj_sp;
380
381     ExecutionContext exe_ctx (thread.shared_from_this());
382     if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
383         return return_valobj_sp;
384
385     value.SetCompilerType(return_compiler_type);
386
387     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
388     if (!reg_ctx)
389         return return_valobj_sp;
390     
391     bool is_signed = false;
392     bool is_complex = false;
393     uint32_t count = 0;
394
395     // In MIPS register "r2" (v0) holds the integer function return values
396     const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
397     size_t bit_width = return_compiler_type.GetBitSize(&thread);
398     
399     if (return_compiler_type.IsIntegerType (is_signed))
400     {
401         switch (bit_width)
402         {
403             default:
404                 return return_valobj_sp;
405             case 64:
406             {
407                 const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
408                 uint64_t raw_value;
409                 raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
410                 raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) & UINT32_MAX)) << 32;
411                 if (is_signed)
412                     value.GetScalar() = (int64_t)raw_value;
413                 else
414                     value.GetScalar() = (uint64_t)raw_value;
415             }
416                 break;
417             case 32:
418                 if (is_signed)
419                     value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
420                 else
421                     value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
422                 break;
423             case 16:
424                 if (is_signed)
425                     value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
426                 else
427                     value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
428                 break;
429             case 8:
430                 if (is_signed)
431                     value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
432                 else
433                     value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
434                 break;
435         }
436     }
437     else if (return_compiler_type.IsPointerType ())
438     {
439         uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
440         value.GetScalar() = ptr;
441     }
442     else if (return_compiler_type.IsAggregateType ())
443     {
444         // Structure/Vector is always passed in memory and pointer to that memory is passed in r2. 
445         uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
446         // We have got the address. Create a memory object out of it
447         return_valobj_sp = ValueObjectMemory::Create (&thread,
448                                                       "",
449                                                       Address (mem_address, NULL),
450                                                       return_compiler_type);
451         return return_valobj_sp;
452     }
453     else if (return_compiler_type.IsFloatingPointType (count, is_complex))
454     {
455         const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
456         const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
457
458         if (count == 1 && !is_complex)
459         {
460             switch (bit_width)
461             {
462                 default:
463                     return return_valobj_sp;
464                 case 64:
465                 {
466                     static_assert(sizeof(double) == sizeof(uint64_t), "");
467                     uint64_t raw_value;
468                     raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
469                     raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32;
470                     value.GetScalar() = *reinterpret_cast<double*>(&raw_value);
471                     break;
472                 }
473                 case 32:
474                 {
475                     static_assert(sizeof(float) == sizeof(uint32_t), "");
476                     uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
477                     value.GetScalar() = *reinterpret_cast<float*>(&raw_value);
478                     break;
479                 }
480             }
481         }
482         else
483         {
484             // not handled yet
485             return return_valobj_sp;
486         }
487     }
488     else
489     {
490         // not handled yet
491         return return_valobj_sp;
492     }
493     
494     // If we get here, we have a valid Value, so make our ValueObject out of it:
495
496     return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
497                                                       value,
498                                                       ConstString(""));
499     return return_valobj_sp;
500 }
501
502 bool
503 ABISysV_mips::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
504 {
505     unwind_plan.Clear();
506     unwind_plan.SetRegisterKind (eRegisterKindDWARF);
507
508     UnwindPlan::RowSP row(new UnwindPlan::Row);
509
510     // Our Call Frame Address is the stack pointer value
511     row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
512
513     // The previous PC is in the RA
514     row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
515     unwind_plan.AppendRow (row);
516
517     // All other registers are the same.
518
519     unwind_plan.SetSourceName ("mips at-func-entry default");
520     unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
521     unwind_plan.SetReturnAddressRegister(dwarf_r31);
522     return true;
523 }
524
525 bool
526 ABISysV_mips::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
527 {
528     unwind_plan.Clear();
529     unwind_plan.SetRegisterKind (eRegisterKindDWARF);
530
531     UnwindPlan::RowSP row(new UnwindPlan::Row);
532
533     row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
534
535     row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
536         
537     unwind_plan.AppendRow (row);
538     unwind_plan.SetSourceName ("mips default unwind plan");
539     unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
540     unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
541     return true;
542 }
543
544 bool
545 ABISysV_mips::RegisterIsVolatile (const RegisterInfo *reg_info)
546 {
547     return !RegisterIsCalleeSaved (reg_info);
548 }
549
550 bool
551 ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
552 {
553     if (reg_info)
554     {
555         // Preserved registers are :
556         // r16-r23, r28, r29, r30, r31
557         const char *name = reg_info->name;
558
559         if (name[0] == 'r')
560         {
561             switch (name[1])
562             {
563                 case '1': 
564                     if (name[2] == '6' || name[2] == '7' || name[2] == '8' || name[2] == '9') // r16-r19
565                         return name[3] == '\0';
566                 break;
567                 case '2': 
568                     if (name[2] == '0' || name[2] == '1' || name[2] == '2' || name[2] == '3'  // r20-r23
569                         || name[2] == '8' || name[2] == '9')                                  // r28 and r29
570                         return name[3] == '\0';
571                 break;
572                 case '3': 
573                     if (name[2] == '0' || name[2] == '1')       // r30 and r31
574                         return name[3] == '\0';
575                 break;
576             }
577
578             if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0')   // gp (r28)
579                 return true;
580             if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')   // sp (r29)
581                 return true;
582             if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0')   // fp (r30)
583                 return true;
584             if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0')   // ra (r31)
585                 return true;
586         }
587     }
588     return false;
589 }
590
591 void
592 ABISysV_mips::Initialize()
593 {
594     PluginManager::RegisterPlugin (GetPluginNameStatic(),
595                                    "System V ABI for mips targets",
596                                    CreateInstance);
597 }
598
599 void
600 ABISysV_mips::Terminate()
601 {
602     PluginManager::UnregisterPlugin (CreateInstance);
603 }
604
605 lldb_private::ConstString
606 ABISysV_mips::GetPluginNameStatic()
607 {
608     static ConstString g_name("sysv-mips");
609     return g_name;
610 }
611
612 //------------------------------------------------------------------
613 // PluginInterface protocol
614 //------------------------------------------------------------------
615 lldb_private::ConstString
616 ABISysV_mips::GetPluginName()
617 {
618     return GetPluginNameStatic();
619 }
620
621 uint32_t
622 ABISysV_mips::GetPluginVersion()
623 {
624     return 1;
625 }