1//===----------------------------- Registers.hpp --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8//  Models register sets for supported processors.
9//
10//===----------------------------------------------------------------------===//
11
12#ifndef __REGISTERS_HPP__
13#define __REGISTERS_HPP__
14
15#include <stdint.h>
16#include <string.h>
17
18#include "libunwind.h"
19#include "config.h"
20
21namespace libunwind {
22
23// For emulating 128-bit registers
24struct v128 { uint32_t vec[4]; };
25
26enum {
27  REGISTERS_X86,
28  REGISTERS_X86_64,
29  REGISTERS_PPC,
30  REGISTERS_PPC64,
31  REGISTERS_ARM64,
32  REGISTERS_ARM,
33  REGISTERS_OR1K,
34  REGISTERS_MIPS_O32,
35  REGISTERS_MIPS_NEWABI,
36  REGISTERS_SPARC,
37};
38
39#if defined(_LIBUNWIND_TARGET_I386)
40/// Registers_x86 holds the register state of a thread in a 32-bit intel
41/// process.
42class _LIBUNWIND_HIDDEN Registers_x86 {
43public:
44  Registers_x86();
45  Registers_x86(const void *registers);
46
47  bool        validRegister(int num) const;
48  uint32_t    getRegister(int num) const;
49  void        setRegister(int num, uint32_t value);
50  bool        validFloatRegister(int) const { return false; }
51  double      getFloatRegister(int num) const;
52  void        setFloatRegister(int num, double value);
53  bool        validVectorRegister(int) const { return false; }
54  v128        getVectorRegister(int num) const;
55  void        setVectorRegister(int num, v128 value);
56  static const char *getRegisterName(int num);
57  void        jumpto();
58  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }
59  static int  getArch() { return REGISTERS_X86; }
60
61  uint32_t  getSP() const          { return _registers.__esp; }
62  void      setSP(uint32_t value)  { _registers.__esp = value; }
63  uint32_t  getIP() const          { return _registers.__eip; }
64  void      setIP(uint32_t value)  { _registers.__eip = value; }
65  uint32_t  getEBP() const         { return _registers.__ebp; }
66  void      setEBP(uint32_t value) { _registers.__ebp = value; }
67  uint32_t  getEBX() const         { return _registers.__ebx; }
68  void      setEBX(uint32_t value) { _registers.__ebx = value; }
69  uint32_t  getECX() const         { return _registers.__ecx; }
70  void      setECX(uint32_t value) { _registers.__ecx = value; }
71  uint32_t  getEDX() const         { return _registers.__edx; }
72  void      setEDX(uint32_t value) { _registers.__edx = value; }
73  uint32_t  getESI() const         { return _registers.__esi; }
74  void      setESI(uint32_t value) { _registers.__esi = value; }
75  uint32_t  getEDI() const         { return _registers.__edi; }
76  void      setEDI(uint32_t value) { _registers.__edi = value; }
77
78private:
79  struct GPRs {
80    unsigned int __eax;
81    unsigned int __ebx;
82    unsigned int __ecx;
83    unsigned int __edx;
84    unsigned int __edi;
85    unsigned int __esi;
86    unsigned int __ebp;
87    unsigned int __esp;
88    unsigned int __ss;
89    unsigned int __eflags;
90    unsigned int __eip;
91    unsigned int __cs;
92    unsigned int __ds;
93    unsigned int __es;
94    unsigned int __fs;
95    unsigned int __gs;
96  };
97
98  GPRs _registers;
99};
100
101inline Registers_x86::Registers_x86(const void *registers) {
102  static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
103                "x86 registers do not fit into unw_context_t");
104  memcpy(&_registers, registers, sizeof(_registers));
105}
106
107inline Registers_x86::Registers_x86() {
108  memset(&_registers, 0, sizeof(_registers));
109}
110
111inline bool Registers_x86::validRegister(int regNum) const {
112  if (regNum == UNW_REG_IP)
113    return true;
114  if (regNum == UNW_REG_SP)
115    return true;
116  if (regNum < 0)
117    return false;
118  if (regNum > 7)
119    return false;
120  return true;
121}
122
123inline uint32_t Registers_x86::getRegister(int regNum) const {
124  switch (regNum) {
125  case UNW_REG_IP:
126    return _registers.__eip;
127  case UNW_REG_SP:
128    return _registers.__esp;
129  case UNW_X86_EAX:
130    return _registers.__eax;
131  case UNW_X86_ECX:
132    return _registers.__ecx;
133  case UNW_X86_EDX:
134    return _registers.__edx;
135  case UNW_X86_EBX:
136    return _registers.__ebx;
137#if !defined(__APPLE__)
138  case UNW_X86_ESP:
139#else
140  case UNW_X86_EBP:
141#endif
142    return _registers.__ebp;
143#if !defined(__APPLE__)
144  case UNW_X86_EBP:
145#else
146  case UNW_X86_ESP:
147#endif
148    return _registers.__esp;
149  case UNW_X86_ESI:
150    return _registers.__esi;
151  case UNW_X86_EDI:
152    return _registers.__edi;
153  }
154  _LIBUNWIND_ABORT("unsupported x86 register");
155}
156
157inline void Registers_x86::setRegister(int regNum, uint32_t value) {
158  switch (regNum) {
159  case UNW_REG_IP:
160    _registers.__eip = value;
161    return;
162  case UNW_REG_SP:
163    _registers.__esp = value;
164    return;
165  case UNW_X86_EAX:
166    _registers.__eax = value;
167    return;
168  case UNW_X86_ECX:
169    _registers.__ecx = value;
170    return;
171  case UNW_X86_EDX:
172    _registers.__edx = value;
173    return;
174  case UNW_X86_EBX:
175    _registers.__ebx = value;
176    return;
177#if !defined(__APPLE__)
178  case UNW_X86_ESP:
179#else
180  case UNW_X86_EBP:
181#endif
182    _registers.__ebp = value;
183    return;
184#if !defined(__APPLE__)
185  case UNW_X86_EBP:
186#else
187  case UNW_X86_ESP:
188#endif
189    _registers.__esp = value;
190    return;
191  case UNW_X86_ESI:
192    _registers.__esi = value;
193    return;
194  case UNW_X86_EDI:
195    _registers.__edi = value;
196    return;
197  }
198  _LIBUNWIND_ABORT("unsupported x86 register");
199}
200
201inline const char *Registers_x86::getRegisterName(int regNum) {
202  switch (regNum) {
203  case UNW_REG_IP:
204    return "ip";
205  case UNW_REG_SP:
206    return "esp";
207  case UNW_X86_EAX:
208    return "eax";
209  case UNW_X86_ECX:
210    return "ecx";
211  case UNW_X86_EDX:
212    return "edx";
213  case UNW_X86_EBX:
214    return "ebx";
215  case UNW_X86_EBP:
216    return "ebp";
217  case UNW_X86_ESP:
218    return "esp";
219  case UNW_X86_ESI:
220    return "esi";
221  case UNW_X86_EDI:
222    return "edi";
223  default:
224    return "unknown register";
225  }
226}
227
228inline double Registers_x86::getFloatRegister(int) const {
229  _LIBUNWIND_ABORT("no x86 float registers");
230}
231
232inline void Registers_x86::setFloatRegister(int, double) {
233  _LIBUNWIND_ABORT("no x86 float registers");
234}
235
236inline v128 Registers_x86::getVectorRegister(int) const {
237  _LIBUNWIND_ABORT("no x86 vector registers");
238}
239
240inline void Registers_x86::setVectorRegister(int, v128) {
241  _LIBUNWIND_ABORT("no x86 vector registers");
242}
243#endif // _LIBUNWIND_TARGET_I386
244
245
246#if defined(_LIBUNWIND_TARGET_X86_64)
247/// Registers_x86_64  holds the register state of a thread in a 64-bit intel
248/// process.
249class _LIBUNWIND_HIDDEN Registers_x86_64 {
250public:
251  Registers_x86_64();
252  Registers_x86_64(const void *registers);
253
254  bool        validRegister(int num) const;
255  uint64_t    getRegister(int num) const;
256  void        setRegister(int num, uint64_t value);
257  bool        validFloatRegister(int) const { return false; }
258  double      getFloatRegister(int num) const;
259  void        setFloatRegister(int num, double value);
260  bool        validVectorRegister(int) const;
261  v128        getVectorRegister(int num) const;
262  void        setVectorRegister(int num, v128 value);
263  static const char *getRegisterName(int num);
264  void        jumpto();
265  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }
266  static int  getArch() { return REGISTERS_X86_64; }
267
268  uint64_t  getSP() const          { return _registers.__rsp; }
269  void      setSP(uint64_t value)  { _registers.__rsp = value; }
270  uint64_t  getIP() const          { return _registers.__rip; }
271  void      setIP(uint64_t value)  { _registers.__rip = value; }
272  uint64_t  getRBP() const         { return _registers.__rbp; }
273  void      setRBP(uint64_t value) { _registers.__rbp = value; }
274  uint64_t  getRBX() const         { return _registers.__rbx; }
275  void      setRBX(uint64_t value) { _registers.__rbx = value; }
276  uint64_t  getR12() const         { return _registers.__r12; }
277  void      setR12(uint64_t value) { _registers.__r12 = value; }
278  uint64_t  getR13() const         { return _registers.__r13; }
279  void      setR13(uint64_t value) { _registers.__r13 = value; }
280  uint64_t  getR14() const         { return _registers.__r14; }
281  void      setR14(uint64_t value) { _registers.__r14 = value; }
282  uint64_t  getR15() const         { return _registers.__r15; }
283  void      setR15(uint64_t value) { _registers.__r15 = value; }
284
285private:
286  struct GPRs {
287    uint64_t __rax;
288    uint64_t __rbx;
289    uint64_t __rcx;
290    uint64_t __rdx;
291    uint64_t __rdi;
292    uint64_t __rsi;
293    uint64_t __rbp;
294    uint64_t __rsp;
295    uint64_t __r8;
296    uint64_t __r9;
297    uint64_t __r10;
298    uint64_t __r11;
299    uint64_t __r12;
300    uint64_t __r13;
301    uint64_t __r14;
302    uint64_t __r15;
303    uint64_t __rip;
304    uint64_t __rflags;
305    uint64_t __cs;
306    uint64_t __fs;
307    uint64_t __gs;
308#if defined(_WIN64)
309    uint64_t __padding; // 16-byte align
310#endif
311  };
312  GPRs _registers;
313#if defined(_WIN64)
314  v128 _xmm[16];
315#endif
316};
317
318inline Registers_x86_64::Registers_x86_64(const void *registers) {
319  static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
320                "x86_64 registers do not fit into unw_context_t");
321  memcpy(&_registers, registers, sizeof(_registers));
322}
323
324inline Registers_x86_64::Registers_x86_64() {
325  memset(&_registers, 0, sizeof(_registers));
326}
327
328inline bool Registers_x86_64::validRegister(int regNum) const {
329  if (regNum == UNW_REG_IP)
330    return true;
331  if (regNum == UNW_REG_SP)
332    return true;
333  if (regNum < 0)
334    return false;
335  if (regNum > 15)
336    return false;
337  return true;
338}
339
340inline uint64_t Registers_x86_64::getRegister(int regNum) const {
341  switch (regNum) {
342  case UNW_REG_IP:
343    return _registers.__rip;
344  case UNW_REG_SP:
345    return _registers.__rsp;
346  case UNW_X86_64_RAX:
347    return _registers.__rax;
348  case UNW_X86_64_RDX:
349    return _registers.__rdx;
350  case UNW_X86_64_RCX:
351    return _registers.__rcx;
352  case UNW_X86_64_RBX:
353    return _registers.__rbx;
354  case UNW_X86_64_RSI:
355    return _registers.__rsi;
356  case UNW_X86_64_RDI:
357    return _registers.__rdi;
358  case UNW_X86_64_RBP:
359    return _registers.__rbp;
360  case UNW_X86_64_RSP:
361    return _registers.__rsp;
362  case UNW_X86_64_R8:
363    return _registers.__r8;
364  case UNW_X86_64_R9:
365    return _registers.__r9;
366  case UNW_X86_64_R10:
367    return _registers.__r10;
368  case UNW_X86_64_R11:
369    return _registers.__r11;
370  case UNW_X86_64_R12:
371    return _registers.__r12;
372  case UNW_X86_64_R13:
373    return _registers.__r13;
374  case UNW_X86_64_R14:
375    return _registers.__r14;
376  case UNW_X86_64_R15:
377    return _registers.__r15;
378  }
379  _LIBUNWIND_ABORT("unsupported x86_64 register");
380}
381
382inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
383  switch (regNum) {
384  case UNW_REG_IP:
385    _registers.__rip = value;
386    return;
387  case UNW_REG_SP:
388    _registers.__rsp = value;
389    return;
390  case UNW_X86_64_RAX:
391    _registers.__rax = value;
392    return;
393  case UNW_X86_64_RDX:
394    _registers.__rdx = value;
395    return;
396  case UNW_X86_64_RCX:
397    _registers.__rcx = value;
398    return;
399  case UNW_X86_64_RBX:
400    _registers.__rbx = value;
401    return;
402  case UNW_X86_64_RSI:
403    _registers.__rsi = value;
404    return;
405  case UNW_X86_64_RDI:
406    _registers.__rdi = value;
407    return;
408  case UNW_X86_64_RBP:
409    _registers.__rbp = value;
410    return;
411  case UNW_X86_64_RSP:
412    _registers.__rsp = value;
413    return;
414  case UNW_X86_64_R8:
415    _registers.__r8 = value;
416    return;
417  case UNW_X86_64_R9:
418    _registers.__r9 = value;
419    return;
420  case UNW_X86_64_R10:
421    _registers.__r10 = value;
422    return;
423  case UNW_X86_64_R11:
424    _registers.__r11 = value;
425    return;
426  case UNW_X86_64_R12:
427    _registers.__r12 = value;
428    return;
429  case UNW_X86_64_R13:
430    _registers.__r13 = value;
431    return;
432  case UNW_X86_64_R14:
433    _registers.__r14 = value;
434    return;
435  case UNW_X86_64_R15:
436    _registers.__r15 = value;
437    return;
438  }
439  _LIBUNWIND_ABORT("unsupported x86_64 register");
440}
441
442inline const char *Registers_x86_64::getRegisterName(int regNum) {
443  switch (regNum) {
444  case UNW_REG_IP:
445    return "rip";
446  case UNW_REG_SP:
447    return "rsp";
448  case UNW_X86_64_RAX:
449    return "rax";
450  case UNW_X86_64_RDX:
451    return "rdx";
452  case UNW_X86_64_RCX:
453    return "rcx";
454  case UNW_X86_64_RBX:
455    return "rbx";
456  case UNW_X86_64_RSI:
457    return "rsi";
458  case UNW_X86_64_RDI:
459    return "rdi";
460  case UNW_X86_64_RBP:
461    return "rbp";
462  case UNW_X86_64_RSP:
463    return "rsp";
464  case UNW_X86_64_R8:
465    return "r8";
466  case UNW_X86_64_R9:
467    return "r9";
468  case UNW_X86_64_R10:
469    return "r10";
470  case UNW_X86_64_R11:
471    return "r11";
472  case UNW_X86_64_R12:
473    return "r12";
474  case UNW_X86_64_R13:
475    return "r13";
476  case UNW_X86_64_R14:
477    return "r14";
478  case UNW_X86_64_R15:
479    return "r15";
480  case UNW_X86_64_XMM0:
481    return "xmm0";
482  case UNW_X86_64_XMM1:
483    return "xmm1";
484  case UNW_X86_64_XMM2:
485    return "xmm2";
486  case UNW_X86_64_XMM3:
487    return "xmm3";
488  case UNW_X86_64_XMM4:
489    return "xmm4";
490  case UNW_X86_64_XMM5:
491    return "xmm5";
492  case UNW_X86_64_XMM6:
493    return "xmm6";
494  case UNW_X86_64_XMM7:
495    return "xmm7";
496  case UNW_X86_64_XMM8:
497    return "xmm8";
498  case UNW_X86_64_XMM9:
499    return "xmm9";
500  case UNW_X86_64_XMM10:
501    return "xmm10";
502  case UNW_X86_64_XMM11:
503    return "xmm11";
504  case UNW_X86_64_XMM12:
505    return "xmm12";
506  case UNW_X86_64_XMM13:
507    return "xmm13";
508  case UNW_X86_64_XMM14:
509    return "xmm14";
510  case UNW_X86_64_XMM15:
511    return "xmm15";
512  default:
513    return "unknown register";
514  }
515}
516
517inline double Registers_x86_64::getFloatRegister(int) const {
518  _LIBUNWIND_ABORT("no x86_64 float registers");
519}
520
521inline void Registers_x86_64::setFloatRegister(int, double) {
522  _LIBUNWIND_ABORT("no x86_64 float registers");
523}
524
525inline bool Registers_x86_64::validVectorRegister(int regNum) const {
526#if defined(_WIN64)
527  if (regNum < UNW_X86_64_XMM0)
528    return false;
529  if (regNum > UNW_X86_64_XMM15)
530    return false;
531  return true;
532#else
533  (void)regNum; // suppress unused parameter warning
534  return false;
535#endif
536}
537
538inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
539#if defined(_WIN64)
540  assert(validVectorRegister(regNum));
541  return _xmm[regNum - UNW_X86_64_XMM0];
542#else
543  (void)regNum; // suppress unused parameter warning
544  _LIBUNWIND_ABORT("no x86_64 vector registers");
545#endif
546}
547
548inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
549#if defined(_WIN64)
550  assert(validVectorRegister(regNum));
551  _xmm[regNum - UNW_X86_64_XMM0] = value;
552#else
553  (void)regNum; (void)value; // suppress unused parameter warnings
554  _LIBUNWIND_ABORT("no x86_64 vector registers");
555#endif
556}
557#endif // _LIBUNWIND_TARGET_X86_64
558
559
560#if defined(_LIBUNWIND_TARGET_PPC)
561/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
562/// process.
563class _LIBUNWIND_HIDDEN Registers_ppc {
564public:
565  Registers_ppc();
566  Registers_ppc(const void *registers);
567
568  bool        validRegister(int num) const;
569  uint32_t    getRegister(int num) const;
570  void        setRegister(int num, uint32_t value);
571  bool        validFloatRegister(int num) const;
572  double      getFloatRegister(int num) const;
573  void        setFloatRegister(int num, double value);
574  bool        validVectorRegister(int num) const;
575  v128        getVectorRegister(int num) const;
576  void        setVectorRegister(int num, v128 value);
577  static const char *getRegisterName(int num);
578  void        jumpto();
579  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; }
580  static int  getArch() { return REGISTERS_PPC; }
581
582  uint64_t  getSP() const         { return _registers.__r1; }
583  void      setSP(uint32_t value) { _registers.__r1 = value; }
584  uint64_t  getIP() const         { return _registers.__srr0; }
585  void      setIP(uint32_t value) { _registers.__srr0 = value; }
586
587private:
588  struct ppc_thread_state_t {
589    unsigned int __srr0; /* Instruction address register (PC) */
590    unsigned int __srr1; /* Machine state register (supervisor) */
591    unsigned int __r0;
592    unsigned int __r1;
593    unsigned int __r2;
594    unsigned int __r3;
595    unsigned int __r4;
596    unsigned int __r5;
597    unsigned int __r6;
598    unsigned int __r7;
599    unsigned int __r8;
600    unsigned int __r9;
601    unsigned int __r10;
602    unsigned int __r11;
603    unsigned int __r12;
604    unsigned int __r13;
605    unsigned int __r14;
606    unsigned int __r15;
607    unsigned int __r16;
608    unsigned int __r17;
609    unsigned int __r18;
610    unsigned int __r19;
611    unsigned int __r20;
612    unsigned int __r21;
613    unsigned int __r22;
614    unsigned int __r23;
615    unsigned int __r24;
616    unsigned int __r25;
617    unsigned int __r26;
618    unsigned int __r27;
619    unsigned int __r28;
620    unsigned int __r29;
621    unsigned int __r30;
622    unsigned int __r31;
623    unsigned int __cr;     /* Condition register */
624    unsigned int __xer;    /* User's integer exception register */
625    unsigned int __lr;     /* Link register */
626    unsigned int __ctr;    /* Count register */
627    unsigned int __mq;     /* MQ register (601 only) */
628    unsigned int __vrsave; /* Vector Save Register */
629  };
630
631  struct ppc_float_state_t {
632    double __fpregs[32];
633
634    unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
635    unsigned int __fpscr;     /* floating point status register */
636  };
637
638  ppc_thread_state_t _registers;
639  ppc_float_state_t  _floatRegisters;
640  v128               _vectorRegisters[32]; // offset 424
641};
642
643inline Registers_ppc::Registers_ppc(const void *registers) {
644  static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
645                "ppc registers do not fit into unw_context_t");
646  memcpy(&_registers, static_cast<const uint8_t *>(registers),
647         sizeof(_registers));
648  static_assert(sizeof(ppc_thread_state_t) == 160,
649                "expected float register offset to be 160");
650  memcpy(&_floatRegisters,
651         static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
652         sizeof(_floatRegisters));
653  static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
654                "expected vector register offset to be 424 bytes");
655  memcpy(_vectorRegisters,
656         static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
657             sizeof(ppc_float_state_t),
658         sizeof(_vectorRegisters));
659}
660
661inline Registers_ppc::Registers_ppc() {
662  memset(&_registers, 0, sizeof(_registers));
663  memset(&_floatRegisters, 0, sizeof(_floatRegisters));
664  memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
665}
666
667inline bool Registers_ppc::validRegister(int regNum) const {
668  if (regNum == UNW_REG_IP)
669    return true;
670  if (regNum == UNW_REG_SP)
671    return true;
672  if (regNum == UNW_PPC_VRSAVE)
673    return true;
674  if (regNum < 0)
675    return false;
676  if (regNum <= UNW_PPC_R31)
677    return true;
678  if (regNum == UNW_PPC_MQ)
679    return true;
680  if (regNum == UNW_PPC_LR)
681    return true;
682  if (regNum == UNW_PPC_CTR)
683    return true;
684  if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
685    return true;
686  return false;
687}
688
689inline uint32_t Registers_ppc::getRegister(int regNum) const {
690  switch (regNum) {
691  case UNW_REG_IP:
692    return _registers.__srr0;
693  case UNW_REG_SP:
694    return _registers.__r1;
695  case UNW_PPC_R0:
696    return _registers.__r0;
697  case UNW_PPC_R1:
698    return _registers.__r1;
699  case UNW_PPC_R2:
700    return _registers.__r2;
701  case UNW_PPC_R3:
702    return _registers.__r3;
703  case UNW_PPC_R4:
704    return _registers.__r4;
705  case UNW_PPC_R5:
706    return _registers.__r5;
707  case UNW_PPC_R6:
708    return _registers.__r6;
709  case UNW_PPC_R7:
710    return _registers.__r7;
711  case UNW_PPC_R8:
712    return _registers.__r8;
713  case UNW_PPC_R9:
714    return _registers.__r9;
715  case UNW_PPC_R10:
716    return _registers.__r10;
717  case UNW_PPC_R11:
718    return _registers.__r11;
719  case UNW_PPC_R12:
720    return _registers.__r12;
721  case UNW_PPC_R13:
722    return _registers.__r13;
723  case UNW_PPC_R14:
724    return _registers.__r14;
725  case UNW_PPC_R15:
726    return _registers.__r15;
727  case UNW_PPC_R16:
728    return _registers.__r16;
729  case UNW_PPC_R17:
730    return _registers.__r17;
731  case UNW_PPC_R18:
732    return _registers.__r18;
733  case UNW_PPC_R19:
734    return _registers.__r19;
735  case UNW_PPC_R20:
736    return _registers.__r20;
737  case UNW_PPC_R21:
738    return _registers.__r21;
739  case UNW_PPC_R22:
740    return _registers.__r22;
741  case UNW_PPC_R23:
742    return _registers.__r23;
743  case UNW_PPC_R24:
744    return _registers.__r24;
745  case UNW_PPC_R25:
746    return _registers.__r25;
747  case UNW_PPC_R26:
748    return _registers.__r26;
749  case UNW_PPC_R27:
750    return _registers.__r27;
751  case UNW_PPC_R28:
752    return _registers.__r28;
753  case UNW_PPC_R29:
754    return _registers.__r29;
755  case UNW_PPC_R30:
756    return _registers.__r30;
757  case UNW_PPC_R31:
758    return _registers.__r31;
759  case UNW_PPC_LR:
760    return _registers.__lr;
761  case UNW_PPC_CR0:
762    return (_registers.__cr & 0xF0000000);
763  case UNW_PPC_CR1:
764    return (_registers.__cr & 0x0F000000);
765  case UNW_PPC_CR2:
766    return (_registers.__cr & 0x00F00000);
767  case UNW_PPC_CR3:
768    return (_registers.__cr & 0x000F0000);
769  case UNW_PPC_CR4:
770    return (_registers.__cr & 0x0000F000);
771  case UNW_PPC_CR5:
772    return (_registers.__cr & 0x00000F00);
773  case UNW_PPC_CR6:
774    return (_registers.__cr & 0x000000F0);
775  case UNW_PPC_CR7:
776    return (_registers.__cr & 0x0000000F);
777  case UNW_PPC_VRSAVE:
778    return _registers.__vrsave;
779  }
780  _LIBUNWIND_ABORT("unsupported ppc register");
781}
782
783inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
784  //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
785  switch (regNum) {
786  case UNW_REG_IP:
787    _registers.__srr0 = value;
788    return;
789  case UNW_REG_SP:
790    _registers.__r1 = value;
791    return;
792  case UNW_PPC_R0:
793    _registers.__r0 = value;
794    return;
795  case UNW_PPC_R1:
796    _registers.__r1 = value;
797    return;
798  case UNW_PPC_R2:
799    _registers.__r2 = value;
800    return;
801  case UNW_PPC_R3:
802    _registers.__r3 = value;
803    return;
804  case UNW_PPC_R4:
805    _registers.__r4 = value;
806    return;
807  case UNW_PPC_R5:
808    _registers.__r5 = value;
809    return;
810  case UNW_PPC_R6:
811    _registers.__r6 = value;
812    return;
813  case UNW_PPC_R7:
814    _registers.__r7 = value;
815    return;
816  case UNW_PPC_R8:
817    _registers.__r8 = value;
818    return;
819  case UNW_PPC_R9:
820    _registers.__r9 = value;
821    return;
822  case UNW_PPC_R10:
823    _registers.__r10 = value;
824    return;
825  case UNW_PPC_R11:
826    _registers.__r11 = value;
827    return;
828  case UNW_PPC_R12:
829    _registers.__r12 = value;
830    return;
831  case UNW_PPC_R13:
832    _registers.__r13 = value;
833    return;
834  case UNW_PPC_R14:
835    _registers.__r14 = value;
836    return;
837  case UNW_PPC_R15:
838    _registers.__r15 = value;
839    return;
840  case UNW_PPC_R16:
841    _registers.__r16 = value;
842    return;
843  case UNW_PPC_R17:
844    _registers.__r17 = value;
845    return;
846  case UNW_PPC_R18:
847    _registers.__r18 = value;
848    return;
849  case UNW_PPC_R19:
850    _registers.__r19 = value;
851    return;
852  case UNW_PPC_R20:
853    _registers.__r20 = value;
854    return;
855  case UNW_PPC_R21:
856    _registers.__r21 = value;
857    return;
858  case UNW_PPC_R22:
859    _registers.__r22 = value;
860    return;
861  case UNW_PPC_R23:
862    _registers.__r23 = value;
863    return;
864  case UNW_PPC_R24:
865    _registers.__r24 = value;
866    return;
867  case UNW_PPC_R25:
868    _registers.__r25 = value;
869    return;
870  case UNW_PPC_R26:
871    _registers.__r26 = value;
872    return;
873  case UNW_PPC_R27:
874    _registers.__r27 = value;
875    return;
876  case UNW_PPC_R28:
877    _registers.__r28 = value;
878    return;
879  case UNW_PPC_R29:
880    _registers.__r29 = value;
881    return;
882  case UNW_PPC_R30:
883    _registers.__r30 = value;
884    return;
885  case UNW_PPC_R31:
886    _registers.__r31 = value;
887    return;
888  case UNW_PPC_MQ:
889    _registers.__mq = value;
890    return;
891  case UNW_PPC_LR:
892    _registers.__lr = value;
893    return;
894  case UNW_PPC_CTR:
895    _registers.__ctr = value;
896    return;
897  case UNW_PPC_CR0:
898    _registers.__cr &= 0x0FFFFFFF;
899    _registers.__cr |= (value & 0xF0000000);
900    return;
901  case UNW_PPC_CR1:
902    _registers.__cr &= 0xF0FFFFFF;
903    _registers.__cr |= (value & 0x0F000000);
904    return;
905  case UNW_PPC_CR2:
906    _registers.__cr &= 0xFF0FFFFF;
907    _registers.__cr |= (value & 0x00F00000);
908    return;
909  case UNW_PPC_CR3:
910    _registers.__cr &= 0xFFF0FFFF;
911    _registers.__cr |= (value & 0x000F0000);
912    return;
913  case UNW_PPC_CR4:
914    _registers.__cr &= 0xFFFF0FFF;
915    _registers.__cr |= (value & 0x0000F000);
916    return;
917  case UNW_PPC_CR5:
918    _registers.__cr &= 0xFFFFF0FF;
919    _registers.__cr |= (value & 0x00000F00);
920    return;
921  case UNW_PPC_CR6:
922    _registers.__cr &= 0xFFFFFF0F;
923    _registers.__cr |= (value & 0x000000F0);
924    return;
925  case UNW_PPC_CR7:
926    _registers.__cr &= 0xFFFFFFF0;
927    _registers.__cr |= (value & 0x0000000F);
928    return;
929  case UNW_PPC_VRSAVE:
930    _registers.__vrsave = value;
931    return;
932    // not saved
933    return;
934  case UNW_PPC_XER:
935    _registers.__xer = value;
936    return;
937  case UNW_PPC_AP:
938  case UNW_PPC_VSCR:
939  case UNW_PPC_SPEFSCR:
940    // not saved
941    return;
942  }
943  _LIBUNWIND_ABORT("unsupported ppc register");
944}
945
946inline bool Registers_ppc::validFloatRegister(int regNum) const {
947  if (regNum < UNW_PPC_F0)
948    return false;
949  if (regNum > UNW_PPC_F31)
950    return false;
951  return true;
952}
953
954inline double Registers_ppc::getFloatRegister(int regNum) const {
955  assert(validFloatRegister(regNum));
956  return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
957}
958
959inline void Registers_ppc::setFloatRegister(int regNum, double value) {
960  assert(validFloatRegister(regNum));
961  _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
962}
963
964inline bool Registers_ppc::validVectorRegister(int regNum) const {
965  if (regNum < UNW_PPC_V0)
966    return false;
967  if (regNum > UNW_PPC_V31)
968    return false;
969  return true;
970}
971
972inline v128 Registers_ppc::getVectorRegister(int regNum) const {
973  assert(validVectorRegister(regNum));
974  v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
975  return result;
976}
977
978inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
979  assert(validVectorRegister(regNum));
980  _vectorRegisters[regNum - UNW_PPC_V0] = value;
981}
982
983inline const char *Registers_ppc::getRegisterName(int regNum) {
984  switch (regNum) {
985  case UNW_REG_IP:
986    return "ip";
987  case UNW_REG_SP:
988    return "sp";
989  case UNW_PPC_R0:
990    return "r0";
991  case UNW_PPC_R1:
992    return "r1";
993  case UNW_PPC_R2:
994    return "r2";
995  case UNW_PPC_R3:
996    return "r3";
997  case UNW_PPC_R4:
998    return "r4";
999  case UNW_PPC_R5:
1000    return "r5";
1001  case UNW_PPC_R6:
1002    return "r6";
1003  case UNW_PPC_R7:
1004    return "r7";
1005  case UNW_PPC_R8:
1006    return "r8";
1007  case UNW_PPC_R9:
1008    return "r9";
1009  case UNW_PPC_R10:
1010    return "r10";
1011  case UNW_PPC_R11:
1012    return "r11";
1013  case UNW_PPC_R12:
1014    return "r12";
1015  case UNW_PPC_R13:
1016    return "r13";
1017  case UNW_PPC_R14:
1018    return "r14";
1019  case UNW_PPC_R15:
1020    return "r15";
1021  case UNW_PPC_R16:
1022    return "r16";
1023  case UNW_PPC_R17:
1024    return "r17";
1025  case UNW_PPC_R18:
1026    return "r18";
1027  case UNW_PPC_R19:
1028    return "r19";
1029  case UNW_PPC_R20:
1030    return "r20";
1031  case UNW_PPC_R21:
1032    return "r21";
1033  case UNW_PPC_R22:
1034    return "r22";
1035  case UNW_PPC_R23:
1036    return "r23";
1037  case UNW_PPC_R24:
1038    return "r24";
1039  case UNW_PPC_R25:
1040    return "r25";
1041  case UNW_PPC_R26:
1042    return "r26";
1043  case UNW_PPC_R27:
1044    return "r27";
1045  case UNW_PPC_R28:
1046    return "r28";
1047  case UNW_PPC_R29:
1048    return "r29";
1049  case UNW_PPC_R30:
1050    return "r30";
1051  case UNW_PPC_R31:
1052    return "r31";
1053  case UNW_PPC_F0:
1054    return "fp0";
1055  case UNW_PPC_F1:
1056    return "fp1";
1057  case UNW_PPC_F2:
1058    return "fp2";
1059  case UNW_PPC_F3:
1060    return "fp3";
1061  case UNW_PPC_F4:
1062    return "fp4";
1063  case UNW_PPC_F5:
1064    return "fp5";
1065  case UNW_PPC_F6:
1066    return "fp6";
1067  case UNW_PPC_F7:
1068    return "fp7";
1069  case UNW_PPC_F8:
1070    return "fp8";
1071  case UNW_PPC_F9:
1072    return "fp9";
1073  case UNW_PPC_F10:
1074    return "fp10";
1075  case UNW_PPC_F11:
1076    return "fp11";
1077  case UNW_PPC_F12:
1078    return "fp12";
1079  case UNW_PPC_F13:
1080    return "fp13";
1081  case UNW_PPC_F14:
1082    return "fp14";
1083  case UNW_PPC_F15:
1084    return "fp15";
1085  case UNW_PPC_F16:
1086    return "fp16";
1087  case UNW_PPC_F17:
1088    return "fp17";
1089  case UNW_PPC_F18:
1090    return "fp18";
1091  case UNW_PPC_F19:
1092    return "fp19";
1093  case UNW_PPC_F20:
1094    return "fp20";
1095  case UNW_PPC_F21:
1096    return "fp21";
1097  case UNW_PPC_F22:
1098    return "fp22";
1099  case UNW_PPC_F23:
1100    return "fp23";
1101  case UNW_PPC_F24:
1102    return "fp24";
1103  case UNW_PPC_F25:
1104    return "fp25";
1105  case UNW_PPC_F26:
1106    return "fp26";
1107  case UNW_PPC_F27:
1108    return "fp27";
1109  case UNW_PPC_F28:
1110    return "fp28";
1111  case UNW_PPC_F29:
1112    return "fp29";
1113  case UNW_PPC_F30:
1114    return "fp30";
1115  case UNW_PPC_F31:
1116    return "fp31";
1117  case UNW_PPC_LR:
1118    return "lr";
1119  default:
1120    return "unknown register";
1121  }
1122
1123}
1124#endif // _LIBUNWIND_TARGET_PPC
1125
1126#if defined(_LIBUNWIND_TARGET_PPC64)
1127/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
1128/// process.
1129class _LIBUNWIND_HIDDEN Registers_ppc64 {
1130public:
1131  Registers_ppc64();
1132  Registers_ppc64(const void *registers);
1133
1134  bool        validRegister(int num) const;
1135  uint64_t    getRegister(int num) const;
1136  void        setRegister(int num, uint64_t value);
1137  bool        validFloatRegister(int num) const;
1138  double      getFloatRegister(int num) const;
1139  void        setFloatRegister(int num, double value);
1140  bool        validVectorRegister(int num) const;
1141  v128        getVectorRegister(int num) const;
1142  void        setVectorRegister(int num, v128 value);
1143  static const char *getRegisterName(int num);
1144  void        jumpto();
1145  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; }
1146  static int  getArch() { return REGISTERS_PPC64; }
1147
1148  uint64_t  getSP() const         { return _registers.__r1; }
1149  void      setSP(uint64_t value) { _registers.__r1 = value; }
1150  uint64_t  getIP() const         { return _registers.__srr0; }
1151  void      setIP(uint64_t value) { _registers.__srr0 = value; }
1152
1153private:
1154  struct ppc64_thread_state_t {
1155    uint64_t __srr0;    // Instruction address register (PC)
1156    uint64_t __srr1;    // Machine state register (supervisor)
1157    uint64_t __r0;
1158    uint64_t __r1;
1159    uint64_t __r2;
1160    uint64_t __r3;
1161    uint64_t __r4;
1162    uint64_t __r5;
1163    uint64_t __r6;
1164    uint64_t __r7;
1165    uint64_t __r8;
1166    uint64_t __r9;
1167    uint64_t __r10;
1168    uint64_t __r11;
1169    uint64_t __r12;
1170    uint64_t __r13;
1171    uint64_t __r14;
1172    uint64_t __r15;
1173    uint64_t __r16;
1174    uint64_t __r17;
1175    uint64_t __r18;
1176    uint64_t __r19;
1177    uint64_t __r20;
1178    uint64_t __r21;
1179    uint64_t __r22;
1180    uint64_t __r23;
1181    uint64_t __r24;
1182    uint64_t __r25;
1183    uint64_t __r26;
1184    uint64_t __r27;
1185    uint64_t __r28;
1186    uint64_t __r29;
1187    uint64_t __r30;
1188    uint64_t __r31;
1189    uint64_t __cr;      // Condition register
1190    uint64_t __xer;     // User's integer exception register
1191    uint64_t __lr;      // Link register
1192    uint64_t __ctr;     // Count register
1193    uint64_t __vrsave;  // Vector Save Register
1194  };
1195
1196  union ppc64_vsr_t {
1197    struct asfloat_s {
1198      double f;
1199      uint64_t v2;
1200    } asfloat;
1201    v128 v;
1202  };
1203
1204  ppc64_thread_state_t _registers;
1205  ppc64_vsr_t          _vectorScalarRegisters[64];
1206
1207  static int getVectorRegNum(int num);
1208};
1209
1210inline Registers_ppc64::Registers_ppc64(const void *registers) {
1211  static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),
1212                "ppc64 registers do not fit into unw_context_t");
1213  memcpy(&_registers, static_cast<const uint8_t *>(registers),
1214         sizeof(_registers));
1215  static_assert(sizeof(_registers) == 312,
1216                "expected vector scalar register offset to be 312");
1217  memcpy(&_vectorScalarRegisters,
1218         static_cast<const uint8_t *>(registers) + sizeof(_registers),
1219         sizeof(_vectorScalarRegisters));
1220  static_assert(sizeof(_registers) +
1221                sizeof(_vectorScalarRegisters) == 1336,
1222                "expected vector register offset to be 1336 bytes");
1223}
1224
1225inline Registers_ppc64::Registers_ppc64() {
1226  memset(&_registers, 0, sizeof(_registers));
1227  memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
1228}
1229
1230inline bool Registers_ppc64::validRegister(int regNum) const {
1231  switch (regNum) {
1232  case UNW_REG_IP:
1233  case UNW_REG_SP:
1234  case UNW_PPC64_XER:
1235  case UNW_PPC64_LR:
1236  case UNW_PPC64_CTR:
1237  case UNW_PPC64_VRSAVE:
1238      return true;
1239  }
1240
1241  if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
1242    return true;
1243  if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
1244    return true;
1245
1246  return false;
1247}
1248
1249inline uint64_t Registers_ppc64::getRegister(int regNum) const {
1250  switch (regNum) {
1251  case UNW_REG_IP:
1252    return _registers.__srr0;
1253  case UNW_PPC64_R0:
1254    return _registers.__r0;
1255  case UNW_PPC64_R1:
1256  case UNW_REG_SP:
1257    return _registers.__r1;
1258  case UNW_PPC64_R2:
1259    return _registers.__r2;
1260  case UNW_PPC64_R3:
1261    return _registers.__r3;
1262  case UNW_PPC64_R4:
1263    return _registers.__r4;
1264  case UNW_PPC64_R5:
1265    return _registers.__r5;
1266  case UNW_PPC64_R6:
1267    return _registers.__r6;
1268  case UNW_PPC64_R7:
1269    return _registers.__r7;
1270  case UNW_PPC64_R8:
1271    return _registers.__r8;
1272  case UNW_PPC64_R9:
1273    return _registers.__r9;
1274  case UNW_PPC64_R10:
1275    return _registers.__r10;
1276  case UNW_PPC64_R11:
1277    return _registers.__r11;
1278  case UNW_PPC64_R12:
1279    return _registers.__r12;
1280  case UNW_PPC64_R13:
1281    return _registers.__r13;
1282  case UNW_PPC64_R14:
1283    return _registers.__r14;
1284  case UNW_PPC64_R15:
1285    return _registers.__r15;
1286  case UNW_PPC64_R16:
1287    return _registers.__r16;
1288  case UNW_PPC64_R17:
1289    return _registers.__r17;
1290  case UNW_PPC64_R18:
1291    return _registers.__r18;
1292  case UNW_PPC64_R19:
1293    return _registers.__r19;
1294  case UNW_PPC64_R20:
1295    return _registers.__r20;
1296  case UNW_PPC64_R21:
1297    return _registers.__r21;
1298  case UNW_PPC64_R22:
1299    return _registers.__r22;
1300  case UNW_PPC64_R23:
1301    return _registers.__r23;
1302  case UNW_PPC64_R24:
1303    return _registers.__r24;
1304  case UNW_PPC64_R25:
1305    return _registers.__r25;
1306  case UNW_PPC64_R26:
1307    return _registers.__r26;
1308  case UNW_PPC64_R27:
1309    return _registers.__r27;
1310  case UNW_PPC64_R28:
1311    return _registers.__r28;
1312  case UNW_PPC64_R29:
1313    return _registers.__r29;
1314  case UNW_PPC64_R30:
1315    return _registers.__r30;
1316  case UNW_PPC64_R31:
1317    return _registers.__r31;
1318  case UNW_PPC64_CR0:
1319    return (_registers.__cr & 0xF0000000);
1320  case UNW_PPC64_CR1:
1321    return (_registers.__cr & 0x0F000000);
1322  case UNW_PPC64_CR2:
1323    return (_registers.__cr & 0x00F00000);
1324  case UNW_PPC64_CR3:
1325    return (_registers.__cr & 0x000F0000);
1326  case UNW_PPC64_CR4:
1327    return (_registers.__cr & 0x0000F000);
1328  case UNW_PPC64_CR5:
1329    return (_registers.__cr & 0x00000F00);
1330  case UNW_PPC64_CR6:
1331    return (_registers.__cr & 0x000000F0);
1332  case UNW_PPC64_CR7:
1333    return (_registers.__cr & 0x0000000F);
1334  case UNW_PPC64_XER:
1335    return _registers.__xer;
1336  case UNW_PPC64_LR:
1337    return _registers.__lr;
1338  case UNW_PPC64_CTR:
1339    return _registers.__ctr;
1340  case UNW_PPC64_VRSAVE:
1341    return _registers.__vrsave;
1342  }
1343  _LIBUNWIND_ABORT("unsupported ppc64 register");
1344}
1345
1346inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
1347  switch (regNum) {
1348  case UNW_REG_IP:
1349    _registers.__srr0 = value;
1350    return;
1351  case UNW_PPC64_R0:
1352    _registers.__r0 = value;
1353    return;
1354  case UNW_PPC64_R1:
1355  case UNW_REG_SP:
1356    _registers.__r1 = value;
1357    return;
1358  case UNW_PPC64_R2:
1359    _registers.__r2 = value;
1360    return;
1361  case UNW_PPC64_R3:
1362    _registers.__r3 = value;
1363    return;
1364  case UNW_PPC64_R4:
1365    _registers.__r4 = value;
1366    return;
1367  case UNW_PPC64_R5:
1368    _registers.__r5 = value;
1369    return;
1370  case UNW_PPC64_R6:
1371    _registers.__r6 = value;
1372    return;
1373  case UNW_PPC64_R7:
1374    _registers.__r7 = value;
1375    return;
1376  case UNW_PPC64_R8:
1377    _registers.__r8 = value;
1378    return;
1379  case UNW_PPC64_R9:
1380    _registers.__r9 = value;
1381    return;
1382  case UNW_PPC64_R10:
1383    _registers.__r10 = value;
1384    return;
1385  case UNW_PPC64_R11:
1386    _registers.__r11 = value;
1387    return;
1388  case UNW_PPC64_R12:
1389    _registers.__r12 = value;
1390    return;
1391  case UNW_PPC64_R13:
1392    _registers.__r13 = value;
1393    return;
1394  case UNW_PPC64_R14:
1395    _registers.__r14 = value;
1396    return;
1397  case UNW_PPC64_R15:
1398    _registers.__r15 = value;
1399    return;
1400  case UNW_PPC64_R16:
1401    _registers.__r16 = value;
1402    return;
1403  case UNW_PPC64_R17:
1404    _registers.__r17 = value;
1405    return;
1406  case UNW_PPC64_R18:
1407    _registers.__r18 = value;
1408    return;
1409  case UNW_PPC64_R19:
1410    _registers.__r19 = value;
1411    return;
1412  case UNW_PPC64_R20:
1413    _registers.__r20 = value;
1414    return;
1415  case UNW_PPC64_R21:
1416    _registers.__r21 = value;
1417    return;
1418  case UNW_PPC64_R22:
1419    _registers.__r22 = value;
1420    return;
1421  case UNW_PPC64_R23:
1422    _registers.__r23 = value;
1423    return;
1424  case UNW_PPC64_R24:
1425    _registers.__r24 = value;
1426    return;
1427  case UNW_PPC64_R25:
1428    _registers.__r25 = value;
1429    return;
1430  case UNW_PPC64_R26:
1431    _registers.__r26 = value;
1432    return;
1433  case UNW_PPC64_R27:
1434    _registers.__r27 = value;
1435    return;
1436  case UNW_PPC64_R28:
1437    _registers.__r28 = value;
1438    return;
1439  case UNW_PPC64_R29:
1440    _registers.__r29 = value;
1441    return;
1442  case UNW_PPC64_R30:
1443    _registers.__r30 = value;
1444    return;
1445  case UNW_PPC64_R31:
1446    _registers.__r31 = value;
1447    return;
1448  case UNW_PPC64_CR0:
1449    _registers.__cr &= 0x0FFFFFFF;
1450    _registers.__cr |= (value & 0xF0000000);
1451    return;
1452  case UNW_PPC64_CR1:
1453    _registers.__cr &= 0xF0FFFFFF;
1454    _registers.__cr |= (value & 0x0F000000);
1455    return;
1456  case UNW_PPC64_CR2:
1457    _registers.__cr &= 0xFF0FFFFF;
1458    _registers.__cr |= (value & 0x00F00000);
1459    return;
1460  case UNW_PPC64_CR3:
1461    _registers.__cr &= 0xFFF0FFFF;
1462    _registers.__cr |= (value & 0x000F0000);
1463    return;
1464  case UNW_PPC64_CR4:
1465    _registers.__cr &= 0xFFFF0FFF;
1466    _registers.__cr |= (value & 0x0000F000);
1467    return;
1468  case UNW_PPC64_CR5:
1469    _registers.__cr &= 0xFFFFF0FF;
1470    _registers.__cr |= (value & 0x00000F00);
1471    return;
1472  case UNW_PPC64_CR6:
1473    _registers.__cr &= 0xFFFFFF0F;
1474    _registers.__cr |= (value & 0x000000F0);
1475    return;
1476  case UNW_PPC64_CR7:
1477    _registers.__cr &= 0xFFFFFFF0;
1478    _registers.__cr |= (value & 0x0000000F);
1479    return;
1480  case UNW_PPC64_XER:
1481    _registers.__xer = value;
1482    return;
1483  case UNW_PPC64_LR:
1484    _registers.__lr = value;
1485    return;
1486  case UNW_PPC64_CTR:
1487    _registers.__ctr = value;
1488    return;
1489  case UNW_PPC64_VRSAVE:
1490    _registers.__vrsave = value;
1491    return;
1492  }
1493  _LIBUNWIND_ABORT("unsupported ppc64 register");
1494}
1495
1496inline bool Registers_ppc64::validFloatRegister(int regNum) const {
1497  return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
1498}
1499
1500inline double Registers_ppc64::getFloatRegister(int regNum) const {
1501  assert(validFloatRegister(regNum));
1502  return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
1503}
1504
1505inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
1506  assert(validFloatRegister(regNum));
1507  _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
1508}
1509
1510inline bool Registers_ppc64::validVectorRegister(int regNum) const {
1511#ifdef PPC64_HAS_VMX
1512  if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
1513    return true;
1514  if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
1515    return true;
1516#else
1517  if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
1518    return true;
1519#endif
1520  return false;
1521}
1522
1523inline int Registers_ppc64::getVectorRegNum(int num)
1524{
1525  if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
1526    return num - UNW_PPC64_VS0;
1527  else
1528    return num - UNW_PPC64_VS32 + 32;
1529}
1530
1531inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
1532  assert(validVectorRegister(regNum));
1533  return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
1534}
1535
1536inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
1537  assert(validVectorRegister(regNum));
1538  _vectorScalarRegisters[getVectorRegNum(regNum)].v = value;
1539}
1540
1541inline const char *Registers_ppc64::getRegisterName(int regNum) {
1542  switch (regNum) {
1543  case UNW_REG_IP:
1544    return "ip";
1545  case UNW_REG_SP:
1546    return "sp";
1547  case UNW_PPC64_R0:
1548    return "r0";
1549  case UNW_PPC64_R1:
1550    return "r1";
1551  case UNW_PPC64_R2:
1552    return "r2";
1553  case UNW_PPC64_R3:
1554    return "r3";
1555  case UNW_PPC64_R4:
1556    return "r4";
1557  case UNW_PPC64_R5:
1558    return "r5";
1559  case UNW_PPC64_R6:
1560    return "r6";
1561  case UNW_PPC64_R7:
1562    return "r7";
1563  case UNW_PPC64_R8:
1564    return "r8";
1565  case UNW_PPC64_R9:
1566    return "r9";
1567  case UNW_PPC64_R10:
1568    return "r10";
1569  case UNW_PPC64_R11:
1570    return "r11";
1571  case UNW_PPC64_R12:
1572    return "r12";
1573  case UNW_PPC64_R13:
1574    return "r13";
1575  case UNW_PPC64_R14:
1576    return "r14";
1577  case UNW_PPC64_R15:
1578    return "r15";
1579  case UNW_PPC64_R16:
1580    return "r16";
1581  case UNW_PPC64_R17:
1582    return "r17";
1583  case UNW_PPC64_R18:
1584    return "r18";
1585  case UNW_PPC64_R19:
1586    return "r19";
1587  case UNW_PPC64_R20:
1588    return "r20";
1589  case UNW_PPC64_R21:
1590    return "r21";
1591  case UNW_PPC64_R22:
1592    return "r22";
1593  case UNW_PPC64_R23:
1594    return "r23";
1595  case UNW_PPC64_R24:
1596    return "r24";
1597  case UNW_PPC64_R25:
1598    return "r25";
1599  case UNW_PPC64_R26:
1600    return "r26";
1601  case UNW_PPC64_R27:
1602    return "r27";
1603  case UNW_PPC64_R28:
1604    return "r28";
1605  case UNW_PPC64_R29:
1606    return "r29";
1607  case UNW_PPC64_R30:
1608    return "r30";
1609  case UNW_PPC64_R31:
1610    return "r31";
1611  case UNW_PPC64_CR0:
1612    return "cr0";
1613  case UNW_PPC64_CR1:
1614    return "cr1";
1615  case UNW_PPC64_CR2:
1616    return "cr2";
1617  case UNW_PPC64_CR3:
1618    return "cr3";
1619  case UNW_PPC64_CR4:
1620    return "cr4";
1621  case UNW_PPC64_CR5:
1622    return "cr5";
1623  case UNW_PPC64_CR6:
1624    return "cr6";
1625  case UNW_PPC64_CR7:
1626    return "cr7";
1627  case UNW_PPC64_XER:
1628    return "xer";
1629  case UNW_PPC64_LR:
1630    return "lr";
1631  case UNW_PPC64_CTR:
1632    return "ctr";
1633  case UNW_PPC64_VRSAVE:
1634    return "vrsave";
1635  case UNW_PPC64_F0:
1636    return "fp0";
1637  case UNW_PPC64_F1:
1638    return "fp1";
1639  case UNW_PPC64_F2:
1640    return "fp2";
1641  case UNW_PPC64_F3:
1642    return "fp3";
1643  case UNW_PPC64_F4:
1644    return "fp4";
1645  case UNW_PPC64_F5:
1646    return "fp5";
1647  case UNW_PPC64_F6:
1648    return "fp6";
1649  case UNW_PPC64_F7:
1650    return "fp7";
1651  case UNW_PPC64_F8:
1652    return "fp8";
1653  case UNW_PPC64_F9:
1654    return "fp9";
1655  case UNW_PPC64_F10:
1656    return "fp10";
1657  case UNW_PPC64_F11:
1658    return "fp11";
1659  case UNW_PPC64_F12:
1660    return "fp12";
1661  case UNW_PPC64_F13:
1662    return "fp13";
1663  case UNW_PPC64_F14:
1664    return "fp14";
1665  case UNW_PPC64_F15:
1666    return "fp15";
1667  case UNW_PPC64_F16:
1668    return "fp16";
1669  case UNW_PPC64_F17:
1670    return "fp17";
1671  case UNW_PPC64_F18:
1672    return "fp18";
1673  case UNW_PPC64_F19:
1674    return "fp19";
1675  case UNW_PPC64_F20:
1676    return "fp20";
1677  case UNW_PPC64_F21:
1678    return "fp21";
1679  case UNW_PPC64_F22:
1680    return "fp22";
1681  case UNW_PPC64_F23:
1682    return "fp23";
1683  case UNW_PPC64_F24:
1684    return "fp24";
1685  case UNW_PPC64_F25:
1686    return "fp25";
1687  case UNW_PPC64_F26:
1688    return "fp26";
1689  case UNW_PPC64_F27:
1690    return "fp27";
1691  case UNW_PPC64_F28:
1692    return "fp28";
1693  case UNW_PPC64_F29:
1694    return "fp29";
1695  case UNW_PPC64_F30:
1696    return "fp30";
1697  case UNW_PPC64_F31:
1698    return "fp31";
1699  case UNW_PPC64_V0:
1700    return "v0";
1701  case UNW_PPC64_V1:
1702    return "v1";
1703  case UNW_PPC64_V2:
1704    return "v2";
1705  case UNW_PPC64_V3:
1706    return "v3";
1707  case UNW_PPC64_V4:
1708    return "v4";
1709  case UNW_PPC64_V5:
1710    return "v5";
1711  case UNW_PPC64_V6:
1712    return "v6";
1713  case UNW_PPC64_V7:
1714    return "v7";
1715  case UNW_PPC64_V8:
1716    return "v8";
1717  case UNW_PPC64_V9:
1718    return "v9";
1719  case UNW_PPC64_V10:
1720    return "v10";
1721  case UNW_PPC64_V11:
1722    return "v11";
1723  case UNW_PPC64_V12:
1724    return "v12";
1725  case UNW_PPC64_V13:
1726    return "v13";
1727  case UNW_PPC64_V14:
1728    return "v14";
1729  case UNW_PPC64_V15:
1730    return "v15";
1731  case UNW_PPC64_V16:
1732    return "v16";
1733  case UNW_PPC64_V17:
1734    return "v17";
1735  case UNW_PPC64_V18:
1736    return "v18";
1737  case UNW_PPC64_V19:
1738    return "v19";
1739  case UNW_PPC64_V20:
1740    return "v20";
1741  case UNW_PPC64_V21:
1742    return "v21";
1743  case UNW_PPC64_V22:
1744    return "v22";
1745  case UNW_PPC64_V23:
1746    return "v23";
1747  case UNW_PPC64_V24:
1748    return "v24";
1749  case UNW_PPC64_V25:
1750    return "v25";
1751  case UNW_PPC64_V26:
1752    return "v26";
1753  case UNW_PPC64_V27:
1754    return "v27";
1755  case UNW_PPC64_V28:
1756    return "v28";
1757  case UNW_PPC64_V29:
1758    return "v29";
1759  case UNW_PPC64_V30:
1760    return "v30";
1761  case UNW_PPC64_V31:
1762    return "v31";
1763  }
1764  return "unknown register";
1765}
1766#endif // _LIBUNWIND_TARGET_PPC64
1767
1768
1769#if defined(_LIBUNWIND_TARGET_AARCH64)
1770/// Registers_arm64  holds the register state of a thread in a 64-bit arm
1771/// process.
1772class _LIBUNWIND_HIDDEN Registers_arm64 {
1773public:
1774  Registers_arm64();
1775  Registers_arm64(const void *registers);
1776
1777  bool        validRegister(int num) const;
1778  uint64_t    getRegister(int num) const;
1779  void        setRegister(int num, uint64_t value);
1780  bool        validFloatRegister(int num) const;
1781  double      getFloatRegister(int num) const;
1782  void        setFloatRegister(int num, double value);
1783  bool        validVectorRegister(int num) const;
1784  v128        getVectorRegister(int num) const;
1785  void        setVectorRegister(int num, v128 value);
1786  static const char *getRegisterName(int num);
1787  void        jumpto();
1788  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }
1789  static int  getArch() { return REGISTERS_ARM64; }
1790
1791  uint64_t  getSP() const         { return _registers.__sp; }
1792  void      setSP(uint64_t value) { _registers.__sp = value; }
1793  uint64_t  getIP() const         { return _registers.__pc; }
1794  void      setIP(uint64_t value) { _registers.__pc = value; }
1795  uint64_t  getFP() const         { return _registers.__fp; }
1796  void      setFP(uint64_t value) { _registers.__fp = value; }
1797
1798private:
1799  struct GPRs {
1800    uint64_t __x[29]; // x0-x28
1801    uint64_t __fp;    // Frame pointer x29
1802    uint64_t __lr;    // Link register x30
1803    uint64_t __sp;    // Stack pointer x31
1804    uint64_t __pc;    // Program counter
1805    uint64_t __ra_sign_state; // RA sign state register
1806  };
1807
1808  GPRs    _registers;
1809  double  _vectorHalfRegisters[32];
1810  // Currently only the lower double in 128-bit vectore registers
1811  // is perserved during unwinding.  We could define new register
1812  // numbers (> 96) which mean whole vector registers, then this
1813  // struct would need to change to contain whole vector registers.
1814};
1815
1816inline Registers_arm64::Registers_arm64(const void *registers) {
1817  static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
1818                "arm64 registers do not fit into unw_context_t");
1819  memcpy(&_registers, registers, sizeof(_registers));
1820  static_assert(sizeof(GPRs) == 0x110,
1821                "expected VFP registers to be at offset 272");
1822  memcpy(_vectorHalfRegisters,
1823         static_cast<const uint8_t *>(registers) + sizeof(GPRs),
1824         sizeof(_vectorHalfRegisters));
1825}
1826
1827inline Registers_arm64::Registers_arm64() {
1828  memset(&_registers, 0, sizeof(_registers));
1829  memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
1830}
1831
1832inline bool Registers_arm64::validRegister(int regNum) const {
1833  if (regNum == UNW_REG_IP)
1834    return true;
1835  if (regNum == UNW_REG_SP)
1836    return true;
1837  if (regNum < 0)
1838    return false;
1839  if (regNum > 95)
1840    return false;
1841  if (regNum == UNW_ARM64_RA_SIGN_STATE)
1842    return true;
1843  if ((regNum > 31) && (regNum < 64))
1844    return false;
1845  return true;
1846}
1847
1848inline uint64_t Registers_arm64::getRegister(int regNum) const {
1849  if (regNum == UNW_REG_IP)
1850    return _registers.__pc;
1851  if (regNum == UNW_REG_SP)
1852    return _registers.__sp;
1853  if (regNum == UNW_ARM64_RA_SIGN_STATE)
1854    return _registers.__ra_sign_state;
1855  if ((regNum >= 0) && (regNum < 32))
1856    return _registers.__x[regNum];
1857  _LIBUNWIND_ABORT("unsupported arm64 register");
1858}
1859
1860inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1861  if (regNum == UNW_REG_IP)
1862    _registers.__pc = value;
1863  else if (regNum == UNW_REG_SP)
1864    _registers.__sp = value;
1865  else if (regNum == UNW_ARM64_RA_SIGN_STATE)
1866    _registers.__ra_sign_state = value;
1867  else if ((regNum >= 0) && (regNum < 32))
1868    _registers.__x[regNum] = value;
1869  else
1870    _LIBUNWIND_ABORT("unsupported arm64 register");
1871}
1872
1873inline const char *Registers_arm64::getRegisterName(int regNum) {
1874  switch (regNum) {
1875  case UNW_REG_IP:
1876    return "pc";
1877  case UNW_REG_SP:
1878    return "sp";
1879  case UNW_ARM64_X0:
1880    return "x0";
1881  case UNW_ARM64_X1:
1882    return "x1";
1883  case UNW_ARM64_X2:
1884    return "x2";
1885  case UNW_ARM64_X3:
1886    return "x3";
1887  case UNW_ARM64_X4:
1888    return "x4";
1889  case UNW_ARM64_X5:
1890    return "x5";
1891  case UNW_ARM64_X6:
1892    return "x6";
1893  case UNW_ARM64_X7:
1894    return "x7";
1895  case UNW_ARM64_X8:
1896    return "x8";
1897  case UNW_ARM64_X9:
1898    return "x9";
1899  case UNW_ARM64_X10:
1900    return "x10";
1901  case UNW_ARM64_X11:
1902    return "x11";
1903  case UNW_ARM64_X12:
1904    return "x12";
1905  case UNW_ARM64_X13:
1906    return "x13";
1907  case UNW_ARM64_X14:
1908    return "x14";
1909  case UNW_ARM64_X15:
1910    return "x15";
1911  case UNW_ARM64_X16:
1912    return "x16";
1913  case UNW_ARM64_X17:
1914    return "x17";
1915  case UNW_ARM64_X18:
1916    return "x18";
1917  case UNW_ARM64_X19:
1918    return "x19";
1919  case UNW_ARM64_X20:
1920    return "x20";
1921  case UNW_ARM64_X21:
1922    return "x21";
1923  case UNW_ARM64_X22:
1924    return "x22";
1925  case UNW_ARM64_X23:
1926    return "x23";
1927  case UNW_ARM64_X24:
1928    return "x24";
1929  case UNW_ARM64_X25:
1930    return "x25";
1931  case UNW_ARM64_X26:
1932    return "x26";
1933  case UNW_ARM64_X27:
1934    return "x27";
1935  case UNW_ARM64_X28:
1936    return "x28";
1937  case UNW_ARM64_X29:
1938    return "fp";
1939  case UNW_ARM64_X30:
1940    return "lr";
1941  case UNW_ARM64_X31:
1942    return "sp";
1943  case UNW_ARM64_D0:
1944    return "d0";
1945  case UNW_ARM64_D1:
1946    return "d1";
1947  case UNW_ARM64_D2:
1948    return "d2";
1949  case UNW_ARM64_D3:
1950    return "d3";
1951  case UNW_ARM64_D4:
1952    return "d4";
1953  case UNW_ARM64_D5:
1954    return "d5";
1955  case UNW_ARM64_D6:
1956    return "d6";
1957  case UNW_ARM64_D7:
1958    return "d7";
1959  case UNW_ARM64_D8:
1960    return "d8";
1961  case UNW_ARM64_D9:
1962    return "d9";
1963  case UNW_ARM64_D10:
1964    return "d10";
1965  case UNW_ARM64_D11:
1966    return "d11";
1967  case UNW_ARM64_D12:
1968    return "d12";
1969  case UNW_ARM64_D13:
1970    return "d13";
1971  case UNW_ARM64_D14:
1972    return "d14";
1973  case UNW_ARM64_D15:
1974    return "d15";
1975  case UNW_ARM64_D16:
1976    return "d16";
1977  case UNW_ARM64_D17:
1978    return "d17";
1979  case UNW_ARM64_D18:
1980    return "d18";
1981  case UNW_ARM64_D19:
1982    return "d19";
1983  case UNW_ARM64_D20:
1984    return "d20";
1985  case UNW_ARM64_D21:
1986    return "d21";
1987  case UNW_ARM64_D22:
1988    return "d22";
1989  case UNW_ARM64_D23:
1990    return "d23";
1991  case UNW_ARM64_D24:
1992    return "d24";
1993  case UNW_ARM64_D25:
1994    return "d25";
1995  case UNW_ARM64_D26:
1996    return "d26";
1997  case UNW_ARM64_D27:
1998    return "d27";
1999  case UNW_ARM64_D28:
2000    return "d28";
2001  case UNW_ARM64_D29:
2002    return "d29";
2003  case UNW_ARM64_D30:
2004    return "d30";
2005  case UNW_ARM64_D31:
2006    return "d31";
2007  default:
2008    return "unknown register";
2009  }
2010}
2011
2012inline bool Registers_arm64::validFloatRegister(int regNum) const {
2013  if (regNum < UNW_ARM64_D0)
2014    return false;
2015  if (regNum > UNW_ARM64_D31)
2016    return false;
2017  return true;
2018}
2019
2020inline double Registers_arm64::getFloatRegister(int regNum) const {
2021  assert(validFloatRegister(regNum));
2022  return _vectorHalfRegisters[regNum - UNW_ARM64_D0];
2023}
2024
2025inline void Registers_arm64::setFloatRegister(int regNum, double value) {
2026  assert(validFloatRegister(regNum));
2027  _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value;
2028}
2029
2030inline bool Registers_arm64::validVectorRegister(int) const {
2031  return false;
2032}
2033
2034inline v128 Registers_arm64::getVectorRegister(int) const {
2035  _LIBUNWIND_ABORT("no arm64 vector register support yet");
2036}
2037
2038inline void Registers_arm64::setVectorRegister(int, v128) {
2039  _LIBUNWIND_ABORT("no arm64 vector register support yet");
2040}
2041#endif // _LIBUNWIND_TARGET_AARCH64
2042
2043#if defined(_LIBUNWIND_TARGET_ARM)
2044/// Registers_arm holds the register state of a thread in a 32-bit arm
2045/// process.
2046///
2047/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2048/// this uses more memory than required.
2049class _LIBUNWIND_HIDDEN Registers_arm {
2050public:
2051  Registers_arm();
2052  Registers_arm(const void *registers);
2053
2054  bool        validRegister(int num) const;
2055  uint32_t    getRegister(int num) const;
2056  void        setRegister(int num, uint32_t value);
2057  bool        validFloatRegister(int num) const;
2058  unw_fpreg_t getFloatRegister(int num);
2059  void        setFloatRegister(int num, unw_fpreg_t value);
2060  bool        validVectorRegister(int num) const;
2061  v128        getVectorRegister(int num) const;
2062  void        setVectorRegister(int num, v128 value);
2063  static const char *getRegisterName(int num);
2064  void        jumpto() {
2065    restoreSavedFloatRegisters();
2066    restoreCoreAndJumpTo();
2067  }
2068  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; }
2069  static int  getArch() { return REGISTERS_ARM; }
2070
2071  uint32_t  getSP() const         { return _registers.__sp; }
2072  void      setSP(uint32_t value) { _registers.__sp = value; }
2073  uint32_t  getIP() const         { return _registers.__pc; }
2074  void      setIP(uint32_t value) { _registers.__pc = value; }
2075
2076  void saveVFPAsX() {
2077    assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
2078    _use_X_for_vfp_save = true;
2079  }
2080
2081  void restoreSavedFloatRegisters() {
2082    if (_saved_vfp_d0_d15) {
2083      if (_use_X_for_vfp_save)
2084        restoreVFPWithFLDMX(_vfp_d0_d15_pad);
2085      else
2086        restoreVFPWithFLDMD(_vfp_d0_d15_pad);
2087    }
2088    if (_saved_vfp_d16_d31)
2089      restoreVFPv3(_vfp_d16_d31);
2090#if defined(__ARM_WMMX)
2091    if (_saved_iwmmx)
2092      restoreiWMMX(_iwmmx);
2093    if (_saved_iwmmx_control)
2094      restoreiWMMXControl(_iwmmx_control);
2095#endif
2096  }
2097
2098private:
2099  struct GPRs {
2100    uint32_t __r[13]; // r0-r12
2101    uint32_t __sp;    // Stack pointer r13
2102    uint32_t __lr;    // Link register r14
2103    uint32_t __pc;    // Program counter r15
2104  };
2105
2106  static void saveVFPWithFSTMD(void*);
2107  static void saveVFPWithFSTMX(void*);
2108  static void saveVFPv3(void*);
2109  static void restoreVFPWithFLDMD(void*);
2110  static void restoreVFPWithFLDMX(void*);
2111  static void restoreVFPv3(void*);
2112#if defined(__ARM_WMMX)
2113  static void saveiWMMX(void*);
2114  static void saveiWMMXControl(uint32_t*);
2115  static void restoreiWMMX(void*);
2116  static void restoreiWMMXControl(uint32_t*);
2117#endif
2118  void restoreCoreAndJumpTo();
2119
2120  // ARM registers
2121  GPRs _registers;
2122
2123  // We save floating point registers lazily because we can't know ahead of
2124  // time which ones are used. See EHABI #4.7.
2125
2126  // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2127  //
2128  // See EHABI #7.5 that explains how matching instruction sequences for load
2129  // and store need to be used to correctly restore the exact register bits.
2130  bool _use_X_for_vfp_save;
2131  // Whether VFP D0-D15 are saved.
2132  bool _saved_vfp_d0_d15;
2133  // Whether VFPv3 D16-D31 are saved.
2134  bool _saved_vfp_d16_d31;
2135  // VFP registers D0-D15, + padding if saved using FSTMX
2136  unw_fpreg_t _vfp_d0_d15_pad[17];
2137  // VFPv3 registers D16-D31, always saved using FSTMD
2138  unw_fpreg_t _vfp_d16_d31[16];
2139#if defined(__ARM_WMMX)
2140  // Whether iWMMX data registers are saved.
2141  bool _saved_iwmmx;
2142  // Whether iWMMX control registers are saved.
2143  mutable bool _saved_iwmmx_control;
2144  // iWMMX registers
2145  unw_fpreg_t _iwmmx[16];
2146  // iWMMX control registers
2147  mutable uint32_t _iwmmx_control[4];
2148#endif
2149};
2150
2151inline Registers_arm::Registers_arm(const void *registers)
2152  : _use_X_for_vfp_save(false),
2153    _saved_vfp_d0_d15(false),
2154    _saved_vfp_d16_d31(false) {
2155  static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
2156                "arm registers do not fit into unw_context_t");
2157  // See __unw_getcontext() note about data.
2158  memcpy(&_registers, registers, sizeof(_registers));
2159  memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2160  memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2161#if defined(__ARM_WMMX)
2162  _saved_iwmmx = false;
2163  _saved_iwmmx_control = false;
2164  memset(&_iwmmx, 0, sizeof(_iwmmx));
2165  memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2166#endif
2167}
2168
2169inline Registers_arm::Registers_arm()
2170  : _use_X_for_vfp_save(false),
2171    _saved_vfp_d0_d15(false),
2172    _saved_vfp_d16_d31(false) {
2173  memset(&_registers, 0, sizeof(_registers));
2174  memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2175  memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2176#if defined(__ARM_WMMX)
2177  _saved_iwmmx = false;
2178  _saved_iwmmx_control = false;
2179  memset(&_iwmmx, 0, sizeof(_iwmmx));
2180  memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2181#endif
2182}
2183
2184inline bool Registers_arm::validRegister(int regNum) const {
2185  // Returns true for all non-VFP registers supported by the EHABI
2186  // virtual register set (VRS).
2187  if (regNum == UNW_REG_IP)
2188    return true;
2189
2190  if (regNum == UNW_REG_SP)
2191    return true;
2192
2193  if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
2194    return true;
2195
2196#if defined(__ARM_WMMX)
2197  if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
2198    return true;
2199#endif
2200
2201  return false;
2202}
2203
2204inline uint32_t Registers_arm::getRegister(int regNum) const {
2205  if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
2206    return _registers.__sp;
2207
2208  if (regNum == UNW_ARM_LR)
2209    return _registers.__lr;
2210
2211  if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
2212    return _registers.__pc;
2213
2214  if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
2215    return _registers.__r[regNum];
2216
2217#if defined(__ARM_WMMX)
2218  if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2219    if (!_saved_iwmmx_control) {
2220      _saved_iwmmx_control = true;
2221      saveiWMMXControl(_iwmmx_control);
2222    }
2223    return _iwmmx_control[regNum - UNW_ARM_WC0];
2224  }
2225#endif
2226
2227  _LIBUNWIND_ABORT("unsupported arm register");
2228}
2229
2230inline void Registers_arm::setRegister(int regNum, uint32_t value) {
2231  if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
2232    _registers.__sp = value;
2233    return;
2234  }
2235
2236  if (regNum == UNW_ARM_LR) {
2237    _registers.__lr = value;
2238    return;
2239  }
2240
2241  if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
2242    _registers.__pc = value;
2243    return;
2244  }
2245
2246  if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
2247    _registers.__r[regNum] = value;
2248    return;
2249  }
2250
2251#if defined(__ARM_WMMX)
2252  if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2253    if (!_saved_iwmmx_control) {
2254      _saved_iwmmx_control = true;
2255      saveiWMMXControl(_iwmmx_control);
2256    }
2257    _iwmmx_control[regNum - UNW_ARM_WC0] = value;
2258    return;
2259  }
2260#endif
2261
2262  _LIBUNWIND_ABORT("unsupported arm register");
2263}
2264
2265inline const char *Registers_arm::getRegisterName(int regNum) {
2266  switch (regNum) {
2267  case UNW_REG_IP:
2268  case UNW_ARM_IP: // UNW_ARM_R15 is alias
2269    return "pc";
2270  case UNW_ARM_LR: // UNW_ARM_R14 is alias
2271    return "lr";
2272  case UNW_REG_SP:
2273  case UNW_ARM_SP: // UNW_ARM_R13 is alias
2274    return "sp";
2275  case UNW_ARM_R0:
2276    return "r0";
2277  case UNW_ARM_R1:
2278    return "r1";
2279  case UNW_ARM_R2:
2280    return "r2";
2281  case UNW_ARM_R3:
2282    return "r3";
2283  case UNW_ARM_R4:
2284    return "r4";
2285  case UNW_ARM_R5:
2286    return "r5";
2287  case UNW_ARM_R6:
2288    return "r6";
2289  case UNW_ARM_R7:
2290    return "r7";
2291  case UNW_ARM_R8:
2292    return "r8";
2293  case UNW_ARM_R9:
2294    return "r9";
2295  case UNW_ARM_R10:
2296    return "r10";
2297  case UNW_ARM_R11:
2298    return "r11";
2299  case UNW_ARM_R12:
2300    return "r12";
2301  case UNW_ARM_S0:
2302    return "s0";
2303  case UNW_ARM_S1:
2304    return "s1";
2305  case UNW_ARM_S2:
2306    return "s2";
2307  case UNW_ARM_S3:
2308    return "s3";
2309  case UNW_ARM_S4:
2310    return "s4";
2311  case UNW_ARM_S5:
2312    return "s5";
2313  case UNW_ARM_S6:
2314    return "s6";
2315  case UNW_ARM_S7:
2316    return "s7";
2317  case UNW_ARM_S8:
2318    return "s8";
2319  case UNW_ARM_S9:
2320    return "s9";
2321  case UNW_ARM_S10:
2322    return "s10";
2323  case UNW_ARM_S11:
2324    return "s11";
2325  case UNW_ARM_S12:
2326    return "s12";
2327  case UNW_ARM_S13:
2328    return "s13";
2329  case UNW_ARM_S14:
2330    return "s14";
2331  case UNW_ARM_S15:
2332    return "s15";
2333  case UNW_ARM_S16:
2334    return "s16";
2335  case UNW_ARM_S17:
2336    return "s17";
2337  case UNW_ARM_S18:
2338    return "s18";
2339  case UNW_ARM_S19:
2340    return "s19";
2341  case UNW_ARM_S20:
2342    return "s20";
2343  case UNW_ARM_S21:
2344    return "s21";
2345  case UNW_ARM_S22:
2346    return "s22";
2347  case UNW_ARM_S23:
2348    return "s23";
2349  case UNW_ARM_S24:
2350    return "s24";
2351  case UNW_ARM_S25:
2352    return "s25";
2353  case UNW_ARM_S26:
2354    return "s26";
2355  case UNW_ARM_S27:
2356    return "s27";
2357  case UNW_ARM_S28:
2358    return "s28";
2359  case UNW_ARM_S29:
2360    return "s29";
2361  case UNW_ARM_S30:
2362    return "s30";
2363  case UNW_ARM_S31:
2364    return "s31";
2365  case UNW_ARM_D0:
2366    return "d0";
2367  case UNW_ARM_D1:
2368    return "d1";
2369  case UNW_ARM_D2:
2370    return "d2";
2371  case UNW_ARM_D3:
2372    return "d3";
2373  case UNW_ARM_D4:
2374    return "d4";
2375  case UNW_ARM_D5:
2376    return "d5";
2377  case UNW_ARM_D6:
2378    return "d6";
2379  case UNW_ARM_D7:
2380    return "d7";
2381  case UNW_ARM_D8:
2382    return "d8";
2383  case UNW_ARM_D9:
2384    return "d9";
2385  case UNW_ARM_D10:
2386    return "d10";
2387  case UNW_ARM_D11:
2388    return "d11";
2389  case UNW_ARM_D12:
2390    return "d12";
2391  case UNW_ARM_D13:
2392    return "d13";
2393  case UNW_ARM_D14:
2394    return "d14";
2395  case UNW_ARM_D15:
2396    return "d15";
2397  case UNW_ARM_D16:
2398    return "d16";
2399  case UNW_ARM_D17:
2400    return "d17";
2401  case UNW_ARM_D18:
2402    return "d18";
2403  case UNW_ARM_D19:
2404    return "d19";
2405  case UNW_ARM_D20:
2406    return "d20";
2407  case UNW_ARM_D21:
2408    return "d21";
2409  case UNW_ARM_D22:
2410    return "d22";
2411  case UNW_ARM_D23:
2412    return "d23";
2413  case UNW_ARM_D24:
2414    return "d24";
2415  case UNW_ARM_D25:
2416    return "d25";
2417  case UNW_ARM_D26:
2418    return "d26";
2419  case UNW_ARM_D27:
2420    return "d27";
2421  case UNW_ARM_D28:
2422    return "d28";
2423  case UNW_ARM_D29:
2424    return "d29";
2425  case UNW_ARM_D30:
2426    return "d30";
2427  case UNW_ARM_D31:
2428    return "d31";
2429  default:
2430    return "unknown register";
2431  }
2432}
2433
2434inline bool Registers_arm::validFloatRegister(int regNum) const {
2435  // NOTE: Consider the intel MMX registers floating points so the
2436  // __unw_get_fpreg can be used to transmit the 64-bit data back.
2437  return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
2438#if defined(__ARM_WMMX)
2439      || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
2440#endif
2441      ;
2442}
2443
2444inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
2445  if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2446    if (!_saved_vfp_d0_d15) {
2447      _saved_vfp_d0_d15 = true;
2448      if (_use_X_for_vfp_save)
2449        saveVFPWithFSTMX(_vfp_d0_d15_pad);
2450      else
2451        saveVFPWithFSTMD(_vfp_d0_d15_pad);
2452    }
2453    return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
2454  }
2455
2456  if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2457    if (!_saved_vfp_d16_d31) {
2458      _saved_vfp_d16_d31 = true;
2459      saveVFPv3(_vfp_d16_d31);
2460    }
2461    return _vfp_d16_d31[regNum - UNW_ARM_D16];
2462  }
2463
2464#if defined(__ARM_WMMX)
2465  if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2466    if (!_saved_iwmmx) {
2467      _saved_iwmmx = true;
2468      saveiWMMX(_iwmmx);
2469    }
2470    return _iwmmx[regNum - UNW_ARM_WR0];
2471  }
2472#endif
2473
2474  _LIBUNWIND_ABORT("Unknown ARM float register");
2475}
2476
2477inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
2478  if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2479    if (!_saved_vfp_d0_d15) {
2480      _saved_vfp_d0_d15 = true;
2481      if (_use_X_for_vfp_save)
2482        saveVFPWithFSTMX(_vfp_d0_d15_pad);
2483      else
2484        saveVFPWithFSTMD(_vfp_d0_d15_pad);
2485    }
2486    _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
2487    return;
2488  }
2489
2490  if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2491    if (!_saved_vfp_d16_d31) {
2492      _saved_vfp_d16_d31 = true;
2493      saveVFPv3(_vfp_d16_d31);
2494    }
2495    _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
2496    return;
2497  }
2498
2499#if defined(__ARM_WMMX)
2500  if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2501    if (!_saved_iwmmx) {
2502      _saved_iwmmx = true;
2503      saveiWMMX(_iwmmx);
2504    }
2505    _iwmmx[regNum - UNW_ARM_WR0] = value;
2506    return;
2507  }
2508#endif
2509
2510  _LIBUNWIND_ABORT("Unknown ARM float register");
2511}
2512
2513inline bool Registers_arm::validVectorRegister(int) const {
2514  return false;
2515}
2516
2517inline v128 Registers_arm::getVectorRegister(int) const {
2518  _LIBUNWIND_ABORT("ARM vector support not implemented");
2519}
2520
2521inline void Registers_arm::setVectorRegister(int, v128) {
2522  _LIBUNWIND_ABORT("ARM vector support not implemented");
2523}
2524#endif // _LIBUNWIND_TARGET_ARM
2525
2526
2527#if defined(_LIBUNWIND_TARGET_OR1K)
2528/// Registers_or1k holds the register state of a thread in an OpenRISC1000
2529/// process.
2530class _LIBUNWIND_HIDDEN Registers_or1k {
2531public:
2532  Registers_or1k();
2533  Registers_or1k(const void *registers);
2534
2535  bool        validRegister(int num) const;
2536  uint32_t    getRegister(int num) const;
2537  void        setRegister(int num, uint32_t value);
2538  bool        validFloatRegister(int num) const;
2539  double      getFloatRegister(int num) const;
2540  void        setFloatRegister(int num, double value);
2541  bool        validVectorRegister(int num) const;
2542  v128        getVectorRegister(int num) const;
2543  void        setVectorRegister(int num, v128 value);
2544  static const char *getRegisterName(int num);
2545  void        jumpto();
2546  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; }
2547  static int  getArch() { return REGISTERS_OR1K; }
2548
2549  uint64_t  getSP() const         { return _registers.__r[1]; }
2550  void      setSP(uint32_t value) { _registers.__r[1] = value; }
2551  uint64_t  getIP() const         { return _registers.__pc; }
2552  void      setIP(uint32_t value) { _registers.__pc = value; }
2553
2554private:
2555  struct or1k_thread_state_t {
2556    unsigned int __r[32]; // r0-r31
2557    unsigned int __pc;    // Program counter
2558    unsigned int __epcr;  // Program counter at exception
2559  };
2560
2561  or1k_thread_state_t _registers;
2562};
2563
2564inline Registers_or1k::Registers_or1k(const void *registers) {
2565  static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
2566                "or1k registers do not fit into unw_context_t");
2567  memcpy(&_registers, static_cast<const uint8_t *>(registers),
2568         sizeof(_registers));
2569}
2570
2571inline Registers_or1k::Registers_or1k() {
2572  memset(&_registers, 0, sizeof(_registers));
2573}
2574
2575inline bool Registers_or1k::validRegister(int regNum) const {
2576  if (regNum == UNW_REG_IP)
2577    return true;
2578  if (regNum == UNW_REG_SP)
2579    return true;
2580  if (regNum < 0)
2581    return false;
2582  if (regNum <= UNW_OR1K_R31)
2583    return true;
2584  if (regNum == UNW_OR1K_EPCR)
2585    return true;
2586  return false;
2587}
2588
2589inline uint32_t Registers_or1k::getRegister(int regNum) const {
2590  if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
2591    return _registers.__r[regNum - UNW_OR1K_R0];
2592
2593  switch (regNum) {
2594  case UNW_REG_IP:
2595    return _registers.__pc;
2596  case UNW_REG_SP:
2597    return _registers.__r[1];
2598  case UNW_OR1K_EPCR:
2599    return _registers.__epcr;
2600  }
2601  _LIBUNWIND_ABORT("unsupported or1k register");
2602}
2603
2604inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
2605  if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
2606    _registers.__r[regNum - UNW_OR1K_R0] = value;
2607    return;
2608  }
2609
2610  switch (regNum) {
2611  case UNW_REG_IP:
2612    _registers.__pc = value;
2613    return;
2614  case UNW_REG_SP:
2615    _registers.__r[1] = value;
2616    return;
2617  case UNW_OR1K_EPCR:
2618    _registers.__epcr = value;
2619    return;
2620  }
2621  _LIBUNWIND_ABORT("unsupported or1k register");
2622}
2623
2624inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2625  return false;
2626}
2627
2628inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2629  _LIBUNWIND_ABORT("or1k float support not implemented");
2630}
2631
2632inline void Registers_or1k::setFloatRegister(int /* regNum */,
2633                                             double /* value */) {
2634  _LIBUNWIND_ABORT("or1k float support not implemented");
2635}
2636
2637inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2638  return false;
2639}
2640
2641inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
2642  _LIBUNWIND_ABORT("or1k vector support not implemented");
2643}
2644
2645inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
2646  _LIBUNWIND_ABORT("or1k vector support not implemented");
2647}
2648
2649inline const char *Registers_or1k::getRegisterName(int regNum) {
2650  switch (regNum) {
2651  case UNW_OR1K_R0:
2652    return "r0";
2653  case UNW_OR1K_R1:
2654    return "r1";
2655  case UNW_OR1K_R2:
2656    return "r2";
2657  case UNW_OR1K_R3:
2658    return "r3";
2659  case UNW_OR1K_R4:
2660    return "r4";
2661  case UNW_OR1K_R5:
2662    return "r5";
2663  case UNW_OR1K_R6:
2664    return "r6";
2665  case UNW_OR1K_R7:
2666    return "r7";
2667  case UNW_OR1K_R8:
2668    return "r8";
2669  case UNW_OR1K_R9:
2670    return "r9";
2671  case UNW_OR1K_R10:
2672    return "r10";
2673  case UNW_OR1K_R11:
2674    return "r11";
2675  case UNW_OR1K_R12:
2676    return "r12";
2677  case UNW_OR1K_R13:
2678    return "r13";
2679  case UNW_OR1K_R14:
2680    return "r14";
2681  case UNW_OR1K_R15:
2682    return "r15";
2683  case UNW_OR1K_R16:
2684    return "r16";
2685  case UNW_OR1K_R17:
2686    return "r17";
2687  case UNW_OR1K_R18:
2688    return "r18";
2689  case UNW_OR1K_R19:
2690    return "r19";
2691  case UNW_OR1K_R20:
2692    return "r20";
2693  case UNW_OR1K_R21:
2694    return "r21";
2695  case UNW_OR1K_R22:
2696    return "r22";
2697  case UNW_OR1K_R23:
2698    return "r23";
2699  case UNW_OR1K_R24:
2700    return "r24";
2701  case UNW_OR1K_R25:
2702    return "r25";
2703  case UNW_OR1K_R26:
2704    return "r26";
2705  case UNW_OR1K_R27:
2706    return "r27";
2707  case UNW_OR1K_R28:
2708    return "r28";
2709  case UNW_OR1K_R29:
2710    return "r29";
2711  case UNW_OR1K_R30:
2712    return "r30";
2713  case UNW_OR1K_R31:
2714    return "r31";
2715  case UNW_OR1K_EPCR:
2716    return "EPCR";
2717  default:
2718    return "unknown register";
2719  }
2720
2721}
2722#endif // _LIBUNWIND_TARGET_OR1K
2723
2724#if defined(_LIBUNWIND_TARGET_MIPS_O32)
2725/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2726/// process.
2727class _LIBUNWIND_HIDDEN Registers_mips_o32 {
2728public:
2729  Registers_mips_o32();
2730  Registers_mips_o32(const void *registers);
2731
2732  bool        validRegister(int num) const;
2733  uint32_t    getRegister(int num) const;
2734  void        setRegister(int num, uint32_t value);
2735  bool        validFloatRegister(int num) const;
2736  double      getFloatRegister(int num) const;
2737  void        setFloatRegister(int num, double value);
2738  bool        validVectorRegister(int num) const;
2739  v128        getVectorRegister(int num) const;
2740  void        setVectorRegister(int num, v128 value);
2741  static const char *getRegisterName(int num);
2742  void        jumpto();
2743  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
2744  static int  getArch() { return REGISTERS_MIPS_O32; }
2745
2746  uint32_t  getSP() const         { return _registers.__r[29]; }
2747  void      setSP(uint32_t value) { _registers.__r[29] = value; }
2748  uint32_t  getIP() const         { return _registers.__pc; }
2749  void      setIP(uint32_t value) { _registers.__pc = value; }
2750
2751private:
2752  struct mips_o32_thread_state_t {
2753    uint32_t __r[32];
2754    uint32_t __pc;
2755    uint32_t __hi;
2756    uint32_t __lo;
2757  };
2758
2759  mips_o32_thread_state_t _registers;
2760#ifdef __mips_hard_float
2761  /// O32 with 32-bit floating point registers only uses half of this
2762  /// space.  However, using the same layout for 32-bit vs 64-bit
2763  /// floating point registers results in a single context size for
2764  /// O32 with hard float.
2765  uint32_t _padding;
2766  double _floats[32];
2767#endif
2768};
2769
2770inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
2771  static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
2772                "mips_o32 registers do not fit into unw_context_t");
2773  memcpy(&_registers, static_cast<const uint8_t *>(registers),
2774         sizeof(_registers));
2775}
2776
2777inline Registers_mips_o32::Registers_mips_o32() {
2778  memset(&_registers, 0, sizeof(_registers));
2779}
2780
2781inline bool Registers_mips_o32::validRegister(int regNum) const {
2782  if (regNum == UNW_REG_IP)
2783    return true;
2784  if (regNum == UNW_REG_SP)
2785    return true;
2786  if (regNum < 0)
2787    return false;
2788  if (regNum <= UNW_MIPS_R31)
2789    return true;
2790#if __mips_isa_rev != 6
2791  if (regNum == UNW_MIPS_HI)
2792    return true;
2793  if (regNum == UNW_MIPS_LO)
2794    return true;
2795#endif
2796#if defined(__mips_hard_float) && __mips_fpr == 32
2797  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2798    return true;
2799#endif
2800  // FIXME: DSP accumulator registers, MSA registers
2801  return false;
2802}
2803
2804inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
2805  if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
2806    return _registers.__r[regNum - UNW_MIPS_R0];
2807#if defined(__mips_hard_float) && __mips_fpr == 32
2808  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2809    uint32_t *p;
2810
2811    if (regNum % 2 == 0)
2812      p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2813    else
2814      p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2815    return *p;
2816  }
2817#endif
2818
2819  switch (regNum) {
2820  case UNW_REG_IP:
2821    return _registers.__pc;
2822  case UNW_REG_SP:
2823    return _registers.__r[29];
2824  case UNW_MIPS_HI:
2825    return _registers.__hi;
2826  case UNW_MIPS_LO:
2827    return _registers.__lo;
2828  }
2829  _LIBUNWIND_ABORT("unsupported mips_o32 register");
2830}
2831
2832inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
2833  if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
2834    _registers.__r[regNum - UNW_MIPS_R0] = value;
2835    return;
2836  }
2837#if defined(__mips_hard_float) && __mips_fpr == 32
2838  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2839    uint32_t *p;
2840
2841    if (regNum % 2 == 0)
2842      p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2843    else
2844      p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2845    *p = value;
2846    return;
2847  }
2848#endif
2849
2850  switch (regNum) {
2851  case UNW_REG_IP:
2852    _registers.__pc = value;
2853    return;
2854  case UNW_REG_SP:
2855    _registers.__r[29] = value;
2856    return;
2857  case UNW_MIPS_HI:
2858    _registers.__hi = value;
2859    return;
2860  case UNW_MIPS_LO:
2861    _registers.__lo = value;
2862    return;
2863  }
2864  _LIBUNWIND_ABORT("unsupported mips_o32 register");
2865}
2866
2867inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
2868#if defined(__mips_hard_float) && __mips_fpr == 64
2869  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2870    return true;
2871#endif
2872  return false;
2873}
2874
2875inline double Registers_mips_o32::getFloatRegister(int regNum) const {
2876#if defined(__mips_hard_float) && __mips_fpr == 64
2877  assert(validFloatRegister(regNum));
2878  return _floats[regNum - UNW_MIPS_F0];
2879#else
2880  _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2881#endif
2882}
2883
2884inline void Registers_mips_o32::setFloatRegister(int regNum,
2885                                                 double value) {
2886#if defined(__mips_hard_float) && __mips_fpr == 64
2887  assert(validFloatRegister(regNum));
2888  _floats[regNum - UNW_MIPS_F0] = value;
2889#else
2890  _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2891#endif
2892}
2893
2894inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
2895  return false;
2896}
2897
2898inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
2899  _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2900}
2901
2902inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
2903  _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2904}
2905
2906inline const char *Registers_mips_o32::getRegisterName(int regNum) {
2907  switch (regNum) {
2908  case UNW_MIPS_R0:
2909    return "$0";
2910  case UNW_MIPS_R1:
2911    return "$1";
2912  case UNW_MIPS_R2:
2913    return "$2";
2914  case UNW_MIPS_R3:
2915    return "$3";
2916  case UNW_MIPS_R4:
2917    return "$4";
2918  case UNW_MIPS_R5:
2919    return "$5";
2920  case UNW_MIPS_R6:
2921    return "$6";
2922  case UNW_MIPS_R7:
2923    return "$7";
2924  case UNW_MIPS_R8:
2925    return "$8";
2926  case UNW_MIPS_R9:
2927    return "$9";
2928  case UNW_MIPS_R10:
2929    return "$10";
2930  case UNW_MIPS_R11:
2931    return "$11";
2932  case UNW_MIPS_R12:
2933    return "$12";
2934  case UNW_MIPS_R13:
2935    return "$13";
2936  case UNW_MIPS_R14:
2937    return "$14";
2938  case UNW_MIPS_R15:
2939    return "$15";
2940  case UNW_MIPS_R16:
2941    return "$16";
2942  case UNW_MIPS_R17:
2943    return "$17";
2944  case UNW_MIPS_R18:
2945    return "$18";
2946  case UNW_MIPS_R19:
2947    return "$19";
2948  case UNW_MIPS_R20:
2949    return "$20";
2950  case UNW_MIPS_R21:
2951    return "$21";
2952  case UNW_MIPS_R22:
2953    return "$22";
2954  case UNW_MIPS_R23:
2955    return "$23";
2956  case UNW_MIPS_R24:
2957    return "$24";
2958  case UNW_MIPS_R25:
2959    return "$25";
2960  case UNW_MIPS_R26:
2961    return "$26";
2962  case UNW_MIPS_R27:
2963    return "$27";
2964  case UNW_MIPS_R28:
2965    return "$28";
2966  case UNW_MIPS_R29:
2967    return "$29";
2968  case UNW_MIPS_R30:
2969    return "$30";
2970  case UNW_MIPS_R31:
2971    return "$31";
2972  case UNW_MIPS_F0:
2973    return "$f0";
2974  case UNW_MIPS_F1:
2975    return "$f1";
2976  case UNW_MIPS_F2:
2977    return "$f2";
2978  case UNW_MIPS_F3:
2979    return "$f3";
2980  case UNW_MIPS_F4:
2981    return "$f4";
2982  case UNW_MIPS_F5:
2983    return "$f5";
2984  case UNW_MIPS_F6:
2985    return "$f6";
2986  case UNW_MIPS_F7:
2987    return "$f7";
2988  case UNW_MIPS_F8:
2989    return "$f8";
2990  case UNW_MIPS_F9:
2991    return "$f9";
2992  case UNW_MIPS_F10:
2993    return "$f10";
2994  case UNW_MIPS_F11:
2995    return "$f11";
2996  case UNW_MIPS_F12:
2997    return "$f12";
2998  case UNW_MIPS_F13:
2999    return "$f13";
3000  case UNW_MIPS_F14:
3001    return "$f14";
3002  case UNW_MIPS_F15:
3003    return "$f15";
3004  case UNW_MIPS_F16:
3005    return "$f16";
3006  case UNW_MIPS_F17:
3007    return "$f17";
3008  case UNW_MIPS_F18:
3009    return "$f18";
3010  case UNW_MIPS_F19:
3011    return "$f19";
3012  case UNW_MIPS_F20:
3013    return "$f20";
3014  case UNW_MIPS_F21:
3015    return "$f21";
3016  case UNW_MIPS_F22:
3017    return "$f22";
3018  case UNW_MIPS_F23:
3019    return "$f23";
3020  case UNW_MIPS_F24:
3021    return "$f24";
3022  case UNW_MIPS_F25:
3023    return "$f25";
3024  case UNW_MIPS_F26:
3025    return "$f26";
3026  case UNW_MIPS_F27:
3027    return "$f27";
3028  case UNW_MIPS_F28:
3029    return "$f28";
3030  case UNW_MIPS_F29:
3031    return "$f29";
3032  case UNW_MIPS_F30:
3033    return "$f30";
3034  case UNW_MIPS_F31:
3035    return "$f31";
3036  case UNW_MIPS_HI:
3037    return "$hi";
3038  case UNW_MIPS_LO:
3039    return "$lo";
3040  default:
3041    return "unknown register";
3042  }
3043}
3044#endif // _LIBUNWIND_TARGET_MIPS_O32
3045
3046#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3047/// Registers_mips_newabi holds the register state of a thread in a
3048/// MIPS process using NEWABI (the N32 or N64 ABIs).
3049class _LIBUNWIND_HIDDEN Registers_mips_newabi {
3050public:
3051  Registers_mips_newabi();
3052  Registers_mips_newabi(const void *registers);
3053
3054  bool        validRegister(int num) const;
3055  uint64_t    getRegister(int num) const;
3056  void        setRegister(int num, uint64_t value);
3057  bool        validFloatRegister(int num) const;
3058  double      getFloatRegister(int num) const;
3059  void        setFloatRegister(int num, double value);
3060  bool        validVectorRegister(int num) const;
3061  v128        getVectorRegister(int num) const;
3062  void        setVectorRegister(int num, v128 value);
3063  static const char *getRegisterName(int num);
3064  void        jumpto();
3065  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
3066  static int  getArch() { return REGISTERS_MIPS_NEWABI; }
3067
3068  uint64_t  getSP() const         { return _registers.__r[29]; }
3069  void      setSP(uint64_t value) { _registers.__r[29] = value; }
3070  uint64_t  getIP() const         { return _registers.__pc; }
3071  void      setIP(uint64_t value) { _registers.__pc = value; }
3072
3073private:
3074  struct mips_newabi_thread_state_t {
3075    uint64_t __r[32];
3076    uint64_t __pc;
3077    uint64_t __hi;
3078    uint64_t __lo;
3079  };
3080
3081  mips_newabi_thread_state_t _registers;
3082#ifdef __mips_hard_float
3083  double _floats[32];
3084#endif
3085};
3086
3087inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
3088  static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
3089                "mips_newabi registers do not fit into unw_context_t");
3090  memcpy(&_registers, static_cast<const uint8_t *>(registers),
3091         sizeof(_registers));
3092}
3093
3094inline Registers_mips_newabi::Registers_mips_newabi() {
3095  memset(&_registers, 0, sizeof(_registers));
3096}
3097
3098inline bool Registers_mips_newabi::validRegister(int regNum) const {
3099  if (regNum == UNW_REG_IP)
3100    return true;
3101  if (regNum == UNW_REG_SP)
3102    return true;
3103  if (regNum < 0)
3104    return false;
3105  if (regNum <= UNW_MIPS_R31)
3106    return true;
3107#if __mips_isa_rev != 6
3108  if (regNum == UNW_MIPS_HI)
3109    return true;
3110  if (regNum == UNW_MIPS_LO)
3111    return true;
3112#endif
3113  // FIXME: Hard float, DSP accumulator registers, MSA registers
3114  return false;
3115}
3116
3117inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
3118  if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
3119    return _registers.__r[regNum - UNW_MIPS_R0];
3120
3121  switch (regNum) {
3122  case UNW_REG_IP:
3123    return _registers.__pc;
3124  case UNW_REG_SP:
3125    return _registers.__r[29];
3126  case UNW_MIPS_HI:
3127    return _registers.__hi;
3128  case UNW_MIPS_LO:
3129    return _registers.__lo;
3130  }
3131  _LIBUNWIND_ABORT("unsupported mips_newabi register");
3132}
3133
3134inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
3135  if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
3136    _registers.__r[regNum - UNW_MIPS_R0] = value;
3137    return;
3138  }
3139
3140  switch (regNum) {
3141  case UNW_REG_IP:
3142    _registers.__pc = value;
3143    return;
3144  case UNW_REG_SP:
3145    _registers.__r[29] = value;
3146    return;
3147  case UNW_MIPS_HI:
3148    _registers.__hi = value;
3149    return;
3150  case UNW_MIPS_LO:
3151    _registers.__lo = value;
3152    return;
3153  }
3154  _LIBUNWIND_ABORT("unsupported mips_newabi register");
3155}
3156
3157inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
3158#ifdef __mips_hard_float
3159  if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3160    return true;
3161#endif
3162  return false;
3163}
3164
3165inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
3166#ifdef __mips_hard_float
3167  assert(validFloatRegister(regNum));
3168  return _floats[regNum - UNW_MIPS_F0];
3169#else
3170  _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3171#endif
3172}
3173
3174inline void Registers_mips_newabi::setFloatRegister(int regNum,
3175                                                    double value) {
3176#ifdef __mips_hard_float
3177  assert(validFloatRegister(regNum));
3178  _floats[regNum - UNW_MIPS_F0] = value;
3179#else
3180  _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3181#endif
3182}
3183
3184inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3185  return false;
3186}
3187
3188inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3189  _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3190}
3191
3192inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
3193  _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3194}
3195
3196inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
3197  switch (regNum) {
3198  case UNW_MIPS_R0:
3199    return "$0";
3200  case UNW_MIPS_R1:
3201    return "$1";
3202  case UNW_MIPS_R2:
3203    return "$2";
3204  case UNW_MIPS_R3:
3205    return "$3";
3206  case UNW_MIPS_R4:
3207    return "$4";
3208  case UNW_MIPS_R5:
3209    return "$5";
3210  case UNW_MIPS_R6:
3211    return "$6";
3212  case UNW_MIPS_R7:
3213    return "$7";
3214  case UNW_MIPS_R8:
3215    return "$8";
3216  case UNW_MIPS_R9:
3217    return "$9";
3218  case UNW_MIPS_R10:
3219    return "$10";
3220  case UNW_MIPS_R11:
3221    return "$11";
3222  case UNW_MIPS_R12:
3223    return "$12";
3224  case UNW_MIPS_R13:
3225    return "$13";
3226  case UNW_MIPS_R14:
3227    return "$14";
3228  case UNW_MIPS_R15:
3229    return "$15";
3230  case UNW_MIPS_R16:
3231    return "$16";
3232  case UNW_MIPS_R17:
3233    return "$17";
3234  case UNW_MIPS_R18:
3235    return "$18";
3236  case UNW_MIPS_R19:
3237    return "$19";
3238  case UNW_MIPS_R20:
3239    return "$20";
3240  case UNW_MIPS_R21:
3241    return "$21";
3242  case UNW_MIPS_R22:
3243    return "$22";
3244  case UNW_MIPS_R23:
3245    return "$23";
3246  case UNW_MIPS_R24:
3247    return "$24";
3248  case UNW_MIPS_R25:
3249    return "$25";
3250  case UNW_MIPS_R26:
3251    return "$26";
3252  case UNW_MIPS_R27:
3253    return "$27";
3254  case UNW_MIPS_R28:
3255    return "$28";
3256  case UNW_MIPS_R29:
3257    return "$29";
3258  case UNW_MIPS_R30:
3259    return "$30";
3260  case UNW_MIPS_R31:
3261    return "$31";
3262  case UNW_MIPS_F0:
3263    return "$f0";
3264  case UNW_MIPS_F1:
3265    return "$f1";
3266  case UNW_MIPS_F2:
3267    return "$f2";
3268  case UNW_MIPS_F3:
3269    return "$f3";
3270  case UNW_MIPS_F4:
3271    return "$f4";
3272  case UNW_MIPS_F5:
3273    return "$f5";
3274  case UNW_MIPS_F6:
3275    return "$f6";
3276  case UNW_MIPS_F7:
3277    return "$f7";
3278  case UNW_MIPS_F8:
3279    return "$f8";
3280  case UNW_MIPS_F9:
3281    return "$f9";
3282  case UNW_MIPS_F10:
3283    return "$f10";
3284  case UNW_MIPS_F11:
3285    return "$f11";
3286  case UNW_MIPS_F12:
3287    return "$f12";
3288  case UNW_MIPS_F13:
3289    return "$f13";
3290  case UNW_MIPS_F14:
3291    return "$f14";
3292  case UNW_MIPS_F15:
3293    return "$f15";
3294  case UNW_MIPS_F16:
3295    return "$f16";
3296  case UNW_MIPS_F17:
3297    return "$f17";
3298  case UNW_MIPS_F18:
3299    return "$f18";
3300  case UNW_MIPS_F19:
3301    return "$f19";
3302  case UNW_MIPS_F20:
3303    return "$f20";
3304  case UNW_MIPS_F21:
3305    return "$f21";
3306  case UNW_MIPS_F22:
3307    return "$f22";
3308  case UNW_MIPS_F23:
3309    return "$f23";
3310  case UNW_MIPS_F24:
3311    return "$f24";
3312  case UNW_MIPS_F25:
3313    return "$f25";
3314  case UNW_MIPS_F26:
3315    return "$f26";
3316  case UNW_MIPS_F27:
3317    return "$f27";
3318  case UNW_MIPS_F28:
3319    return "$f28";
3320  case UNW_MIPS_F29:
3321    return "$f29";
3322  case UNW_MIPS_F30:
3323    return "$f30";
3324  case UNW_MIPS_F31:
3325    return "$f31";
3326  case UNW_MIPS_HI:
3327    return "$hi";
3328  case UNW_MIPS_LO:
3329    return "$lo";
3330  default:
3331    return "unknown register";
3332  }
3333}
3334#endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3335
3336#if defined(_LIBUNWIND_TARGET_SPARC)
3337/// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3338/// process.
3339class _LIBUNWIND_HIDDEN Registers_sparc {
3340public:
3341  Registers_sparc();
3342  Registers_sparc(const void *registers);
3343
3344  bool        validRegister(int num) const;
3345  uint32_t    getRegister(int num) const;
3346  void        setRegister(int num, uint32_t value);
3347  bool        validFloatRegister(int num) const;
3348  double      getFloatRegister(int num) const;
3349  void        setFloatRegister(int num, double value);
3350  bool        validVectorRegister(int num) const;
3351  v128        getVectorRegister(int num) const;
3352  void        setVectorRegister(int num, v128 value);
3353  static const char *getRegisterName(int num);
3354  void        jumpto();
3355  static int  lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; }
3356  static int  getArch() { return REGISTERS_SPARC; }
3357
3358  uint64_t  getSP() const         { return _registers.__regs[UNW_SPARC_O6]; }
3359  void      setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
3360  uint64_t  getIP() const         { return _registers.__regs[UNW_SPARC_O7]; }
3361  void      setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3362
3363private:
3364  struct sparc_thread_state_t {
3365    unsigned int __regs[32];
3366  };
3367
3368  sparc_thread_state_t _registers;
3369};
3370
3371inline Registers_sparc::Registers_sparc(const void *registers) {
3372  static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
3373                "sparc registers do not fit into unw_context_t");
3374  memcpy(&_registers, static_cast<const uint8_t *>(registers),
3375         sizeof(_registers));
3376}
3377
3378inline Registers_sparc::Registers_sparc() {
3379  memset(&_registers, 0, sizeof(_registers));
3380}
3381
3382inline bool Registers_sparc::validRegister(int regNum) const {
3383  if (regNum == UNW_REG_IP)
3384    return true;
3385  if (regNum == UNW_REG_SP)
3386    return true;
3387  if (regNum < 0)
3388    return false;
3389  if (regNum <= UNW_SPARC_I7)
3390    return true;
3391  return false;
3392}
3393
3394inline uint32_t Registers_sparc::getRegister(int regNum) const {
3395  if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3396    return _registers.__regs[regNum];
3397  }
3398
3399  switch (regNum) {
3400  case UNW_REG_IP:
3401    return _registers.__regs[UNW_SPARC_O7];
3402  case UNW_REG_SP:
3403    return _registers.__regs[UNW_SPARC_O6];
3404  }
3405  _LIBUNWIND_ABORT("unsupported sparc register");
3406}
3407
3408inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
3409  if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3410    _registers.__regs[regNum] = value;
3411    return;
3412  }
3413
3414  switch (regNum) {
3415  case UNW_REG_IP:
3416    _registers.__regs[UNW_SPARC_O7] = value;
3417    return;
3418  case UNW_REG_SP:
3419    _registers.__regs[UNW_SPARC_O6] = value;
3420    return;
3421  }
3422  _LIBUNWIND_ABORT("unsupported sparc register");
3423}
3424
3425inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3426
3427inline double Registers_sparc::getFloatRegister(int) const {
3428  _LIBUNWIND_ABORT("no Sparc float registers");
3429}
3430
3431inline void Registers_sparc::setFloatRegister(int, double) {
3432  _LIBUNWIND_ABORT("no Sparc float registers");
3433}
3434
3435inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3436
3437inline v128 Registers_sparc::getVectorRegister(int) const {
3438  _LIBUNWIND_ABORT("no Sparc vector registers");
3439}
3440
3441inline void Registers_sparc::setVectorRegister(int, v128) {
3442  _LIBUNWIND_ABORT("no Sparc vector registers");
3443}
3444
3445inline const char *Registers_sparc::getRegisterName(int regNum) {
3446  switch (regNum) {
3447  case UNW_REG_IP:
3448    return "pc";
3449  case UNW_SPARC_G0:
3450    return "g0";
3451  case UNW_SPARC_G1:
3452    return "g1";
3453  case UNW_SPARC_G2:
3454    return "g2";
3455  case UNW_SPARC_G3:
3456    return "g3";
3457  case UNW_SPARC_G4:
3458    return "g4";
3459  case UNW_SPARC_G5:
3460    return "g5";
3461  case UNW_SPARC_G6:
3462    return "g6";
3463  case UNW_SPARC_G7:
3464    return "g7";
3465  case UNW_SPARC_O0:
3466    return "o0";
3467  case UNW_SPARC_O1:
3468    return "o1";
3469  case UNW_SPARC_O2:
3470    return "o2";
3471  case UNW_SPARC_O3:
3472    return "o3";
3473  case UNW_SPARC_O4:
3474    return "o4";
3475  case UNW_SPARC_O5:
3476    return "o5";
3477  case UNW_REG_SP:
3478  case UNW_SPARC_O6:
3479    return "sp";
3480  case UNW_SPARC_O7:
3481    return "o7";
3482  case UNW_SPARC_L0:
3483    return "l0";
3484  case UNW_SPARC_L1:
3485    return "l1";
3486  case UNW_SPARC_L2:
3487    return "l2";
3488  case UNW_SPARC_L3:
3489    return "l3";
3490  case UNW_SPARC_L4:
3491    return "l4";
3492  case UNW_SPARC_L5:
3493    return "l5";
3494  case UNW_SPARC_L6:
3495    return "l6";
3496  case UNW_SPARC_L7:
3497    return "l7";
3498  case UNW_SPARC_I0:
3499    return "i0";
3500  case UNW_SPARC_I1:
3501    return "i1";
3502  case UNW_SPARC_I2:
3503    return "i2";
3504  case UNW_SPARC_I3:
3505    return "i3";
3506  case UNW_SPARC_I4:
3507    return "i4";
3508  case UNW_SPARC_I5:
3509    return "i5";
3510  case UNW_SPARC_I6:
3511    return "fp";
3512  case UNW_SPARC_I7:
3513    return "i7";
3514  default:
3515    return "unknown register";
3516  }
3517}
3518#endif // _LIBUNWIND_TARGET_SPARC
3519
3520} // namespace libunwind
3521
3522#endif // __REGISTERS_HPP__
3523