1 //===-- GDBRemoteRegisterContext.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 "GDBRemoteRegisterContext.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 #include "lldb/Core/DataBufferHeap.h"
16 #include "lldb/Core/DataExtractor.h"
17 #include "lldb/Core/Scalar.h"
18 #include "lldb/Core/StreamString.h"
19 // Project includes
20 #include "StringExtractorGDBRemote.h"
21 #include "ProcessGDBRemote.h"
22 #include "ThreadGDBRemote.h"
23 #include "ARM_GCC_Registers.h"
24 #include "ARM_DWARF_Registers.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //----------------------------------------------------------------------
30 // GDBRemoteRegisterContext constructor
31 //----------------------------------------------------------------------
32 GDBRemoteRegisterContext::GDBRemoteRegisterContext
33 (
34     ThreadGDBRemote &thread,
35     StackFrame *frame,
36     GDBRemoteDynamicRegisterInfo &reg_info,
37     bool read_all_at_once
38 ) :
39     RegisterContext (thread, frame),
40     m_reg_info (reg_info),
41     m_reg_valid (),
42     m_reg_data (),
43     m_read_all_at_once (read_all_at_once)
44 {
45     // Resize our vector of bools to contain one bool for every register.
46     // We will use these boolean values to know when a register value
47     // is valid in m_reg_data.
48     m_reg_valid.resize (reg_info.GetNumRegisters());
49 
50     // Make a heap based buffer that is big enough to store all registers
51     DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0));
52     m_reg_data.SetData (reg_data_sp);
53 
54 }
55 
56 //----------------------------------------------------------------------
57 // Destructor
58 //----------------------------------------------------------------------
59 GDBRemoteRegisterContext::~GDBRemoteRegisterContext()
60 {
61 }
62 
63 ProcessGDBRemote &
64 GDBRemoteRegisterContext::GetGDBProcess()
65 {
66     return static_cast<ProcessGDBRemote &>(m_thread.GetProcess());
67 }
68 
69 ThreadGDBRemote &
70 GDBRemoteRegisterContext::GetGDBThread()
71 {
72     return static_cast<ThreadGDBRemote &>(m_thread);
73 }
74 
75 void
76 GDBRemoteRegisterContext::Invalidate ()
77 {
78     SetAllRegisterValid (false);
79 }
80 
81 void
82 GDBRemoteRegisterContext::SetAllRegisterValid (bool b)
83 {
84     std::vector<bool>::iterator pos, end = m_reg_valid.end();
85     for (pos = m_reg_valid.begin(); pos != end; ++pos)
86         *pos = b;
87 }
88 
89 size_t
90 GDBRemoteRegisterContext::GetRegisterCount ()
91 {
92     return m_reg_info.GetNumRegisters ();
93 }
94 
95 const lldb::RegisterInfo *
96 GDBRemoteRegisterContext::GetRegisterInfoAtIndex (uint32_t reg)
97 {
98     return m_reg_info.GetRegisterInfoAtIndex (reg);
99 }
100 
101 size_t
102 GDBRemoteRegisterContext::GetRegisterSetCount ()
103 {
104     return m_reg_info.GetNumRegisterSets ();
105 }
106 
107 
108 
109 const lldb::RegisterSet *
110 GDBRemoteRegisterContext::GetRegisterSet (uint32_t reg_set)
111 {
112     return m_reg_info.GetRegisterSet (reg_set);
113 }
114 
115 
116 
117 bool
118 GDBRemoteRegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value)
119 {
120     // Read the register
121     if (ReadRegisterBytes (reg, m_reg_data))
122     {
123         const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
124         uint32_t offset = reg_info->byte_offset;
125         switch (reg_info->encoding)
126         {
127         case eEncodingUint:
128             switch (reg_info->byte_size)
129             {
130             case 1:
131             case 2:
132             case 4:
133                 value = m_reg_data.GetMaxU32 (&offset, reg_info->byte_size);
134                 return true;
135 
136             case 8:
137                 value = m_reg_data.GetMaxU64 (&offset, reg_info->byte_size);
138                 return true;
139             }
140             break;
141 
142         case eEncodingSint:
143             switch (reg_info->byte_size)
144             {
145             case 1:
146             case 2:
147             case 4:
148                 value = (int32_t)m_reg_data.GetMaxU32 (&offset, reg_info->byte_size);
149                 return true;
150 
151             case 8:
152                 value = m_reg_data.GetMaxS64 (&offset, reg_info->byte_size);
153                 return true;
154             }
155             break;
156 
157         case eEncodingIEEE754:
158             switch (reg_info->byte_size)
159             {
160             case sizeof (float):
161                 value = m_reg_data.GetFloat (&offset);
162                 return true;
163 
164             case sizeof (double):
165                 value = m_reg_data.GetDouble (&offset);
166                 return true;
167 
168             case sizeof (long double):
169                 value = m_reg_data.GetLongDouble (&offset);
170                 return true;
171             }
172             break;
173         }
174     }
175     return false;
176 }
177 
178 
179 bool
180 GDBRemoteRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
181 {
182     GDBRemoteCommunication &gdb_comm = GetGDBProcess().GetGDBRemote();
183 // FIXME: This check isn't right because IsRunning checks the Public state, but this
184 // is work you need to do - for instance in ShouldStop & friends - before the public
185 // state has been changed.
186 //    if (gdb_comm.IsRunning())
187 //        return false;
188 
189     if (m_reg_valid_stop_id != m_thread.GetProcess().GetStopID())
190     {
191         Invalidate();
192         m_reg_valid_stop_id = m_thread.GetProcess().GetStopID();
193     }
194     const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
195     assert (reg_info);
196     if (m_reg_valid[reg] == false)
197     {
198         Mutex::Locker locker;
199         if (gdb_comm.GetSequenceMutex (locker))
200         {
201             if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
202             {
203                 char packet[32];
204                 StringExtractorGDBRemote response;
205                 int packet_len;
206                 if (m_read_all_at_once)
207                 {
208                     // Get all registers in one packet
209                     packet_len = ::snprintf (packet, sizeof(packet), "g");
210                     assert (packet_len < (sizeof(packet) - 1));
211                     if (gdb_comm.SendPacketAndWaitForResponse(packet, response, 1, false))
212                     {
213                         if (response.IsNormalPacket())
214                             if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
215                                 SetAllRegisterValid (true);
216                     }
217                 }
218                 else
219                 {
220                     // Get each register individually
221                     packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg, false);
222                     assert (packet_len < (sizeof(packet) - 1));
223                     if (gdb_comm.SendPacketAndWaitForResponse(packet, response, 1, false))
224                         if (response.GetHexBytes ((uint8_t*)m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size), reg_info->byte_size, '\xcc') == reg_info->byte_size)
225                             m_reg_valid[reg] = true;
226                 }
227             }
228         }
229     }
230 
231     bool reg_is_valid = m_reg_valid[reg];
232     if (reg_is_valid)
233     {
234         if (&data != &m_reg_data)
235         {
236             // If we aren't extracting into our own buffer (which
237             // only happens when this function is called from
238             // ReadRegisterValue(uint32_t, Scalar&)) then
239             // we transfer bytes from our buffer into the data
240             // buffer that was passed in
241             data.SetByteOrder (m_reg_data.GetByteOrder());
242             data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size);
243         }
244     }
245     return reg_is_valid;
246 }
247 
248 
249 bool
250 GDBRemoteRegisterContext::WriteRegisterValue (uint32_t reg, const Scalar &value)
251 {
252     const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
253     if (reg_info)
254     {
255         DataExtractor data;
256         if (value.GetData (data, reg_info->byte_size))
257             return WriteRegisterBytes (reg, data, 0);
258     }
259     return false;
260 }
261 
262 
263 bool
264 GDBRemoteRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset)
265 {
266     GDBRemoteCommunication &gdb_comm = GetGDBProcess().GetGDBRemote();
267 // FIXME: This check isn't right because IsRunning checks the Public state, but this
268 // is work you need to do - for instance in ShouldStop & friends - before the public
269 // state has been changed.
270 //    if (gdb_comm.IsRunning())
271 //        return false;
272 
273     const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
274 
275     if (reg_info)
276     {
277         // Grab a pointer to where we are going to put this register
278         uint8_t *dst = (uint8_t *)m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size);
279 
280         if (dst == NULL)
281             return false;
282 
283         // Grab a pointer to where we are going to grab the new value from
284         const uint8_t *src = data.PeekData(0, reg_info->byte_size);
285 
286         if (src == NULL)
287             return false;
288 
289         if (data.GetByteOrder() == m_reg_data.GetByteOrder())
290         {
291             // No swapping, just copy the bytes
292             ::memcpy (dst, src, reg_info->byte_size);
293         }
294         else
295         {
296             // Swap the bytes
297             for (uint32_t i=0; i<reg_info->byte_size; ++i)
298                 dst[i] = src[reg_info->byte_size - 1 - i];
299         }
300 
301         Mutex::Locker locker;
302         if (gdb_comm.GetSequenceMutex (locker))
303         {
304             if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
305             {
306                 uint32_t offset, end_offset;
307                 StreamString packet;
308                 StringExtractorGDBRemote response;
309                 if (m_read_all_at_once)
310                 {
311                     // Get all registers in one packet
312                     packet.PutChar ('G');
313                     offset = 0;
314                     end_offset = m_reg_data.GetByteSize();
315 
316                     packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),
317                                               m_reg_data.GetByteSize(),
318                                               eByteOrderHost,
319                                               eByteOrderHost);
320 
321                     // Invalidate all register values
322                     Invalidate ();
323 
324                     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
325                                                               packet.GetString().size(),
326                                                               response,
327                                                               1,
328                                                               false))
329                     {
330                         SetAllRegisterValid (false);
331                         if (response.IsOKPacket())
332                         {
333                             return true;
334                         }
335                     }
336                 }
337                 else
338                 {
339                     // Get each register individually
340                     packet.Printf ("P%x=", reg);
341                     packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
342                                               reg_info->byte_size,
343                                               eByteOrderHost,
344                                               eByteOrderHost);
345 
346                     // Invalidate just this register
347                     m_reg_valid[reg] = false;
348                     if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
349                                                               packet.GetString().size(),
350                                                               response,
351                                                               1,
352                                                               false))
353                     {
354                         if (response.IsOKPacket())
355                         {
356                             return true;
357                         }
358                     }
359                 }
360             }
361         }
362     }
363     return false;
364 }
365 
366 
367 bool
368 GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
369 {
370     GDBRemoteCommunication &gdb_comm = GetGDBProcess().GetGDBRemote();
371     StringExtractorGDBRemote response;
372     if (gdb_comm.SendPacketAndWaitForResponse("g", response, 1, false))
373     {
374         if (response.IsErrorPacket())
375             return false;
376 
377         response.GetStringRef().insert(0, 1, 'G');
378         data_sp.reset (new DataBufferHeap(response.GetStringRef().data(),
379                                           response.GetStringRef().size()));
380         return true;
381     }
382     return false;
383 }
384 
385 bool
386 GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
387 {
388     GDBRemoteCommunication &gdb_comm = GetGDBProcess().GetGDBRemote();
389     StringExtractorGDBRemote response;
390     if (gdb_comm.SendPacketAndWaitForResponse((const char *)data_sp->GetBytes(),
391                                               data_sp->GetByteSize(),
392                                               response,
393                                               1,
394                                               false))
395     {
396         if (response.IsOKPacket())
397             return true;
398     }
399     return false;
400 }
401 
402 
403 uint32_t
404 GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
405 {
406     return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
407 }
408 
409 void
410 GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters()
411 {
412     static lldb::RegisterInfo
413     g_register_infos[] =
414     {
415         //  NAME        ALT     SZ  OFF   ENCODING           FORMAT          NUM      COMPILER            DWARF               GENERIC
416         //  ======      ======= ==  ====  =============      ============    ===  ===============     ===============     =========
417         {   "r0",       NULL,   4,    0,  eEncodingUint,     eFormatHex,      0,  { gcc_r0,               dwarf_r0,           LLDB_INVALID_REGNUM     }},
418         {   "r1",       NULL,   4,    4,  eEncodingUint,     eFormatHex,      1,  { gcc_r1,               dwarf_r1,           LLDB_INVALID_REGNUM     }},
419         {   "r2",       NULL,   4,    8,  eEncodingUint,     eFormatHex,      2,  { gcc_r2,               dwarf_r2,           LLDB_INVALID_REGNUM     }},
420         {   "r3",       NULL,   4,   12,  eEncodingUint,     eFormatHex,      3,  { gcc_r3,               dwarf_r3,           LLDB_INVALID_REGNUM     }},
421         {   "r4",       NULL,   4,   16,  eEncodingUint,     eFormatHex,      4,  { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM     }},
422         {   "r5",       NULL,   4,   20,  eEncodingUint,     eFormatHex,      5,  { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM     }},
423         {   "r6",       NULL,   4,   24,  eEncodingUint,     eFormatHex,      6,  { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM     }},
424         {   "r7",       NULL,   4,   28,  eEncodingUint,     eFormatHex,      7,  { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP  }},
425         {   "r8",       NULL,   4,   32,  eEncodingUint,     eFormatHex,      8,  { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM     }},
426         {   "r9",       NULL,   4,   36,  eEncodingUint,     eFormatHex,      9,  { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM     }},
427         {   "r10",      NULL,   4,   40,  eEncodingUint,     eFormatHex,     10,  { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM     }},
428         {   "r11",      NULL,   4,   44,  eEncodingUint,     eFormatHex,     11,  { gcc_r11,              dwarf_r11,          LLDB_INVALID_REGNUM     }},
429         {   "r12",      NULL,   4,   48,  eEncodingUint,     eFormatHex,     12,  { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM     }},
430         {   "sp",      "r13",   4,   52,  eEncodingUint,     eFormatHex,     13,  { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP  }},
431         {   "lr",      "r14",   4,   56,  eEncodingUint,     eFormatHex,     14,  { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA  }},
432         {   "pc",      "r15",   4,   60,  eEncodingUint,     eFormatHex,     15,  { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC  }},
433         {   NULL,       NULL,  12,   64,  eEncodingIEEE754,  eFormatFloat,   16,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
434         {   NULL,       NULL,  12,   76,  eEncodingIEEE754,  eFormatFloat,   17,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
435         {   NULL,       NULL,  12,   88,  eEncodingIEEE754,  eFormatFloat,   18,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
436         {   NULL,       NULL,  12,  100,  eEncodingIEEE754,  eFormatFloat,   19,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
437         {   NULL,       NULL,  12,  112,  eEncodingIEEE754,  eFormatFloat,   20,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
438         {   NULL,       NULL,  12,  124,  eEncodingIEEE754,  eFormatFloat,   21,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
439         {   NULL,       NULL,  12,  136,  eEncodingIEEE754,  eFormatFloat,   22,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
440         {   NULL,       NULL,  12,  148,  eEncodingIEEE754,  eFormatFloat,   23,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
441         {   NULL,       NULL,  12,  160,  eEncodingIEEE754,  eFormatFloat,   24,  { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
442         {   "cpsr",     "psr",  4,  172,  eEncodingUint,     eFormatHex,     25,  { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS   }},
443         {   "s0",       NULL,   4,  176,  eEncodingIEEE754,  eFormatFloat,   26,  { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM     }},
444         {   "s1",       NULL,   4,  180,  eEncodingIEEE754,  eFormatFloat,   27,  { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM     }},
445         {   "s2",       NULL,   4,  184,  eEncodingIEEE754,  eFormatFloat,   28,  { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM     }},
446         {   "s3",       NULL,   4,  188,  eEncodingIEEE754,  eFormatFloat,   29,  { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM     }},
447         {   "s4",       NULL,   4,  192,  eEncodingIEEE754,  eFormatFloat,   30,  { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM     }},
448         {   "s5",       NULL,   4,  196,  eEncodingIEEE754,  eFormatFloat,   31,  { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM     }},
449         {   "s6",       NULL,   4,  200,  eEncodingIEEE754,  eFormatFloat,   32,  { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM     }},
450         {   "s7",       NULL,   4,  204,  eEncodingIEEE754,  eFormatFloat,   33,  { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM     }},
451         {   "s8",       NULL,   4,  208,  eEncodingIEEE754,  eFormatFloat,   34,  { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM     }},
452         {   "s9",       NULL,   4,  212,  eEncodingIEEE754,  eFormatFloat,   35,  { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM     }},
453         {   "s10",      NULL,   4,  216,  eEncodingIEEE754,  eFormatFloat,   36,  { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM     }},
454         {   "s11",      NULL,   4,  220,  eEncodingIEEE754,  eFormatFloat,   37,  { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM     }},
455         {   "s12",      NULL,   4,  224,  eEncodingIEEE754,  eFormatFloat,   38,  { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM     }},
456         {   "s13",      NULL,   4,  228,  eEncodingIEEE754,  eFormatFloat,   39,  { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM     }},
457         {   "s14",      NULL,   4,  232,  eEncodingIEEE754,  eFormatFloat,   40,  { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM     }},
458         {   "s15",      NULL,   4,  236,  eEncodingIEEE754,  eFormatFloat,   41,  { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM     }},
459         {   "s16",      NULL,   4,  240,  eEncodingIEEE754,  eFormatFloat,   42,  { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM     }},
460         {   "s17",      NULL,   4,  244,  eEncodingIEEE754,  eFormatFloat,   43,  { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM     }},
461         {   "s18",      NULL,   4,  248,  eEncodingIEEE754,  eFormatFloat,   44,  { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM     }},
462         {   "s19",      NULL,   4,  252,  eEncodingIEEE754,  eFormatFloat,   45,  { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM     }},
463         {   "s20",      NULL,   4,  256,  eEncodingIEEE754,  eFormatFloat,   46,  { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM     }},
464         {   "s21",      NULL,   4,  260,  eEncodingIEEE754,  eFormatFloat,   47,  { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM     }},
465         {   "s22",      NULL,   4,  264,  eEncodingIEEE754,  eFormatFloat,   48,  { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM     }},
466         {   "s23",      NULL,   4,  268,  eEncodingIEEE754,  eFormatFloat,   49,  { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM     }},
467         {   "s24",      NULL,   4,  272,  eEncodingIEEE754,  eFormatFloat,   50,  { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM     }},
468         {   "s25",      NULL,   4,  276,  eEncodingIEEE754,  eFormatFloat,   51,  { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM     }},
469         {   "s26",      NULL,   4,  280,  eEncodingIEEE754,  eFormatFloat,   52,  { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM     }},
470         {   "s27",      NULL,   4,  284,  eEncodingIEEE754,  eFormatFloat,   53,  { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM     }},
471         {   "s28",      NULL,   4,  288,  eEncodingIEEE754,  eFormatFloat,   54,  { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM     }},
472         {   "s29",      NULL,   4,  292,  eEncodingIEEE754,  eFormatFloat,   55,  { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM     }},
473         {   "s30",      NULL,   4,  296,  eEncodingIEEE754,  eFormatFloat,   56,  { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM     }},
474         {   "s31",      NULL,   4,  300,  eEncodingIEEE754,  eFormatFloat,   57,  { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM     }},
475         {   "fpscr",    NULL,   4,  304,  eEncodingUint,     eFormatHex,     58,  { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM     }},
476         {   "d16",      NULL,   8,  308,  eEncodingIEEE754,  eFormatFloat,   59,  { LLDB_INVALID_REGNUM,  dwarf_d16,          LLDB_INVALID_REGNUM     }},
477         {   "d17",      NULL,   8,  316,  eEncodingIEEE754,  eFormatFloat,   60,  { LLDB_INVALID_REGNUM,  dwarf_d17,          LLDB_INVALID_REGNUM     }},
478         {   "d18",      NULL,   8,  324,  eEncodingIEEE754,  eFormatFloat,   61,  { LLDB_INVALID_REGNUM,  dwarf_d18,          LLDB_INVALID_REGNUM     }},
479         {   "d19",      NULL,   8,  332,  eEncodingIEEE754,  eFormatFloat,   62,  { LLDB_INVALID_REGNUM,  dwarf_d19,          LLDB_INVALID_REGNUM     }},
480         {   "d20",      NULL,   8,  340,  eEncodingIEEE754,  eFormatFloat,   63,  { LLDB_INVALID_REGNUM,  dwarf_d20,          LLDB_INVALID_REGNUM     }},
481         {   "d21",      NULL,   8,  348,  eEncodingIEEE754,  eFormatFloat,   64,  { LLDB_INVALID_REGNUM,  dwarf_d21,          LLDB_INVALID_REGNUM     }},
482         {   "d22",      NULL,   8,  356,  eEncodingIEEE754,  eFormatFloat,   65,  { LLDB_INVALID_REGNUM,  dwarf_d22,          LLDB_INVALID_REGNUM     }},
483         {   "d23",      NULL,   8,  364,  eEncodingIEEE754,  eFormatFloat,   66,  { LLDB_INVALID_REGNUM,  dwarf_d23,          LLDB_INVALID_REGNUM     }},
484         {   "d24",      NULL,   8,  372,  eEncodingIEEE754,  eFormatFloat,   67,  { LLDB_INVALID_REGNUM,  dwarf_d24,          LLDB_INVALID_REGNUM     }},
485         {   "d25",      NULL,   8,  380,  eEncodingIEEE754,  eFormatFloat,   68,  { LLDB_INVALID_REGNUM,  dwarf_d25,          LLDB_INVALID_REGNUM     }},
486         {   "d26",      NULL,   8,  388,  eEncodingIEEE754,  eFormatFloat,   69,  { LLDB_INVALID_REGNUM,  dwarf_d26,          LLDB_INVALID_REGNUM     }},
487         {   "d27",      NULL,   8,  396,  eEncodingIEEE754,  eFormatFloat,   70,  { LLDB_INVALID_REGNUM,  dwarf_d27,          LLDB_INVALID_REGNUM     }},
488         {   "d28",      NULL,   8,  404,  eEncodingIEEE754,  eFormatFloat,   71,  { LLDB_INVALID_REGNUM,  dwarf_d28,          LLDB_INVALID_REGNUM     }},
489         {   "d29",      NULL,   8,  412,  eEncodingIEEE754,  eFormatFloat,   72,  { LLDB_INVALID_REGNUM,  dwarf_d29,          LLDB_INVALID_REGNUM     }},
490         {   "d30",      NULL,   8,  420,  eEncodingIEEE754,  eFormatFloat,   73,  { LLDB_INVALID_REGNUM,  dwarf_d30,          LLDB_INVALID_REGNUM     }},
491         {   "d31",      NULL,   8,  428,  eEncodingIEEE754,  eFormatFloat,   74,  { LLDB_INVALID_REGNUM,  dwarf_d31,          LLDB_INVALID_REGNUM     }},
492     };
493     static const uint32_t num_registers = sizeof (g_register_infos)/sizeof (lldb::RegisterInfo);
494     static ConstString gpr_reg_set ("General Purpose Registers");
495     static ConstString vfp_reg_set ("Floating Point Registers");
496     for (uint32_t i=0; i<num_registers; ++i)
497     {
498         ConstString name;
499         ConstString alt_name;
500         if (g_register_infos[i].name && g_register_infos[i].name[0])
501             name.SetCString(g_register_infos[i].name);
502         if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0])
503             alt_name.SetCString(g_register_infos[i].alt_name);
504 
505         AddRegister (g_register_infos[i], name, alt_name, i < 26 ? gpr_reg_set : vfp_reg_set);
506     }
507 }
508 
509