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