1 //===-- ABISysV_hexagon.cpp --------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "ABISysV_hexagon.h"
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/ClangASTContext.h"
24 #include "lldb/Symbol/UnwindPlan.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Process.h"
27 #include "lldb/Target/RegisterContext.h"
28 #include "lldb/Target/StackFrame.h"
29 #include "lldb/Target/Thread.h"
31 #include "llvm/ADT/Triple.h"
33 #include "llvm/IR/Type.h"
36 using namespace lldb_private;
38 static RegisterInfo g_register_infos[] =
41 { "r00" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 0, 0, LLDB_INVALID_REGNUM, 0, 0 }, NULL, NULL },
42 { "r01" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 1, 1, LLDB_INVALID_REGNUM, 1, 1 }, NULL, NULL },
43 { "r02" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 2, 2, LLDB_INVALID_REGNUM, 2, 2 }, NULL, NULL },
44 { "r03" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 3, 3, LLDB_INVALID_REGNUM, 3, 3 }, NULL, NULL },
45 { "r04" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 4, 4, LLDB_INVALID_REGNUM, 4, 4 }, NULL, NULL },
46 { "r05" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 5, 5, LLDB_INVALID_REGNUM, 5, 5 }, NULL, NULL },
47 { "r06" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 6, 6, LLDB_INVALID_REGNUM, 6, 6 }, NULL, NULL },
48 { "r07" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 7, 7, LLDB_INVALID_REGNUM, 7, 7 }, NULL, NULL },
49 { "r08" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 8, 8, LLDB_INVALID_REGNUM, 8, 8 }, NULL, NULL },
50 { "r09" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 9, 9, LLDB_INVALID_REGNUM, 9, 9 }, NULL, NULL },
51 { "r10" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 10, 10, LLDB_INVALID_REGNUM, 10, 10 }, NULL, NULL },
52 { "r11" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 11, 11, LLDB_INVALID_REGNUM, 11, 11 }, NULL, NULL },
53 { "r12" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 12, 12, LLDB_INVALID_REGNUM, 12, 12 }, NULL, NULL },
54 { "r13" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 13, 13, LLDB_INVALID_REGNUM, 13, 13 }, NULL, NULL },
55 { "r14" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 14, 14, LLDB_INVALID_REGNUM, 14, 14 }, NULL, NULL },
56 { "r15" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 15, 15, LLDB_INVALID_REGNUM, 15, 15 }, NULL, NULL },
57 { "r16" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 16, 16, LLDB_INVALID_REGNUM, 16, 16 }, NULL, NULL },
58 { "r17" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 17, 17, LLDB_INVALID_REGNUM, 17, 17 }, NULL, NULL },
59 { "r18" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 18, 18, LLDB_INVALID_REGNUM, 18, 18 }, NULL, NULL },
60 { "r19" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 19, 19, LLDB_INVALID_REGNUM, 19, 19 }, NULL, NULL },
61 { "r20" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 20, 20, LLDB_INVALID_REGNUM, 20, 20 }, NULL, NULL },
62 { "r21" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 21, 21, LLDB_INVALID_REGNUM, 21, 21 }, NULL, NULL },
63 { "r22" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 22, 22, LLDB_INVALID_REGNUM, 22, 22 }, NULL, NULL },
64 { "r23" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 23, 23, LLDB_INVALID_REGNUM, 23, 23 }, NULL, NULL },
65 { "r24" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 24, 24, LLDB_INVALID_REGNUM, 24, 24 }, NULL, NULL },
66 { "r25" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 25, 25, LLDB_INVALID_REGNUM, 25, 25 }, NULL, NULL },
67 { "r26" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 26, 26, LLDB_INVALID_REGNUM, 26, 26 }, NULL, NULL },
68 { "r27" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 27, 27, LLDB_INVALID_REGNUM, 27, 27 }, NULL, NULL },
69 { "r28" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 28, 28, LLDB_INVALID_REGNUM, 28, 28 }, NULL, NULL },
70 { "sp" ,"r29", 4, 0, eEncodingUint, eFormatAddressInfo, { 29, 29, LLDB_REGNUM_GENERIC_SP, 29, 29 }, NULL, NULL },
71 { "fp" ,"r30", 4, 0, eEncodingUint, eFormatAddressInfo, { 30, 30, LLDB_REGNUM_GENERIC_FP, 30, 30 }, NULL, NULL },
72 { "lr" ,"r31", 4, 0, eEncodingUint, eFormatAddressInfo, { 31, 31, LLDB_REGNUM_GENERIC_RA, 31, 31 }, NULL, NULL },
73 { "sa0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 32, 32, LLDB_INVALID_REGNUM, 32, 32 }, NULL, NULL },
74 { "lc0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 33, 33, LLDB_INVALID_REGNUM, 33, 33 }, NULL, NULL },
75 { "sa1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 34, 34, LLDB_INVALID_REGNUM, 34, 34 }, NULL, NULL },
76 { "lc1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 35, 35, LLDB_INVALID_REGNUM, 35, 35 }, NULL, NULL },
77 // --> hexagon-v4/5/55/56-sim.xml
78 { "p3_0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 36, 36, LLDB_INVALID_REGNUM, 36, 36 }, NULL, NULL },
80 { "p00" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 37, 37, LLDB_INVALID_REGNUM, 37, 37 }, NULL, NULL },
82 { "m0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 38, 38, LLDB_INVALID_REGNUM, 38, 38 }, NULL, NULL },
83 { "m1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 39, 39, LLDB_INVALID_REGNUM, 39, 39 }, NULL, NULL },
84 { "usr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 40, 40, LLDB_INVALID_REGNUM, 40, 40 }, NULL, NULL },
85 { "pc" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 41, 41, LLDB_REGNUM_GENERIC_PC, 41, 41 }, NULL, NULL },
86 { "ugp" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 42, 42, LLDB_INVALID_REGNUM, 42, 42 }, NULL, NULL },
87 { "gp" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 43, 43, LLDB_INVALID_REGNUM, 43, 43 }, NULL, NULL },
88 { "cs0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 44, 44, LLDB_INVALID_REGNUM, 44, 44 }, NULL, NULL },
89 { "cs1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 45, 45, LLDB_INVALID_REGNUM, 45, 45 }, NULL, NULL },
91 { "p01" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 46, 46, LLDB_INVALID_REGNUM, 46, 46 }, NULL, NULL },
92 { "p02" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 47, 47, LLDB_INVALID_REGNUM, 47, 47 }, NULL, NULL },
93 { "p03" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 48, 48, LLDB_INVALID_REGNUM, 48, 48 }, NULL, NULL },
94 { "p04" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 49, 49, LLDB_INVALID_REGNUM, 49, 49 }, NULL, NULL },
95 { "p05" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 50, 50, LLDB_INVALID_REGNUM, 50, 50 }, NULL, NULL },
96 { "p06" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 51, 51, LLDB_INVALID_REGNUM, 51, 51 }, NULL, NULL },
97 { "p07" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 52, 52, LLDB_INVALID_REGNUM, 52, 52 }, NULL, NULL },
98 { "p08" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 53, 53, LLDB_INVALID_REGNUM, 53, 53 }, NULL, NULL },
99 { "p09" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 54, 54, LLDB_INVALID_REGNUM, 54, 54 }, NULL, NULL },
100 { "p10" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 55, 55, LLDB_INVALID_REGNUM, 55, 55 }, NULL, NULL },
101 { "p11" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 56, 56, LLDB_INVALID_REGNUM, 56, 56 }, NULL, NULL },
102 { "p12" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 57, 57, LLDB_INVALID_REGNUM, 57, 57 }, NULL, NULL },
103 { "p13" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 58, 58, LLDB_INVALID_REGNUM, 58, 58 }, NULL, NULL },
104 { "p14" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 59, 59, LLDB_INVALID_REGNUM, 59, 59 }, NULL, NULL },
105 { "p15" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 60, 60, LLDB_INVALID_REGNUM, 60, 60 }, NULL, NULL },
106 { "p16" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 61, 61, LLDB_INVALID_REGNUM, 61, 61 }, NULL, NULL },
107 { "p17" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 62, 62, LLDB_INVALID_REGNUM, 62, 62 }, NULL, NULL },
108 { "p18" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 63, 63, LLDB_INVALID_REGNUM, 63, 63 }, NULL, NULL },
110 { "sgp0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 64, 64, LLDB_INVALID_REGNUM, 64, 64 }, NULL, NULL },
112 { "p19" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 65, 65, LLDB_INVALID_REGNUM, 65, 65 }, NULL, NULL },
114 { "stid" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 66, 66, LLDB_INVALID_REGNUM, 66, 66 }, NULL, NULL },
115 { "elr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 67, 67, LLDB_INVALID_REGNUM, 67, 67 }, NULL, NULL },
116 { "badva0", "", 4, 0, eEncodingUint, eFormatAddressInfo, { 68, 68, LLDB_INVALID_REGNUM, 68, 68 }, NULL, NULL },
117 { "badva1", "", 4, 0, eEncodingUint, eFormatAddressInfo, { 69, 69, LLDB_INVALID_REGNUM, 69, 69 }, NULL, NULL },
118 { "ssr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 70, 70, LLDB_INVALID_REGNUM, 70, 70 }, NULL, NULL },
119 { "ccr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 71, 71, LLDB_INVALID_REGNUM, 71, 71 }, NULL, NULL },
120 { "htid" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 72, 72, LLDB_INVALID_REGNUM, 72, 72 }, NULL, NULL },
122 { "p20" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 73, 73, LLDB_INVALID_REGNUM, 73, 73 }, NULL, NULL },
124 { "imask" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 74, 74, LLDB_INVALID_REGNUM, 74, 74 }, NULL, NULL },
126 { "p21" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 75, 75, LLDB_INVALID_REGNUM, 75, 75 }, NULL, NULL },
127 { "p22" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 76, 76, LLDB_INVALID_REGNUM, 76, 76 }, NULL, NULL },
128 { "p23" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 77, 77, LLDB_INVALID_REGNUM, 77, 77 }, NULL, NULL },
129 { "p24" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 78, 78, LLDB_INVALID_REGNUM, 78, 78 }, NULL, NULL },
130 { "p25" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 79, 79, LLDB_INVALID_REGNUM, 79, 79 }, NULL, NULL },
132 { "g0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 80, 80, LLDB_INVALID_REGNUM, 80, 80 }, NULL, NULL },
133 { "g1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 81, 81, LLDB_INVALID_REGNUM, 81, 81 }, NULL, NULL },
134 { "g2" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 82, 82, LLDB_INVALID_REGNUM, 82, 82 }, NULL, NULL },
135 { "g3" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 83, 83, LLDB_INVALID_REGNUM, 83, 83 }, NULL, NULL }
138 static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
139 static bool g_register_info_names_constified = false;
141 const lldb_private::RegisterInfo *
142 ABISysV_hexagon::GetRegisterInfoArray ( uint32_t &count )
144 // Make the C-string names and alt_names for the register infos into const
145 // C-string values by having the ConstString unique the names in the global
146 // constant C-string pool.
147 if (!g_register_info_names_constified)
149 g_register_info_names_constified = true;
150 for (uint32_t i=0; i<k_num_register_infos; ++i)
152 if (g_register_infos[i].name)
153 g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
154 if (g_register_infos[i].alt_name)
155 g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
158 count = k_num_register_infos;
159 return g_register_infos;
163 http://en.wikipedia.org/wiki/Red_zone_%28computing%29
165 In computing, a red zone is a fixed size area in memory beyond the stack pointer that has not been
166 "allocated". This region of memory is not to be modified by interrupt/exception/signal handlers.
167 This allows the space to be used for temporary data without the extra overhead of modifying the
168 stack pointer. The x86-64 ABI mandates a 128 byte red zone.[1] The OpenRISC toolchain assumes a
169 128 byte red zone though it is not documented.
172 ABISysV_hexagon::GetRedZoneSize () const
177 //------------------------------------------------------------------
179 //------------------------------------------------------------------
181 ABISysV_hexagon::CreateInstance ( const ArchSpec &arch )
183 static ABISP g_abi_sp;
184 if (arch.GetTriple().getArch() == llvm::Triple::hexagon)
187 g_abi_sp.reset (new ABISysV_hexagon);
194 ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
198 llvm::ArrayRef<addr_t> args ) const
200 // we don't use the traditional trivial call specialized for jit
207 // . safeguard the current stack
208 // . how can we know that the called function will create its own frame properly?
209 // . we could manually make a new stack first:
213 // 5. SP = SP ( since no locals in our temp frame )
216 // . variable argument list parameters are not passed via registers, they are passed on
217 // the stack. This presents us with a problem, since we need to know when the valist
218 // starts. Currently I can find out if a function is varg, but not how many
219 // real parameters it takes. Thus I don't know when to start spilling the vargs. For
220 // the time being, to progress, I will assume that it takes on real parameter before
221 // the vargs list starts.
224 // . how do we adhere to the stack alignment requirements
227 // . handle 64bit values and their register / stack requirements
230 #define HEX_ABI_DEBUG 1
232 ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
236 llvm::Type &prototype,
237 llvm::ArrayRef<ABI::CallArgument> args) const
239 // default number of register passed arguments for varg functions
240 const int nVArgRegParams = 1;
243 // grab the process so we have access to the memory for spilling
244 lldb::ProcessSP proc = thread.GetProcess( );
246 // push host data onto target
247 for ( size_t i = 0; i < args.size( ); i++ )
249 const ABI::CallArgument &arg = args[i];
250 // skip over target values
251 if ( arg.type == ABI::CallArgument::TargetValue )
253 // round up to 8 byte multiple
254 size_t argSize = ( arg.size | 0x7 ) + 1;
256 // create space on the stack for this data
259 // write this argument onto the stack of the host process
260 proc.get( )->WriteMemory( sp, arg.data, arg.size, error );
264 // update the argument with the target pointer
265 //XXX: This is a gross hack for getting around the const
266 *((size_t*)(&arg.value)) = sp;
271 // print the original stack pointer
272 printf( "sp : %04lx \n", sp );
275 // make sure number of parameters matches prototype
276 assert( prototype.getFunctionNumParams( ) == args.size( ) );
278 // check if this is a variable argument function
279 bool isVArg = prototype.isFunctionVarArg();
281 // get the register context for modifying all of the registers
282 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
286 // number of arguments passed by register
287 int nRegArgs = nVArgRegParams;
290 // number of arguments is limited by [R0 : R5] space
291 nRegArgs = args.size( );
296 // pass arguments that are passed via registers
297 for ( int i = 0; i < nRegArgs; i++ )
299 // get the parameter as a u32
300 uint32_t param = (uint32_t)args[i].value;
301 // write argument into register
302 if (!reg_ctx->WriteRegisterFromUnsigned( i, param ))
306 // number of arguments to spill onto stack
307 int nSpillArgs = args.size( ) - nRegArgs;
308 // make space on the stack for arguments
309 sp -= 4 * nSpillArgs;
310 // align stack on an 8 byte boundary
314 // arguments that are passed on the stack
315 for ( size_t i = nRegArgs, offs=0; i < args.size( ); i++ )
317 // get the parameter as a u32
318 uint32_t param = (uint32_t)args[i].value;
319 // write argument to stack
320 proc->WriteMemory( sp + offs, (void*)¶m, sizeof( param ), error );
321 if ( !error.Success( ) )
327 // update registers with current function call state
328 reg_ctx->WriteRegisterFromUnsigned ( 41, pc );
329 reg_ctx->WriteRegisterFromUnsigned ( 31, ra );
330 reg_ctx->WriteRegisterFromUnsigned ( 29, sp );
331 // reg_ctx->WriteRegisterFromUnsigned ( FP ??? );
334 // quick and dirty stack dumper for debugging
335 for ( int i = -8; i < 8; i++ )
338 lldb::addr_t addr = sp + i * 4;
339 proc->ReadMemory( addr, (void*)&data, sizeof( data ), error );
340 printf( "\n0x%04lx 0x%08x ", addr, data );
341 if ( i == 0 ) printf( "<<-- sp" );
350 ABISysV_hexagon::GetArgumentValues ( Thread &thread, ValueList &values ) const
356 ABISysV_hexagon::SetReturnValueObject ( lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp )
363 ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, ClangASTType &return_clang_type ) const
365 ValueObjectSP return_valobj_sp;
366 return return_valobj_sp;
370 ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, ClangASTType &return_clang_type ) const
372 ValueObjectSP return_valobj_sp;
373 return return_valobj_sp;
376 // called when we are on the first instruction of a new function
377 // for hexagon the return address is in RA (R31)
379 ABISysV_hexagon::CreateFunctionEntryUnwindPlan ( UnwindPlan &unwind_plan )
382 unwind_plan.SetRegisterKind(eRegisterKindGeneric);
383 unwind_plan.SetReturnAddressRegister(LLDB_REGNUM_GENERIC_RA);
385 UnwindPlan::RowSP row(new UnwindPlan::Row);
387 // Our Call Frame Address is the stack pointer value
388 row->SetCFARegister(LLDB_REGNUM_GENERIC_SP);
389 row->SetCFAOffset(4);
392 // The previous PC is in the LR
393 row->SetRegisterLocationToRegister(LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_RA, true);
394 unwind_plan.AppendRow(row);
396 unwind_plan.SetSourceName("hexagon at-func-entry default");
397 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
402 ABISysV_hexagon::CreateDefaultUnwindPlan ( UnwindPlan &unwind_plan )
405 unwind_plan.SetRegisterKind(eRegisterKindGeneric);
407 uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP;
408 uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
409 uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC;
411 UnwindPlan::RowSP row(new UnwindPlan::Row);
413 row->SetCFARegister(LLDB_REGNUM_GENERIC_FP);
414 row->SetCFAOffset(8);
416 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num,-8, true);
417 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num,-4, true);
418 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
420 unwind_plan.AppendRow(row);
421 unwind_plan.SetSourceName("hexagon default unwind plan");
422 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
423 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
428 Register Usage Saved By
430 R0 - R5 parameters(a) -
431 R6 - R15 Scratch(b) Caller
432 R16 - R27 Scratch Callee
433 R28 Scratch(b) Caller
434 R29 - R31 Stack Frames Callee(c)
435 P3:0 Processor State Caller
437 a = the caller can change parameter values
438 b = R14 - R15 and R28 are used by the procedure linkage table
439 c = R29 - R31 are saved and restored by allocframe() and deallocframe()
442 ABISysV_hexagon::RegisterIsVolatile ( const RegisterInfo *reg_info )
444 return !RegisterIsCalleeSaved( reg_info );
448 ABISysV_hexagon::RegisterIsCalleeSaved ( const RegisterInfo *reg_info )
450 int reg = ((reg_info->byte_offset) / 4);
452 bool save = (reg >= 16) && (reg <= 27);
453 save |= (reg >= 29) && (reg <= 32);
459 ABISysV_hexagon::Initialize( void )
461 PluginManager::RegisterPlugin
463 GetPluginNameStatic(),
464 "System V ABI for hexagon targets",
470 ABISysV_hexagon::Terminate( void )
472 PluginManager::UnregisterPlugin( CreateInstance );
475 lldb_private::ConstString
476 ABISysV_hexagon::GetPluginNameStatic()
478 static ConstString g_name( "sysv-hexagon" );
482 //------------------------------------------------------------------
483 // PluginInterface protocol
484 //------------------------------------------------------------------
485 lldb_private::ConstString
486 ABISysV_hexagon::GetPluginName( void )
488 return GetPluginNameStatic();
492 ABISysV_hexagon::GetPluginVersion( void )
497 // get value object specialized to work with llvm IR types
499 ABISysV_hexagon::GetReturnValueObjectImpl( lldb_private::Thread &thread, llvm::Type &retType ) const
502 ValueObjectSP vObjSP;
504 // get the current register context
505 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
509 // for now just pop R0 to find the return value
510 const lldb_private::RegisterInfo *r0_info = reg_ctx->GetRegisterInfoAtIndex( 0 );
511 if ( r0_info == nullptr )
515 if ( retType.isVoidTy( ) )
517 value.GetScalar( ) = 0;
519 // integer / pointer return type
521 if ( retType.isIntegerTy( ) || retType.isPointerTy( ) )
523 // read r0 register value
524 lldb_private::RegisterValue r0_value;
525 if ( !reg_ctx->ReadRegister( r0_info, r0_value ) )
528 // push r0 into value
529 uint32_t r0_u32 = r0_value.GetAsUInt32( );
531 // account for integer size
532 if ( retType.isIntegerTy() && retType.isSized() )
534 uint64_t size = retType.getScalarSizeInBits( );
535 uint64_t mask = ( 1ull << size ) - 1;
536 // mask out higher order bits then the type we expect
540 value.GetScalar( ) = r0_u32;
542 // unsupported return type
546 // pack the value into a ValueObjectSP
547 vObjSP = ValueObjectConstResult::Create
549 thread.GetStackFrameAtIndex(0).get(),