]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
Update llvm, clang and lldb to release_38 branch r260756.
[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     const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
246
247     if (log)
248         log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0);
249
250     /* Write r0 with 0, in case we are stopped in syscall,
251      * such setting prevents automatic decrement of the PC.
252      * This clears the bug 23659 for MIPS.
253     */ 
254     if (!reg_ctx->WriteRegisterFromUnsigned (r0_info, (uint64_t)0))
255         return false;
256
257     if (log)
258         log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
259
260     // Set "sp" to the requested value
261     if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
262         return false;
263
264     if (log)
265         log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
266
267     // Set "ra" to the return address
268     if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_info, return_addr))
269         return false;
270
271     if (log)
272         log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
273
274     // Set pc to the address of the called function.
275     if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
276         return false;
277     
278     if (log)
279         log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
280     
281     // All callers of position independent functions must place the address of the called function in t9 (r25)
282     if (!reg_ctx->WriteRegisterFromUnsigned (r25_info, func_addr))
283         return false;
284   
285     return true;
286 }
287
288 bool
289 ABISysV_mips::GetArgumentValues (Thread &thread, ValueList &values) const
290 {
291     return false;
292 }
293
294 Error
295 ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
296 {
297     Error error;
298     if (!new_value_sp)
299     {
300         error.SetErrorString("Empty value object for return value.");
301         return error;
302     }
303
304     CompilerType compiler_type = new_value_sp->GetCompilerType();
305     if (!compiler_type)
306     {
307         error.SetErrorString ("Null clang type for return value.");
308         return error;
309     }
310
311     Thread *thread = frame_sp->GetThread().get();
312
313     bool is_signed;
314     uint32_t count;
315     bool is_complex;
316
317     RegisterContext *reg_ctx = thread->GetRegisterContext().get();
318
319     bool set_it_simple = false;
320     if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
321     {
322         DataExtractor data;
323         Error data_error;
324         size_t num_bytes = new_value_sp->GetData(data, data_error);
325         if (data_error.Fail())
326         {
327             error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
328             return error;
329         }
330
331         lldb::offset_t offset = 0;
332         if (num_bytes <= 8)
333         {
334             const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
335             if (num_bytes <= 4)
336             {
337                 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
338
339                 if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
340                     set_it_simple = true;
341             }
342             else
343             {
344                 uint32_t raw_value = data.GetMaxU32(&offset, 4);
345
346                 if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
347                 {
348                     const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
349                     uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
350
351                     if (reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value))
352                         set_it_simple = true;
353                 }
354             }
355         }
356         else
357         {
358             error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
359         }
360     }
361     else if (compiler_type.IsFloatingPointType (count, is_complex))
362     {
363         if (is_complex)
364             error.SetErrorString ("We don't support returning complex values at present");
365         else
366             error.SetErrorString ("We don't support returning float values at present");
367     }
368
369     if (!set_it_simple)
370         error.SetErrorString ("We only support setting simple integer return types at present.");
371
372     return error;
373 }
374
375
376 ValueObjectSP
377 ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const
378 {
379     ValueObjectSP return_valobj_sp;
380     return return_valobj_sp;
381 }
382
383 ValueObjectSP
384 ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
385 {
386     ValueObjectSP return_valobj_sp;
387     Value value;
388
389     if (!return_compiler_type)
390         return return_valobj_sp;
391
392     ExecutionContext exe_ctx (thread.shared_from_this());
393     if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
394         return return_valobj_sp;
395
396     value.SetCompilerType(return_compiler_type);
397
398     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
399     if (!reg_ctx)
400         return return_valobj_sp;
401     
402     bool is_signed = false;
403     bool is_complex = false;
404     uint32_t count = 0;
405
406     // In MIPS register "r2" (v0) holds the integer function return values
407     const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
408     size_t bit_width = return_compiler_type.GetBitSize(&thread);
409     
410     if (return_compiler_type.IsIntegerType (is_signed))
411     {
412         switch (bit_width)
413         {
414             default:
415                 return return_valobj_sp;
416             case 64:
417             {
418                 const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
419                 uint64_t raw_value;
420                 raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
421                 raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) & UINT32_MAX)) << 32;
422                 if (is_signed)
423                     value.GetScalar() = (int64_t)raw_value;
424                 else
425                     value.GetScalar() = (uint64_t)raw_value;
426             }
427                 break;
428             case 32:
429                 if (is_signed)
430                     value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
431                 else
432                     value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
433                 break;
434             case 16:
435                 if (is_signed)
436                     value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
437                 else
438                     value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
439                 break;
440             case 8:
441                 if (is_signed)
442                     value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
443                 else
444                     value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
445                 break;
446         }
447     }
448     else if (return_compiler_type.IsPointerType ())
449     {
450         uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
451         value.GetScalar() = ptr;
452     }
453     else if (return_compiler_type.IsAggregateType ())
454     {
455         // Structure/Vector is always passed in memory and pointer to that memory is passed in r2. 
456         uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
457         // We have got the address. Create a memory object out of it
458         return_valobj_sp = ValueObjectMemory::Create (&thread,
459                                                       "",
460                                                       Address (mem_address, NULL),
461                                                       return_compiler_type);
462         return return_valobj_sp;
463     }
464     else if (return_compiler_type.IsFloatingPointType (count, is_complex))
465     {
466         const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
467         const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
468
469         if (count == 1 && !is_complex)
470         {
471             switch (bit_width)
472             {
473                 default:
474                     return return_valobj_sp;
475                 case 64:
476                 {
477                     static_assert(sizeof(double) == sizeof(uint64_t), "");
478                     uint64_t raw_value;
479                     raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
480                     raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32;
481                     value.GetScalar() = *reinterpret_cast<double*>(&raw_value);
482                     break;
483                 }
484                 case 32:
485                 {
486                     static_assert(sizeof(float) == sizeof(uint32_t), "");
487                     uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
488                     value.GetScalar() = *reinterpret_cast<float*>(&raw_value);
489                     break;
490                 }
491             }
492         }
493         else
494         {
495             // not handled yet
496             return return_valobj_sp;
497         }
498     }
499     else
500     {
501         // not handled yet
502         return return_valobj_sp;
503     }
504     
505     // If we get here, we have a valid Value, so make our ValueObject out of it:
506
507     return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
508                                                       value,
509                                                       ConstString(""));
510     return return_valobj_sp;
511 }
512
513 bool
514 ABISysV_mips::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
515 {
516     unwind_plan.Clear();
517     unwind_plan.SetRegisterKind (eRegisterKindDWARF);
518
519     UnwindPlan::RowSP row(new UnwindPlan::Row);
520
521     // Our Call Frame Address is the stack pointer value
522     row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
523
524     // The previous PC is in the RA
525     row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
526     unwind_plan.AppendRow (row);
527
528     // All other registers are the same.
529
530     unwind_plan.SetSourceName ("mips at-func-entry default");
531     unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
532     unwind_plan.SetReturnAddressRegister(dwarf_r31);
533     return true;
534 }
535
536 bool
537 ABISysV_mips::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
538 {
539     unwind_plan.Clear();
540     unwind_plan.SetRegisterKind (eRegisterKindDWARF);
541
542     UnwindPlan::RowSP row(new UnwindPlan::Row);
543
544     row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
545
546     row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
547         
548     unwind_plan.AppendRow (row);
549     unwind_plan.SetSourceName ("mips default unwind plan");
550     unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
551     unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
552     return true;
553 }
554
555 bool
556 ABISysV_mips::RegisterIsVolatile (const RegisterInfo *reg_info)
557 {
558     return !RegisterIsCalleeSaved (reg_info);
559 }
560
561 bool
562 ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
563 {
564     if (reg_info)
565     {
566         // Preserved registers are :
567         // r16-r23, r28, r29, r30, r31
568         const char *name = reg_info->name;
569
570         if (name[0] == 'r')
571         {
572             switch (name[1])
573             {
574                 case '1': 
575                     if (name[2] == '6' || name[2] == '7' || name[2] == '8' || name[2] == '9') // r16-r19
576                         return name[3] == '\0';
577                 break;
578                 case '2': 
579                     if (name[2] == '0' || name[2] == '1' || name[2] == '2' || name[2] == '3'  // r20-r23
580                         || name[2] == '8' || name[2] == '9')                                  // r28 and r29
581                         return name[3] == '\0';
582                 break;
583                 case '3': 
584                     if (name[2] == '0' || name[2] == '1')       // r30 and r31
585                         return name[3] == '\0';
586                 break;
587             }
588
589             if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0')   // gp (r28)
590                 return true;
591             if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')   // sp (r29)
592                 return true;
593             if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0')   // fp (r30)
594                 return true;
595             if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0')   // ra (r31)
596                 return true;
597         }
598     }
599     return false;
600 }
601
602 void
603 ABISysV_mips::Initialize()
604 {
605     PluginManager::RegisterPlugin (GetPluginNameStatic(),
606                                    "System V ABI for mips targets",
607                                    CreateInstance);
608 }
609
610 void
611 ABISysV_mips::Terminate()
612 {
613     PluginManager::UnregisterPlugin (CreateInstance);
614 }
615
616 lldb_private::ConstString
617 ABISysV_mips::GetPluginNameStatic()
618 {
619     static ConstString g_name("sysv-mips");
620     return g_name;
621 }
622
623 //------------------------------------------------------------------
624 // PluginInterface protocol
625 //------------------------------------------------------------------
626 lldb_private::ConstString
627 ABISysV_mips::GetPluginName()
628 {
629     return GetPluginNameStatic();
630 }
631
632 uint32_t
633 ABISysV_mips::GetPluginVersion()
634 {
635     return 1;
636 }