1 //===----------------------------------------------------------------------===//
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
8 // Models register sets for supported processors.
10 //===----------------------------------------------------------------------===//
12 #ifndef __REGISTERS_HPP__
13 #define __REGISTERS_HPP__
18 #include "cet_unwind.h"
20 #include "libunwind.h"
24 // For emulating 128-bit registers
25 struct v128
{ uint32_t vec
[4]; };
36 REGISTERS_MIPS_NEWABI
,
46 #if defined(_LIBUNWIND_TARGET_I386)
47 class _LIBUNWIND_HIDDEN Registers_x86
;
48 extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86
*);
50 #if defined(_LIBUNWIND_USE_CET)
51 extern "C" void *__libunwind_cet_get_jump_target() {
52 return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto
);
56 /// Registers_x86 holds the register state of a thread in a 32-bit intel
58 class _LIBUNWIND_HIDDEN Registers_x86
{
61 Registers_x86(const void *registers
);
63 bool validRegister(int num
) const;
64 uint32_t getRegister(int num
) const;
65 void setRegister(int num
, uint32_t value
);
66 bool validFloatRegister(int) const { return false; }
67 double getFloatRegister(int num
) const;
68 void setFloatRegister(int num
, double value
);
69 bool validVectorRegister(int) const { return false; }
70 v128
getVectorRegister(int num
) const;
71 void setVectorRegister(int num
, v128 value
);
72 static const char *getRegisterName(int num
);
73 void jumpto() { __libunwind_Registers_x86_jumpto(this); }
74 static constexpr int lastDwarfRegNum() {
75 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86
;
77 static int getArch() { return REGISTERS_X86
; }
79 uint32_t getSP() const { return _registers
.__esp
; }
80 void setSP(uint32_t value
) { _registers
.__esp
= value
; }
81 uint32_t getIP() const { return _registers
.__eip
; }
82 void setIP(uint32_t value
) { _registers
.__eip
= value
; }
83 uint32_t getEBP() const { return _registers
.__ebp
; }
84 void setEBP(uint32_t value
) { _registers
.__ebp
= value
; }
85 uint32_t getEBX() const { return _registers
.__ebx
; }
86 void setEBX(uint32_t value
) { _registers
.__ebx
= value
; }
87 uint32_t getECX() const { return _registers
.__ecx
; }
88 void setECX(uint32_t value
) { _registers
.__ecx
= value
; }
89 uint32_t getEDX() const { return _registers
.__edx
; }
90 void setEDX(uint32_t value
) { _registers
.__edx
= value
; }
91 uint32_t getESI() const { return _registers
.__esi
; }
92 void setESI(uint32_t value
) { _registers
.__esi
= value
; }
93 uint32_t getEDI() const { return _registers
.__edi
; }
94 void setEDI(uint32_t value
) { _registers
.__edi
= value
; }
107 unsigned int __eflags
;
119 inline Registers_x86::Registers_x86(const void *registers
) {
120 static_assert((check_fit
<Registers_x86
, unw_context_t
>::does_fit
),
121 "x86 registers do not fit into unw_context_t");
122 memcpy(&_registers
, registers
, sizeof(_registers
));
125 inline Registers_x86::Registers_x86() {
126 memset(&_registers
, 0, sizeof(_registers
));
129 inline bool Registers_x86::validRegister(int regNum
) const {
130 if (regNum
== UNW_REG_IP
)
132 if (regNum
== UNW_REG_SP
)
141 inline uint32_t Registers_x86::getRegister(int regNum
) const {
144 return _registers
.__eip
;
146 return _registers
.__esp
;
148 return _registers
.__eax
;
150 return _registers
.__ecx
;
152 return _registers
.__edx
;
154 return _registers
.__ebx
;
155 #if !defined(__APPLE__)
160 return _registers
.__ebp
;
161 #if !defined(__APPLE__)
166 return _registers
.__esp
;
168 return _registers
.__esi
;
170 return _registers
.__edi
;
172 _LIBUNWIND_ABORT("unsupported x86 register");
175 inline void Registers_x86::setRegister(int regNum
, uint32_t value
) {
178 _registers
.__eip
= value
;
181 _registers
.__esp
= value
;
184 _registers
.__eax
= value
;
187 _registers
.__ecx
= value
;
190 _registers
.__edx
= value
;
193 _registers
.__ebx
= value
;
195 #if !defined(__APPLE__)
200 _registers
.__ebp
= value
;
202 #if !defined(__APPLE__)
207 _registers
.__esp
= value
;
210 _registers
.__esi
= value
;
213 _registers
.__edi
= value
;
216 _LIBUNWIND_ABORT("unsupported x86 register");
219 inline const char *Registers_x86::getRegisterName(int regNum
) {
242 return "unknown register";
246 inline double Registers_x86::getFloatRegister(int) const {
247 _LIBUNWIND_ABORT("no x86 float registers");
250 inline void Registers_x86::setFloatRegister(int, double) {
251 _LIBUNWIND_ABORT("no x86 float registers");
254 inline v128
Registers_x86::getVectorRegister(int) const {
255 _LIBUNWIND_ABORT("no x86 vector registers");
258 inline void Registers_x86::setVectorRegister(int, v128
) {
259 _LIBUNWIND_ABORT("no x86 vector registers");
261 #endif // _LIBUNWIND_TARGET_I386
264 #if defined(_LIBUNWIND_TARGET_X86_64)
265 /// Registers_x86_64 holds the register state of a thread in a 64-bit intel
267 class _LIBUNWIND_HIDDEN Registers_x86_64
;
268 extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64
*);
270 #if defined(_LIBUNWIND_USE_CET)
271 extern "C" void *__libunwind_cet_get_jump_target() {
272 return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto
);
276 class _LIBUNWIND_HIDDEN Registers_x86_64
{
279 Registers_x86_64(const void *registers
);
281 bool validRegister(int num
) const;
282 uint64_t getRegister(int num
) const;
283 void setRegister(int num
, uint64_t value
);
284 bool validFloatRegister(int) const { return false; }
285 double getFloatRegister(int num
) const;
286 void setFloatRegister(int num
, double value
);
287 bool validVectorRegister(int) const;
288 v128
getVectorRegister(int num
) const;
289 void setVectorRegister(int num
, v128 value
);
290 static const char *getRegisterName(int num
);
291 void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }
292 static constexpr int lastDwarfRegNum() {
293 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64
;
295 static int getArch() { return REGISTERS_X86_64
; }
297 uint64_t getSP() const { return _registers
.__rsp
; }
298 void setSP(uint64_t value
) { _registers
.__rsp
= value
; }
299 uint64_t getIP() const { return _registers
.__rip
; }
300 void setIP(uint64_t value
) { _registers
.__rip
= value
; }
301 uint64_t getRBP() const { return _registers
.__rbp
; }
302 void setRBP(uint64_t value
) { _registers
.__rbp
= value
; }
303 uint64_t getRBX() const { return _registers
.__rbx
; }
304 void setRBX(uint64_t value
) { _registers
.__rbx
= value
; }
305 uint64_t getR12() const { return _registers
.__r12
; }
306 void setR12(uint64_t value
) { _registers
.__r12
= value
; }
307 uint64_t getR13() const { return _registers
.__r13
; }
308 void setR13(uint64_t value
) { _registers
.__r13
= value
; }
309 uint64_t getR14() const { return _registers
.__r14
; }
310 void setR14(uint64_t value
) { _registers
.__r14
= value
; }
311 uint64_t getR15() const { return _registers
.__r15
; }
312 void setR15(uint64_t value
) { _registers
.__r15
= value
; }
338 uint64_t __padding
; // 16-byte align
347 inline Registers_x86_64::Registers_x86_64(const void *registers
) {
348 static_assert((check_fit
<Registers_x86_64
, unw_context_t
>::does_fit
),
349 "x86_64 registers do not fit into unw_context_t");
350 memcpy(&_registers
, registers
, sizeof(_registers
));
353 inline Registers_x86_64::Registers_x86_64() {
354 memset(&_registers
, 0, sizeof(_registers
));
357 inline bool Registers_x86_64::validRegister(int regNum
) const {
358 if (regNum
== UNW_REG_IP
)
360 if (regNum
== UNW_REG_SP
)
369 inline uint64_t Registers_x86_64::getRegister(int regNum
) const {
373 return _registers
.__rip
;
375 return _registers
.__rsp
;
377 return _registers
.__rax
;
379 return _registers
.__rdx
;
381 return _registers
.__rcx
;
383 return _registers
.__rbx
;
385 return _registers
.__rsi
;
387 return _registers
.__rdi
;
389 return _registers
.__rbp
;
391 return _registers
.__rsp
;
393 return _registers
.__r8
;
395 return _registers
.__r9
;
397 return _registers
.__r10
;
399 return _registers
.__r11
;
401 return _registers
.__r12
;
403 return _registers
.__r13
;
405 return _registers
.__r14
;
407 return _registers
.__r15
;
409 _LIBUNWIND_ABORT("unsupported x86_64 register");
412 inline void Registers_x86_64::setRegister(int regNum
, uint64_t value
) {
416 _registers
.__rip
= value
;
419 _registers
.__rsp
= value
;
422 _registers
.__rax
= value
;
425 _registers
.__rdx
= value
;
428 _registers
.__rcx
= value
;
431 _registers
.__rbx
= value
;
434 _registers
.__rsi
= value
;
437 _registers
.__rdi
= value
;
440 _registers
.__rbp
= value
;
443 _registers
.__rsp
= value
;
446 _registers
.__r8
= value
;
449 _registers
.__r9
= value
;
452 _registers
.__r10
= value
;
455 _registers
.__r11
= value
;
458 _registers
.__r12
= value
;
461 _registers
.__r13
= value
;
464 _registers
.__r14
= value
;
467 _registers
.__r15
= value
;
470 _LIBUNWIND_ABORT("unsupported x86_64 register");
473 inline const char *Registers_x86_64::getRegisterName(int regNum
) {
512 case UNW_X86_64_XMM0
:
514 case UNW_X86_64_XMM1
:
516 case UNW_X86_64_XMM2
:
518 case UNW_X86_64_XMM3
:
520 case UNW_X86_64_XMM4
:
522 case UNW_X86_64_XMM5
:
524 case UNW_X86_64_XMM6
:
526 case UNW_X86_64_XMM7
:
528 case UNW_X86_64_XMM8
:
530 case UNW_X86_64_XMM9
:
532 case UNW_X86_64_XMM10
:
534 case UNW_X86_64_XMM11
:
536 case UNW_X86_64_XMM12
:
538 case UNW_X86_64_XMM13
:
540 case UNW_X86_64_XMM14
:
542 case UNW_X86_64_XMM15
:
545 return "unknown register";
549 inline double Registers_x86_64::getFloatRegister(int) const {
550 _LIBUNWIND_ABORT("no x86_64 float registers");
553 inline void Registers_x86_64::setFloatRegister(int, double) {
554 _LIBUNWIND_ABORT("no x86_64 float registers");
557 inline bool Registers_x86_64::validVectorRegister(int regNum
) const {
559 if (regNum
< UNW_X86_64_XMM0
)
561 if (regNum
> UNW_X86_64_XMM15
)
565 (void)regNum
; // suppress unused parameter warning
570 inline v128
Registers_x86_64::getVectorRegister(int regNum
) const {
572 assert(validVectorRegister(regNum
));
573 return _xmm
[regNum
- UNW_X86_64_XMM0
];
575 (void)regNum
; // suppress unused parameter warning
576 _LIBUNWIND_ABORT("no x86_64 vector registers");
580 inline void Registers_x86_64::setVectorRegister(int regNum
, v128 value
) {
582 assert(validVectorRegister(regNum
));
583 _xmm
[regNum
- UNW_X86_64_XMM0
] = value
;
585 (void)regNum
; (void)value
; // suppress unused parameter warnings
586 _LIBUNWIND_ABORT("no x86_64 vector registers");
589 #endif // _LIBUNWIND_TARGET_X86_64
592 #if defined(_LIBUNWIND_TARGET_PPC)
593 /// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
595 class _LIBUNWIND_HIDDEN Registers_ppc
{
598 Registers_ppc(const void *registers
);
600 bool validRegister(int num
) const;
601 uint32_t getRegister(int num
) const;
602 void setRegister(int num
, uint32_t value
);
603 bool validFloatRegister(int num
) const;
604 double getFloatRegister(int num
) const;
605 void setFloatRegister(int num
, double value
);
606 bool validVectorRegister(int num
) const;
607 v128
getVectorRegister(int num
) const;
608 void setVectorRegister(int num
, v128 value
);
609 static const char *getRegisterName(int num
);
611 static constexpr int lastDwarfRegNum() {
612 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC
;
614 static int getArch() { return REGISTERS_PPC
; }
616 uint64_t getSP() const { return _registers
.__r1
; }
617 void setSP(uint32_t value
) { _registers
.__r1
= value
; }
618 uint64_t getIP() const { return _registers
.__srr0
; }
619 void setIP(uint32_t value
) { _registers
.__srr0
= value
; }
620 uint64_t getCR() const { return _registers
.__cr
; }
621 void setCR(uint32_t value
) { _registers
.__cr
= value
; }
624 struct ppc_thread_state_t
{
625 unsigned int __srr0
; /* Instruction address register (PC) */
626 unsigned int __srr1
; /* Machine state register (supervisor) */
659 unsigned int __cr
; /* Condition register */
660 unsigned int __xer
; /* User's integer exception register */
661 unsigned int __lr
; /* Link register */
662 unsigned int __ctr
; /* Count register */
663 unsigned int __mq
; /* MQ register (601 only) */
664 unsigned int __vrsave
; /* Vector Save Register */
667 struct ppc_float_state_t
{
670 unsigned int __fpscr_pad
; /* fpscr is 64 bits, 32 bits of rubbish */
671 unsigned int __fpscr
; /* floating point status register */
674 ppc_thread_state_t _registers
;
675 ppc_float_state_t _floatRegisters
;
676 v128 _vectorRegisters
[32]; // offset 424
679 inline Registers_ppc::Registers_ppc(const void *registers
) {
680 static_assert((check_fit
<Registers_ppc
, unw_context_t
>::does_fit
),
681 "ppc registers do not fit into unw_context_t");
682 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
684 static_assert(sizeof(ppc_thread_state_t
) == 160,
685 "expected float register offset to be 160");
686 memcpy(&_floatRegisters
,
687 static_cast<const uint8_t *>(registers
) + sizeof(ppc_thread_state_t
),
688 sizeof(_floatRegisters
));
689 static_assert(sizeof(ppc_thread_state_t
) + sizeof(ppc_float_state_t
) == 424,
690 "expected vector register offset to be 424 bytes");
691 memcpy(_vectorRegisters
,
692 static_cast<const uint8_t *>(registers
) + sizeof(ppc_thread_state_t
) +
693 sizeof(ppc_float_state_t
),
694 sizeof(_vectorRegisters
));
697 inline Registers_ppc::Registers_ppc() {
698 memset(&_registers
, 0, sizeof(_registers
));
699 memset(&_floatRegisters
, 0, sizeof(_floatRegisters
));
700 memset(&_vectorRegisters
, 0, sizeof(_vectorRegisters
));
703 inline bool Registers_ppc::validRegister(int regNum
) const {
704 if (regNum
== UNW_REG_IP
)
706 if (regNum
== UNW_REG_SP
)
708 if (regNum
== UNW_PPC_VRSAVE
)
712 if (regNum
<= UNW_PPC_R31
)
714 if (regNum
== UNW_PPC_MQ
)
716 if (regNum
== UNW_PPC_LR
)
718 if (regNum
== UNW_PPC_CTR
)
720 if ((UNW_PPC_CR0
<= regNum
) && (regNum
<= UNW_PPC_CR7
))
725 inline uint32_t Registers_ppc::getRegister(int regNum
) const {
728 return _registers
.__srr0
;
730 return _registers
.__r1
;
732 return _registers
.__r0
;
734 return _registers
.__r1
;
736 return _registers
.__r2
;
738 return _registers
.__r3
;
740 return _registers
.__r4
;
742 return _registers
.__r5
;
744 return _registers
.__r6
;
746 return _registers
.__r7
;
748 return _registers
.__r8
;
750 return _registers
.__r9
;
752 return _registers
.__r10
;
754 return _registers
.__r11
;
756 return _registers
.__r12
;
758 return _registers
.__r13
;
760 return _registers
.__r14
;
762 return _registers
.__r15
;
764 return _registers
.__r16
;
766 return _registers
.__r17
;
768 return _registers
.__r18
;
770 return _registers
.__r19
;
772 return _registers
.__r20
;
774 return _registers
.__r21
;
776 return _registers
.__r22
;
778 return _registers
.__r23
;
780 return _registers
.__r24
;
782 return _registers
.__r25
;
784 return _registers
.__r26
;
786 return _registers
.__r27
;
788 return _registers
.__r28
;
790 return _registers
.__r29
;
792 return _registers
.__r30
;
794 return _registers
.__r31
;
796 return _registers
.__lr
;
798 return (_registers
.__cr
& 0xF0000000);
800 return (_registers
.__cr
& 0x0F000000);
802 return (_registers
.__cr
& 0x00F00000);
804 return (_registers
.__cr
& 0x000F0000);
806 return (_registers
.__cr
& 0x0000F000);
808 return (_registers
.__cr
& 0x00000F00);
810 return (_registers
.__cr
& 0x000000F0);
812 return (_registers
.__cr
& 0x0000000F);
814 return _registers
.__vrsave
;
816 _LIBUNWIND_ABORT("unsupported ppc register");
819 inline void Registers_ppc::setRegister(int regNum
, uint32_t value
) {
820 //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
823 _registers
.__srr0
= value
;
826 _registers
.__r1
= value
;
829 _registers
.__r0
= value
;
832 _registers
.__r1
= value
;
835 _registers
.__r2
= value
;
838 _registers
.__r3
= value
;
841 _registers
.__r4
= value
;
844 _registers
.__r5
= value
;
847 _registers
.__r6
= value
;
850 _registers
.__r7
= value
;
853 _registers
.__r8
= value
;
856 _registers
.__r9
= value
;
859 _registers
.__r10
= value
;
862 _registers
.__r11
= value
;
865 _registers
.__r12
= value
;
868 _registers
.__r13
= value
;
871 _registers
.__r14
= value
;
874 _registers
.__r15
= value
;
877 _registers
.__r16
= value
;
880 _registers
.__r17
= value
;
883 _registers
.__r18
= value
;
886 _registers
.__r19
= value
;
889 _registers
.__r20
= value
;
892 _registers
.__r21
= value
;
895 _registers
.__r22
= value
;
898 _registers
.__r23
= value
;
901 _registers
.__r24
= value
;
904 _registers
.__r25
= value
;
907 _registers
.__r26
= value
;
910 _registers
.__r27
= value
;
913 _registers
.__r28
= value
;
916 _registers
.__r29
= value
;
919 _registers
.__r30
= value
;
922 _registers
.__r31
= value
;
925 _registers
.__mq
= value
;
928 _registers
.__lr
= value
;
931 _registers
.__ctr
= value
;
934 _registers
.__cr
&= 0x0FFFFFFF;
935 _registers
.__cr
|= (value
& 0xF0000000);
938 _registers
.__cr
&= 0xF0FFFFFF;
939 _registers
.__cr
|= (value
& 0x0F000000);
942 _registers
.__cr
&= 0xFF0FFFFF;
943 _registers
.__cr
|= (value
& 0x00F00000);
946 _registers
.__cr
&= 0xFFF0FFFF;
947 _registers
.__cr
|= (value
& 0x000F0000);
950 _registers
.__cr
&= 0xFFFF0FFF;
951 _registers
.__cr
|= (value
& 0x0000F000);
954 _registers
.__cr
&= 0xFFFFF0FF;
955 _registers
.__cr
|= (value
& 0x00000F00);
958 _registers
.__cr
&= 0xFFFFFF0F;
959 _registers
.__cr
|= (value
& 0x000000F0);
962 _registers
.__cr
&= 0xFFFFFFF0;
963 _registers
.__cr
|= (value
& 0x0000000F);
966 _registers
.__vrsave
= value
;
971 _registers
.__xer
= value
;
975 case UNW_PPC_SPEFSCR
:
979 _LIBUNWIND_ABORT("unsupported ppc register");
982 inline bool Registers_ppc::validFloatRegister(int regNum
) const {
983 if (regNum
< UNW_PPC_F0
)
985 if (regNum
> UNW_PPC_F31
)
990 inline double Registers_ppc::getFloatRegister(int regNum
) const {
991 assert(validFloatRegister(regNum
));
992 return _floatRegisters
.__fpregs
[regNum
- UNW_PPC_F0
];
995 inline void Registers_ppc::setFloatRegister(int regNum
, double value
) {
996 assert(validFloatRegister(regNum
));
997 _floatRegisters
.__fpregs
[regNum
- UNW_PPC_F0
] = value
;
1000 inline bool Registers_ppc::validVectorRegister(int regNum
) const {
1001 if (regNum
< UNW_PPC_V0
)
1003 if (regNum
> UNW_PPC_V31
)
1008 inline v128
Registers_ppc::getVectorRegister(int regNum
) const {
1009 assert(validVectorRegister(regNum
));
1010 v128 result
= _vectorRegisters
[regNum
- UNW_PPC_V0
];
1014 inline void Registers_ppc::setVectorRegister(int regNum
, v128 value
) {
1015 assert(validVectorRegister(regNum
));
1016 _vectorRegisters
[regNum
- UNW_PPC_V0
] = value
;
1019 inline const char *Registers_ppc::getRegisterName(int regNum
) {
1156 return "unknown register";
1160 #endif // _LIBUNWIND_TARGET_PPC
1162 #if defined(_LIBUNWIND_TARGET_PPC64)
1163 /// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
1165 class _LIBUNWIND_HIDDEN Registers_ppc64
{
1168 Registers_ppc64(const void *registers
);
1170 bool validRegister(int num
) const;
1171 uint64_t getRegister(int num
) const;
1172 void setRegister(int num
, uint64_t value
);
1173 bool validFloatRegister(int num
) const;
1174 double getFloatRegister(int num
) const;
1175 void setFloatRegister(int num
, double value
);
1176 bool validVectorRegister(int num
) const;
1177 v128
getVectorRegister(int num
) const;
1178 void setVectorRegister(int num
, v128 value
);
1179 static const char *getRegisterName(int num
);
1181 static constexpr int lastDwarfRegNum() {
1182 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64
;
1184 static int getArch() { return REGISTERS_PPC64
; }
1186 uint64_t getSP() const { return _registers
.__r1
; }
1187 void setSP(uint64_t value
) { _registers
.__r1
= value
; }
1188 uint64_t getIP() const { return _registers
.__srr0
; }
1189 void setIP(uint64_t value
) { _registers
.__srr0
= value
; }
1190 uint64_t getCR() const { return _registers
.__cr
; }
1191 void setCR(uint64_t value
) { _registers
.__cr
= value
; }
1194 struct ppc64_thread_state_t
{
1195 uint64_t __srr0
; // Instruction address register (PC)
1196 uint64_t __srr1
; // Machine state register (supervisor)
1229 uint64_t __cr
; // Condition register
1230 uint64_t __xer
; // User's integer exception register
1231 uint64_t __lr
; // Link register
1232 uint64_t __ctr
; // Count register
1233 uint64_t __vrsave
; // Vector Save Register
1244 ppc64_thread_state_t _registers
;
1245 ppc64_vsr_t _vectorScalarRegisters
[64];
1247 static int getVectorRegNum(int num
);
1250 inline Registers_ppc64::Registers_ppc64(const void *registers
) {
1251 static_assert((check_fit
<Registers_ppc64
, unw_context_t
>::does_fit
),
1252 "ppc64 registers do not fit into unw_context_t");
1253 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
1254 sizeof(_registers
));
1255 static_assert(sizeof(_registers
) == 312,
1256 "expected vector scalar register offset to be 312");
1257 memcpy(&_vectorScalarRegisters
,
1258 static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
1259 sizeof(_vectorScalarRegisters
));
1260 static_assert(sizeof(_registers
) +
1261 sizeof(_vectorScalarRegisters
) == 1336,
1262 "expected vector register offset to be 1336 bytes");
1265 inline Registers_ppc64::Registers_ppc64() {
1266 memset(&_registers
, 0, sizeof(_registers
));
1267 memset(&_vectorScalarRegisters
, 0, sizeof(_vectorScalarRegisters
));
1270 inline bool Registers_ppc64::validRegister(int regNum
) const {
1277 case UNW_PPC64_VRSAVE
:
1281 if (regNum
>= UNW_PPC64_R0
&& regNum
<= UNW_PPC64_R31
)
1283 if (regNum
>= UNW_PPC64_CR0
&& regNum
<= UNW_PPC64_CR7
)
1289 inline uint64_t Registers_ppc64::getRegister(int regNum
) const {
1292 return _registers
.__srr0
;
1294 return _registers
.__r0
;
1297 return _registers
.__r1
;
1299 return _registers
.__r2
;
1301 return _registers
.__r3
;
1303 return _registers
.__r4
;
1305 return _registers
.__r5
;
1307 return _registers
.__r6
;
1309 return _registers
.__r7
;
1311 return _registers
.__r8
;
1313 return _registers
.__r9
;
1315 return _registers
.__r10
;
1317 return _registers
.__r11
;
1319 return _registers
.__r12
;
1321 return _registers
.__r13
;
1323 return _registers
.__r14
;
1325 return _registers
.__r15
;
1327 return _registers
.__r16
;
1329 return _registers
.__r17
;
1331 return _registers
.__r18
;
1333 return _registers
.__r19
;
1335 return _registers
.__r20
;
1337 return _registers
.__r21
;
1339 return _registers
.__r22
;
1341 return _registers
.__r23
;
1343 return _registers
.__r24
;
1345 return _registers
.__r25
;
1347 return _registers
.__r26
;
1349 return _registers
.__r27
;
1351 return _registers
.__r28
;
1353 return _registers
.__r29
;
1355 return _registers
.__r30
;
1357 return _registers
.__r31
;
1359 return (_registers
.__cr
& 0xF0000000);
1361 return (_registers
.__cr
& 0x0F000000);
1363 return (_registers
.__cr
& 0x00F00000);
1365 return (_registers
.__cr
& 0x000F0000);
1367 return (_registers
.__cr
& 0x0000F000);
1369 return (_registers
.__cr
& 0x00000F00);
1371 return (_registers
.__cr
& 0x000000F0);
1373 return (_registers
.__cr
& 0x0000000F);
1375 return _registers
.__xer
;
1377 return _registers
.__lr
;
1379 return _registers
.__ctr
;
1380 case UNW_PPC64_VRSAVE
:
1381 return _registers
.__vrsave
;
1383 _LIBUNWIND_ABORT("unsupported ppc64 register");
1386 inline void Registers_ppc64::setRegister(int regNum
, uint64_t value
) {
1389 _registers
.__srr0
= value
;
1392 _registers
.__r0
= value
;
1396 _registers
.__r1
= value
;
1399 _registers
.__r2
= value
;
1402 _registers
.__r3
= value
;
1405 _registers
.__r4
= value
;
1408 _registers
.__r5
= value
;
1411 _registers
.__r6
= value
;
1414 _registers
.__r7
= value
;
1417 _registers
.__r8
= value
;
1420 _registers
.__r9
= value
;
1423 _registers
.__r10
= value
;
1426 _registers
.__r11
= value
;
1429 _registers
.__r12
= value
;
1432 _registers
.__r13
= value
;
1435 _registers
.__r14
= value
;
1438 _registers
.__r15
= value
;
1441 _registers
.__r16
= value
;
1444 _registers
.__r17
= value
;
1447 _registers
.__r18
= value
;
1450 _registers
.__r19
= value
;
1453 _registers
.__r20
= value
;
1456 _registers
.__r21
= value
;
1459 _registers
.__r22
= value
;
1462 _registers
.__r23
= value
;
1465 _registers
.__r24
= value
;
1468 _registers
.__r25
= value
;
1471 _registers
.__r26
= value
;
1474 _registers
.__r27
= value
;
1477 _registers
.__r28
= value
;
1480 _registers
.__r29
= value
;
1483 _registers
.__r30
= value
;
1486 _registers
.__r31
= value
;
1489 _registers
.__cr
&= 0x0FFFFFFF;
1490 _registers
.__cr
|= (value
& 0xF0000000);
1493 _registers
.__cr
&= 0xF0FFFFFF;
1494 _registers
.__cr
|= (value
& 0x0F000000);
1497 _registers
.__cr
&= 0xFF0FFFFF;
1498 _registers
.__cr
|= (value
& 0x00F00000);
1501 _registers
.__cr
&= 0xFFF0FFFF;
1502 _registers
.__cr
|= (value
& 0x000F0000);
1505 _registers
.__cr
&= 0xFFFF0FFF;
1506 _registers
.__cr
|= (value
& 0x0000F000);
1509 _registers
.__cr
&= 0xFFFFF0FF;
1510 _registers
.__cr
|= (value
& 0x00000F00);
1513 _registers
.__cr
&= 0xFFFFFF0F;
1514 _registers
.__cr
|= (value
& 0x000000F0);
1517 _registers
.__cr
&= 0xFFFFFFF0;
1518 _registers
.__cr
|= (value
& 0x0000000F);
1521 _registers
.__xer
= value
;
1524 _registers
.__lr
= value
;
1527 _registers
.__ctr
= value
;
1529 case UNW_PPC64_VRSAVE
:
1530 _registers
.__vrsave
= value
;
1533 _LIBUNWIND_ABORT("unsupported ppc64 register");
1536 inline bool Registers_ppc64::validFloatRegister(int regNum
) const {
1537 return regNum
>= UNW_PPC64_F0
&& regNum
<= UNW_PPC64_F31
;
1540 inline double Registers_ppc64::getFloatRegister(int regNum
) const {
1541 assert(validFloatRegister(regNum
));
1542 return _vectorScalarRegisters
[regNum
- UNW_PPC64_F0
].asfloat
.f
;
1545 inline void Registers_ppc64::setFloatRegister(int regNum
, double value
) {
1546 assert(validFloatRegister(regNum
));
1547 _vectorScalarRegisters
[regNum
- UNW_PPC64_F0
].asfloat
.f
= value
;
1550 inline bool Registers_ppc64::validVectorRegister(int regNum
) const {
1551 #if defined(__VSX__)
1552 if (regNum
>= UNW_PPC64_VS0
&& regNum
<= UNW_PPC64_VS31
)
1554 if (regNum
>= UNW_PPC64_VS32
&& regNum
<= UNW_PPC64_VS63
)
1556 #elif defined(__ALTIVEC__)
1557 if (regNum
>= UNW_PPC64_V0
&& regNum
<= UNW_PPC64_V31
)
1563 inline int Registers_ppc64::getVectorRegNum(int num
)
1565 if (num
>= UNW_PPC64_VS0
&& num
<= UNW_PPC64_VS31
)
1566 return num
- UNW_PPC64_VS0
;
1568 return num
- UNW_PPC64_VS32
+ 32;
1571 inline v128
Registers_ppc64::getVectorRegister(int regNum
) const {
1572 assert(validVectorRegister(regNum
));
1573 return _vectorScalarRegisters
[getVectorRegNum(regNum
)].v
;
1576 inline void Registers_ppc64::setVectorRegister(int regNum
, v128 value
) {
1577 assert(validVectorRegister(regNum
));
1578 _vectorScalarRegisters
[getVectorRegNum(regNum
)].v
= value
;
1581 inline const char *Registers_ppc64::getRegisterName(int regNum
) {
1673 case UNW_PPC64_VRSAVE
:
1804 return "unknown register";
1806 #endif // _LIBUNWIND_TARGET_PPC64
1809 #if defined(_LIBUNWIND_TARGET_AARCH64)
1810 /// Registers_arm64 holds the register state of a thread in a 64-bit arm
1812 class _LIBUNWIND_HIDDEN Registers_arm64
;
1813 extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64
*);
1814 class _LIBUNWIND_HIDDEN Registers_arm64
{
1817 Registers_arm64(const void *registers
);
1819 bool validRegister(int num
) const;
1820 uint64_t getRegister(int num
) const;
1821 void setRegister(int num
, uint64_t value
);
1822 bool validFloatRegister(int num
) const;
1823 double getFloatRegister(int num
) const;
1824 void setFloatRegister(int num
, double value
);
1825 bool validVectorRegister(int num
) const;
1826 v128
getVectorRegister(int num
) const;
1827 void setVectorRegister(int num
, v128 value
);
1828 static const char *getRegisterName(int num
);
1829 void jumpto() { __libunwind_Registers_arm64_jumpto(this); }
1830 static constexpr int lastDwarfRegNum() {
1831 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
;
1833 static int getArch() { return REGISTERS_ARM64
; }
1835 uint64_t getSP() const { return _registers
.__sp
; }
1836 void setSP(uint64_t value
) { _registers
.__sp
= value
; }
1837 uint64_t getIP() const { return _registers
.__pc
; }
1838 void setIP(uint64_t value
) { _registers
.__pc
= value
; }
1839 uint64_t getFP() const { return _registers
.__fp
; }
1840 void setFP(uint64_t value
) { _registers
.__fp
= value
; }
1844 uint64_t __x
[29]; // x0-x28
1845 uint64_t __fp
; // Frame pointer x29
1846 uint64_t __lr
; // Link register x30
1847 uint64_t __sp
; // Stack pointer x31
1848 uint64_t __pc
; // Program counter
1849 uint64_t __ra_sign_state
; // RA sign state register
1853 double _vectorHalfRegisters
[32];
1854 // Currently only the lower double in 128-bit vectore registers
1855 // is perserved during unwinding. We could define new register
1856 // numbers (> 96) which mean whole vector registers, then this
1857 // struct would need to change to contain whole vector registers.
1860 inline Registers_arm64::Registers_arm64(const void *registers
) {
1861 static_assert((check_fit
<Registers_arm64
, unw_context_t
>::does_fit
),
1862 "arm64 registers do not fit into unw_context_t");
1863 memcpy(&_registers
, registers
, sizeof(_registers
));
1864 static_assert(sizeof(GPRs
) == 0x110,
1865 "expected VFP registers to be at offset 272");
1866 memcpy(_vectorHalfRegisters
,
1867 static_cast<const uint8_t *>(registers
) + sizeof(GPRs
),
1868 sizeof(_vectorHalfRegisters
));
1871 inline Registers_arm64::Registers_arm64() {
1872 memset(&_registers
, 0, sizeof(_registers
));
1873 memset(&_vectorHalfRegisters
, 0, sizeof(_vectorHalfRegisters
));
1876 inline bool Registers_arm64::validRegister(int regNum
) const {
1877 if (regNum
== UNW_REG_IP
)
1879 if (regNum
== UNW_REG_SP
)
1885 if (regNum
== UNW_AARCH64_RA_SIGN_STATE
)
1887 if ((regNum
> 32) && (regNum
< 64))
1892 inline uint64_t Registers_arm64::getRegister(int regNum
) const {
1893 if (regNum
== UNW_REG_IP
|| regNum
== UNW_AARCH64_PC
)
1894 return _registers
.__pc
;
1895 if (regNum
== UNW_REG_SP
|| regNum
== UNW_AARCH64_SP
)
1896 return _registers
.__sp
;
1897 if (regNum
== UNW_AARCH64_RA_SIGN_STATE
)
1898 return _registers
.__ra_sign_state
;
1899 if (regNum
== UNW_AARCH64_FP
)
1900 return _registers
.__fp
;
1901 if (regNum
== UNW_AARCH64_LR
)
1902 return _registers
.__lr
;
1903 if ((regNum
>= 0) && (regNum
< 29))
1904 return _registers
.__x
[regNum
];
1905 _LIBUNWIND_ABORT("unsupported arm64 register");
1908 inline void Registers_arm64::setRegister(int regNum
, uint64_t value
) {
1909 if (regNum
== UNW_REG_IP
|| regNum
== UNW_AARCH64_PC
)
1910 _registers
.__pc
= value
;
1911 else if (regNum
== UNW_REG_SP
|| regNum
== UNW_AARCH64_SP
)
1912 _registers
.__sp
= value
;
1913 else if (regNum
== UNW_AARCH64_RA_SIGN_STATE
)
1914 _registers
.__ra_sign_state
= value
;
1915 else if (regNum
== UNW_AARCH64_FP
)
1916 _registers
.__fp
= value
;
1917 else if (regNum
== UNW_AARCH64_LR
)
1918 _registers
.__lr
= value
;
1919 else if ((regNum
>= 0) && (regNum
< 29))
1920 _registers
.__x
[regNum
] = value
;
1922 _LIBUNWIND_ABORT("unsupported arm64 register");
1925 inline const char *Registers_arm64::getRegisterName(int regNum
) {
1931 case UNW_AARCH64_X0
:
1933 case UNW_AARCH64_X1
:
1935 case UNW_AARCH64_X2
:
1937 case UNW_AARCH64_X3
:
1939 case UNW_AARCH64_X4
:
1941 case UNW_AARCH64_X5
:
1943 case UNW_AARCH64_X6
:
1945 case UNW_AARCH64_X7
:
1947 case UNW_AARCH64_X8
:
1949 case UNW_AARCH64_X9
:
1951 case UNW_AARCH64_X10
:
1953 case UNW_AARCH64_X11
:
1955 case UNW_AARCH64_X12
:
1957 case UNW_AARCH64_X13
:
1959 case UNW_AARCH64_X14
:
1961 case UNW_AARCH64_X15
:
1963 case UNW_AARCH64_X16
:
1965 case UNW_AARCH64_X17
:
1967 case UNW_AARCH64_X18
:
1969 case UNW_AARCH64_X19
:
1971 case UNW_AARCH64_X20
:
1973 case UNW_AARCH64_X21
:
1975 case UNW_AARCH64_X22
:
1977 case UNW_AARCH64_X23
:
1979 case UNW_AARCH64_X24
:
1981 case UNW_AARCH64_X25
:
1983 case UNW_AARCH64_X26
:
1985 case UNW_AARCH64_X27
:
1987 case UNW_AARCH64_X28
:
1989 case UNW_AARCH64_FP
:
1991 case UNW_AARCH64_LR
:
1993 case UNW_AARCH64_SP
:
1995 case UNW_AARCH64_PC
:
1997 case UNW_AARCH64_V0
:
1999 case UNW_AARCH64_V1
:
2001 case UNW_AARCH64_V2
:
2003 case UNW_AARCH64_V3
:
2005 case UNW_AARCH64_V4
:
2007 case UNW_AARCH64_V5
:
2009 case UNW_AARCH64_V6
:
2011 case UNW_AARCH64_V7
:
2013 case UNW_AARCH64_V8
:
2015 case UNW_AARCH64_V9
:
2017 case UNW_AARCH64_V10
:
2019 case UNW_AARCH64_V11
:
2021 case UNW_AARCH64_V12
:
2023 case UNW_AARCH64_V13
:
2025 case UNW_AARCH64_V14
:
2027 case UNW_AARCH64_V15
:
2029 case UNW_AARCH64_V16
:
2031 case UNW_AARCH64_V17
:
2033 case UNW_AARCH64_V18
:
2035 case UNW_AARCH64_V19
:
2037 case UNW_AARCH64_V20
:
2039 case UNW_AARCH64_V21
:
2041 case UNW_AARCH64_V22
:
2043 case UNW_AARCH64_V23
:
2045 case UNW_AARCH64_V24
:
2047 case UNW_AARCH64_V25
:
2049 case UNW_AARCH64_V26
:
2051 case UNW_AARCH64_V27
:
2053 case UNW_AARCH64_V28
:
2055 case UNW_AARCH64_V29
:
2057 case UNW_AARCH64_V30
:
2059 case UNW_AARCH64_V31
:
2062 return "unknown register";
2066 inline bool Registers_arm64::validFloatRegister(int regNum
) const {
2067 if (regNum
< UNW_AARCH64_V0
)
2069 if (regNum
> UNW_AARCH64_V31
)
2074 inline double Registers_arm64::getFloatRegister(int regNum
) const {
2075 assert(validFloatRegister(regNum
));
2076 return _vectorHalfRegisters
[regNum
- UNW_AARCH64_V0
];
2079 inline void Registers_arm64::setFloatRegister(int regNum
, double value
) {
2080 assert(validFloatRegister(regNum
));
2081 _vectorHalfRegisters
[regNum
- UNW_AARCH64_V0
] = value
;
2084 inline bool Registers_arm64::validVectorRegister(int) const {
2088 inline v128
Registers_arm64::getVectorRegister(int) const {
2089 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2092 inline void Registers_arm64::setVectorRegister(int, v128
) {
2093 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2095 #endif // _LIBUNWIND_TARGET_AARCH64
2097 #if defined(_LIBUNWIND_TARGET_ARM)
2098 /// Registers_arm holds the register state of a thread in a 32-bit arm
2101 /// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2102 /// this uses more memory than required.
2103 class _LIBUNWIND_HIDDEN Registers_arm
{
2106 Registers_arm(const void *registers
);
2108 bool validRegister(int num
) const;
2109 uint32_t getRegister(int num
) const;
2110 void setRegister(int num
, uint32_t value
);
2111 bool validFloatRegister(int num
) const;
2112 unw_fpreg_t
getFloatRegister(int num
);
2113 void setFloatRegister(int num
, unw_fpreg_t value
);
2114 bool validVectorRegister(int num
) const;
2115 v128
getVectorRegister(int num
) const;
2116 void setVectorRegister(int num
, v128 value
);
2117 static const char *getRegisterName(int num
);
2119 restoreSavedFloatRegisters();
2120 restoreCoreAndJumpTo();
2122 static constexpr int lastDwarfRegNum() {
2123 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM
;
2125 static int getArch() { return REGISTERS_ARM
; }
2127 uint32_t getSP() const { return _registers
.__sp
; }
2128 void setSP(uint32_t value
) { _registers
.__sp
= value
; }
2129 uint32_t getIP() const { return _registers
.__pc
; }
2130 void setIP(uint32_t value
) { _registers
.__pc
= value
; }
2133 assert(_use_X_for_vfp_save
|| !_saved_vfp_d0_d15
);
2134 _use_X_for_vfp_save
= true;
2137 void restoreSavedFloatRegisters() {
2138 if (_saved_vfp_d0_d15
) {
2139 if (_use_X_for_vfp_save
)
2140 restoreVFPWithFLDMX(_vfp_d0_d15_pad
);
2142 restoreVFPWithFLDMD(_vfp_d0_d15_pad
);
2144 if (_saved_vfp_d16_d31
)
2145 restoreVFPv3(_vfp_d16_d31
);
2146 #if defined(__ARM_WMMX)
2148 restoreiWMMX(_iwmmx
);
2149 if (_saved_iwmmx_control
)
2150 restoreiWMMXControl(_iwmmx_control
);
2156 uint32_t __r
[13]; // r0-r12
2157 uint32_t __sp
; // Stack pointer r13
2158 uint32_t __lr
; // Link register r14
2159 uint32_t __pc
; // Program counter r15
2162 struct PseudoRegisters
{
2163 uint32_t __pac
; // Return Authentication Code (PAC)
2166 static void saveVFPWithFSTMD(void*);
2167 static void saveVFPWithFSTMX(void*);
2168 static void saveVFPv3(void*);
2169 static void restoreVFPWithFLDMD(void*);
2170 static void restoreVFPWithFLDMX(void*);
2171 static void restoreVFPv3(void*);
2172 #if defined(__ARM_WMMX)
2173 static void saveiWMMX(void*);
2174 static void saveiWMMXControl(uint32_t*);
2175 static void restoreiWMMX(void*);
2176 static void restoreiWMMXControl(uint32_t*);
2178 void restoreCoreAndJumpTo();
2182 PseudoRegisters _pseudo_registers
;
2184 // We save floating point registers lazily because we can't know ahead of
2185 // time which ones are used. See EHABI #4.7.
2187 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2189 // See EHABI #7.5 that explains how matching instruction sequences for load
2190 // and store need to be used to correctly restore the exact register bits.
2191 bool _use_X_for_vfp_save
;
2192 // Whether VFP D0-D15 are saved.
2193 bool _saved_vfp_d0_d15
;
2194 // Whether VFPv3 D16-D31 are saved.
2195 bool _saved_vfp_d16_d31
;
2196 // VFP registers D0-D15, + padding if saved using FSTMX
2197 unw_fpreg_t _vfp_d0_d15_pad
[17];
2198 // VFPv3 registers D16-D31, always saved using FSTMD
2199 unw_fpreg_t _vfp_d16_d31
[16];
2200 #if defined(__ARM_WMMX)
2201 // Whether iWMMX data registers are saved.
2203 // Whether iWMMX control registers are saved.
2204 mutable bool _saved_iwmmx_control
;
2206 unw_fpreg_t _iwmmx
[16];
2207 // iWMMX control registers
2208 mutable uint32_t _iwmmx_control
[4];
2212 inline Registers_arm::Registers_arm(const void *registers
)
2213 : _use_X_for_vfp_save(false),
2214 _saved_vfp_d0_d15(false),
2215 _saved_vfp_d16_d31(false) {
2216 static_assert((check_fit
<Registers_arm
, unw_context_t
>::does_fit
),
2217 "arm registers do not fit into unw_context_t");
2218 // See __unw_getcontext() note about data.
2219 memcpy(&_registers
, registers
, sizeof(_registers
));
2220 memset(&_pseudo_registers
, 0, sizeof(_pseudo_registers
));
2221 memset(&_vfp_d0_d15_pad
, 0, sizeof(_vfp_d0_d15_pad
));
2222 memset(&_vfp_d16_d31
, 0, sizeof(_vfp_d16_d31
));
2223 #if defined(__ARM_WMMX)
2224 _saved_iwmmx
= false;
2225 _saved_iwmmx_control
= false;
2226 memset(&_iwmmx
, 0, sizeof(_iwmmx
));
2227 memset(&_iwmmx_control
, 0, sizeof(_iwmmx_control
));
2231 inline Registers_arm::Registers_arm()
2232 : _use_X_for_vfp_save(false),
2233 _saved_vfp_d0_d15(false),
2234 _saved_vfp_d16_d31(false) {
2235 memset(&_registers
, 0, sizeof(_registers
));
2236 memset(&_pseudo_registers
, 0, sizeof(_pseudo_registers
));
2237 memset(&_vfp_d0_d15_pad
, 0, sizeof(_vfp_d0_d15_pad
));
2238 memset(&_vfp_d16_d31
, 0, sizeof(_vfp_d16_d31
));
2239 #if defined(__ARM_WMMX)
2240 _saved_iwmmx
= false;
2241 _saved_iwmmx_control
= false;
2242 memset(&_iwmmx
, 0, sizeof(_iwmmx
));
2243 memset(&_iwmmx_control
, 0, sizeof(_iwmmx_control
));
2247 inline bool Registers_arm::validRegister(int regNum
) const {
2248 // Returns true for all non-VFP registers supported by the EHABI
2249 // virtual register set (VRS).
2250 if (regNum
== UNW_REG_IP
)
2253 if (regNum
== UNW_REG_SP
)
2256 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R15
)
2259 #if defined(__ARM_WMMX)
2260 if (regNum
>= UNW_ARM_WC0
&& regNum
<= UNW_ARM_WC3
)
2264 #ifdef __ARM_FEATURE_PAUTH
2265 if (regNum
== UNW_ARM_RA_AUTH_CODE
)
2272 inline uint32_t Registers_arm::getRegister(int regNum
) const {
2273 if (regNum
== UNW_REG_SP
|| regNum
== UNW_ARM_SP
)
2274 return _registers
.__sp
;
2276 if (regNum
== UNW_ARM_LR
)
2277 return _registers
.__lr
;
2279 if (regNum
== UNW_REG_IP
|| regNum
== UNW_ARM_IP
)
2280 return _registers
.__pc
;
2282 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R12
)
2283 return _registers
.__r
[regNum
];
2285 #if defined(__ARM_WMMX)
2286 if (regNum
>= UNW_ARM_WC0
&& regNum
<= UNW_ARM_WC3
) {
2287 if (!_saved_iwmmx_control
) {
2288 _saved_iwmmx_control
= true;
2289 saveiWMMXControl(_iwmmx_control
);
2291 return _iwmmx_control
[regNum
- UNW_ARM_WC0
];
2295 #ifdef __ARM_FEATURE_PAUTH
2296 if (regNum
== UNW_ARM_RA_AUTH_CODE
)
2297 return _pseudo_registers
.__pac
;
2300 _LIBUNWIND_ABORT("unsupported arm register");
2303 inline void Registers_arm::setRegister(int regNum
, uint32_t value
) {
2304 if (regNum
== UNW_REG_SP
|| regNum
== UNW_ARM_SP
) {
2305 _registers
.__sp
= value
;
2309 if (regNum
== UNW_ARM_LR
) {
2310 _registers
.__lr
= value
;
2314 if (regNum
== UNW_REG_IP
|| regNum
== UNW_ARM_IP
) {
2315 _registers
.__pc
= value
;
2319 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R12
) {
2320 _registers
.__r
[regNum
] = value
;
2324 #if defined(__ARM_WMMX)
2325 if (regNum
>= UNW_ARM_WC0
&& regNum
<= UNW_ARM_WC3
) {
2326 if (!_saved_iwmmx_control
) {
2327 _saved_iwmmx_control
= true;
2328 saveiWMMXControl(_iwmmx_control
);
2330 _iwmmx_control
[regNum
- UNW_ARM_WC0
] = value
;
2335 if (regNum
== UNW_ARM_RA_AUTH_CODE
) {
2336 _pseudo_registers
.__pac
= value
;
2340 _LIBUNWIND_ABORT("unsupported arm register");
2343 inline const char *Registers_arm::getRegisterName(int regNum
) {
2346 case UNW_ARM_IP
: // UNW_ARM_R15 is alias
2348 case UNW_ARM_LR
: // UNW_ARM_R14 is alias
2351 case UNW_ARM_SP
: // UNW_ARM_R13 is alias
2508 return "unknown register";
2512 inline bool Registers_arm::validFloatRegister(int regNum
) const {
2513 // NOTE: Consider the intel MMX registers floating points so the
2514 // __unw_get_fpreg can be used to transmit the 64-bit data back.
2515 return ((regNum
>= UNW_ARM_D0
) && (regNum
<= UNW_ARM_D31
))
2516 #if defined(__ARM_WMMX)
2517 || ((regNum
>= UNW_ARM_WR0
) && (regNum
<= UNW_ARM_WR15
))
2522 inline unw_fpreg_t
Registers_arm::getFloatRegister(int regNum
) {
2523 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D15
) {
2524 if (!_saved_vfp_d0_d15
) {
2525 _saved_vfp_d0_d15
= true;
2526 if (_use_X_for_vfp_save
)
2527 saveVFPWithFSTMX(_vfp_d0_d15_pad
);
2529 saveVFPWithFSTMD(_vfp_d0_d15_pad
);
2531 return _vfp_d0_d15_pad
[regNum
- UNW_ARM_D0
];
2534 if (regNum
>= UNW_ARM_D16
&& regNum
<= UNW_ARM_D31
) {
2535 if (!_saved_vfp_d16_d31
) {
2536 _saved_vfp_d16_d31
= true;
2537 saveVFPv3(_vfp_d16_d31
);
2539 return _vfp_d16_d31
[regNum
- UNW_ARM_D16
];
2542 #if defined(__ARM_WMMX)
2543 if (regNum
>= UNW_ARM_WR0
&& regNum
<= UNW_ARM_WR15
) {
2544 if (!_saved_iwmmx
) {
2545 _saved_iwmmx
= true;
2548 return _iwmmx
[regNum
- UNW_ARM_WR0
];
2552 _LIBUNWIND_ABORT("Unknown ARM float register");
2555 inline void Registers_arm::setFloatRegister(int regNum
, unw_fpreg_t value
) {
2556 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D15
) {
2557 if (!_saved_vfp_d0_d15
) {
2558 _saved_vfp_d0_d15
= true;
2559 if (_use_X_for_vfp_save
)
2560 saveVFPWithFSTMX(_vfp_d0_d15_pad
);
2562 saveVFPWithFSTMD(_vfp_d0_d15_pad
);
2564 _vfp_d0_d15_pad
[regNum
- UNW_ARM_D0
] = value
;
2568 if (regNum
>= UNW_ARM_D16
&& regNum
<= UNW_ARM_D31
) {
2569 if (!_saved_vfp_d16_d31
) {
2570 _saved_vfp_d16_d31
= true;
2571 saveVFPv3(_vfp_d16_d31
);
2573 _vfp_d16_d31
[regNum
- UNW_ARM_D16
] = value
;
2577 #if defined(__ARM_WMMX)
2578 if (regNum
>= UNW_ARM_WR0
&& regNum
<= UNW_ARM_WR15
) {
2579 if (!_saved_iwmmx
) {
2580 _saved_iwmmx
= true;
2583 _iwmmx
[regNum
- UNW_ARM_WR0
] = value
;
2588 _LIBUNWIND_ABORT("Unknown ARM float register");
2591 inline bool Registers_arm::validVectorRegister(int) const {
2595 inline v128
Registers_arm::getVectorRegister(int) const {
2596 _LIBUNWIND_ABORT("ARM vector support not implemented");
2599 inline void Registers_arm::setVectorRegister(int, v128
) {
2600 _LIBUNWIND_ABORT("ARM vector support not implemented");
2602 #endif // _LIBUNWIND_TARGET_ARM
2605 #if defined(_LIBUNWIND_TARGET_OR1K)
2606 /// Registers_or1k holds the register state of a thread in an OpenRISC1000
2608 class _LIBUNWIND_HIDDEN Registers_or1k
{
2611 Registers_or1k(const void *registers
);
2613 bool validRegister(int num
) const;
2614 uint32_t getRegister(int num
) const;
2615 void setRegister(int num
, uint32_t value
);
2616 bool validFloatRegister(int num
) const;
2617 double getFloatRegister(int num
) const;
2618 void setFloatRegister(int num
, double value
);
2619 bool validVectorRegister(int num
) const;
2620 v128
getVectorRegister(int num
) const;
2621 void setVectorRegister(int num
, v128 value
);
2622 static const char *getRegisterName(int num
);
2624 static constexpr int lastDwarfRegNum() {
2625 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K
;
2627 static int getArch() { return REGISTERS_OR1K
; }
2629 uint64_t getSP() const { return _registers
.__r
[1]; }
2630 void setSP(uint32_t value
) { _registers
.__r
[1] = value
; }
2631 uint64_t getIP() const { return _registers
.__pc
; }
2632 void setIP(uint32_t value
) { _registers
.__pc
= value
; }
2635 struct or1k_thread_state_t
{
2636 unsigned int __r
[32]; // r0-r31
2637 unsigned int __pc
; // Program counter
2638 unsigned int __epcr
; // Program counter at exception
2641 or1k_thread_state_t _registers
;
2644 inline Registers_or1k::Registers_or1k(const void *registers
) {
2645 static_assert((check_fit
<Registers_or1k
, unw_context_t
>::does_fit
),
2646 "or1k registers do not fit into unw_context_t");
2647 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
2648 sizeof(_registers
));
2651 inline Registers_or1k::Registers_or1k() {
2652 memset(&_registers
, 0, sizeof(_registers
));
2655 inline bool Registers_or1k::validRegister(int regNum
) const {
2656 if (regNum
== UNW_REG_IP
)
2658 if (regNum
== UNW_REG_SP
)
2662 if (regNum
<= UNW_OR1K_R31
)
2664 if (regNum
== UNW_OR1K_EPCR
)
2669 inline uint32_t Registers_or1k::getRegister(int regNum
) const {
2670 if (regNum
>= UNW_OR1K_R0
&& regNum
<= UNW_OR1K_R31
)
2671 return _registers
.__r
[regNum
- UNW_OR1K_R0
];
2675 return _registers
.__pc
;
2677 return _registers
.__r
[1];
2679 return _registers
.__epcr
;
2681 _LIBUNWIND_ABORT("unsupported or1k register");
2684 inline void Registers_or1k::setRegister(int regNum
, uint32_t value
) {
2685 if (regNum
>= UNW_OR1K_R0
&& regNum
<= UNW_OR1K_R31
) {
2686 _registers
.__r
[regNum
- UNW_OR1K_R0
] = value
;
2692 _registers
.__pc
= value
;
2695 _registers
.__r
[1] = value
;
2698 _registers
.__epcr
= value
;
2701 _LIBUNWIND_ABORT("unsupported or1k register");
2704 inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2708 inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2709 _LIBUNWIND_ABORT("or1k float support not implemented");
2712 inline void Registers_or1k::setFloatRegister(int /* regNum */,
2713 double /* value */) {
2714 _LIBUNWIND_ABORT("or1k float support not implemented");
2717 inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2721 inline v128
Registers_or1k::getVectorRegister(int /* regNum */) const {
2722 _LIBUNWIND_ABORT("or1k vector support not implemented");
2725 inline void Registers_or1k::setVectorRegister(int /* regNum */, v128
/* value */) {
2726 _LIBUNWIND_ABORT("or1k vector support not implemented");
2729 inline const char *Registers_or1k::getRegisterName(int regNum
) {
2798 return "unknown register";
2802 #endif // _LIBUNWIND_TARGET_OR1K
2804 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
2805 /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2807 class _LIBUNWIND_HIDDEN Registers_mips_o32
{
2809 Registers_mips_o32();
2810 Registers_mips_o32(const void *registers
);
2812 bool validRegister(int num
) const;
2813 uint32_t getRegister(int num
) const;
2814 void setRegister(int num
, uint32_t value
);
2815 bool validFloatRegister(int num
) const;
2816 double getFloatRegister(int num
) const;
2817 void setFloatRegister(int num
, double value
);
2818 bool validVectorRegister(int num
) const;
2819 v128
getVectorRegister(int num
) const;
2820 void setVectorRegister(int num
, v128 value
);
2821 static const char *getRegisterName(int num
);
2823 static constexpr int lastDwarfRegNum() {
2824 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
;
2826 static int getArch() { return REGISTERS_MIPS_O32
; }
2828 uint32_t getSP() const { return _registers
.__r
[29]; }
2829 void setSP(uint32_t value
) { _registers
.__r
[29] = value
; }
2830 uint32_t getIP() const { return _registers
.__pc
; }
2831 void setIP(uint32_t value
) { _registers
.__pc
= value
; }
2834 struct mips_o32_thread_state_t
{
2841 mips_o32_thread_state_t _registers
;
2842 #ifdef __mips_hard_float
2843 /// O32 with 32-bit floating point registers only uses half of this
2844 /// space. However, using the same layout for 32-bit vs 64-bit
2845 /// floating point registers results in a single context size for
2846 /// O32 with hard float.
2852 inline Registers_mips_o32::Registers_mips_o32(const void *registers
) {
2853 static_assert((check_fit
<Registers_mips_o32
, unw_context_t
>::does_fit
),
2854 "mips_o32 registers do not fit into unw_context_t");
2855 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
2856 sizeof(_registers
));
2859 inline Registers_mips_o32::Registers_mips_o32() {
2860 memset(&_registers
, 0, sizeof(_registers
));
2863 inline bool Registers_mips_o32::validRegister(int regNum
) const {
2864 if (regNum
== UNW_REG_IP
)
2866 if (regNum
== UNW_REG_SP
)
2870 if (regNum
<= UNW_MIPS_R31
)
2872 #if __mips_isa_rev != 6
2873 if (regNum
== UNW_MIPS_HI
)
2875 if (regNum
== UNW_MIPS_LO
)
2878 #if defined(__mips_hard_float) && __mips_fpr == 32
2879 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
)
2882 // FIXME: DSP accumulator registers, MSA registers
2886 inline uint32_t Registers_mips_o32::getRegister(int regNum
) const {
2887 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
)
2888 return _registers
.__r
[regNum
- UNW_MIPS_R0
];
2889 #if defined(__mips_hard_float) && __mips_fpr == 32
2890 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
) {
2893 if (regNum
% 2 == 0)
2894 p
= (uint32_t *)&_floats
[regNum
- UNW_MIPS_F0
];
2896 p
= (uint32_t *)&_floats
[(regNum
- 1) - UNW_MIPS_F0
] + 1;
2903 return _registers
.__pc
;
2905 return _registers
.__r
[29];
2907 return _registers
.__hi
;
2909 return _registers
.__lo
;
2911 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2914 inline void Registers_mips_o32::setRegister(int regNum
, uint32_t value
) {
2915 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
) {
2916 _registers
.__r
[regNum
- UNW_MIPS_R0
] = value
;
2919 #if defined(__mips_hard_float) && __mips_fpr == 32
2920 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
) {
2923 if (regNum
% 2 == 0)
2924 p
= (uint32_t *)&_floats
[regNum
- UNW_MIPS_F0
];
2926 p
= (uint32_t *)&_floats
[(regNum
- 1) - UNW_MIPS_F0
] + 1;
2934 _registers
.__pc
= value
;
2937 _registers
.__r
[29] = value
;
2940 _registers
.__hi
= value
;
2943 _registers
.__lo
= value
;
2946 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2949 inline bool Registers_mips_o32::validFloatRegister(int regNum
) const {
2950 #if defined(__mips_hard_float) && __mips_fpr == 64
2951 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
)
2959 inline double Registers_mips_o32::getFloatRegister(int regNum
) const {
2960 #if defined(__mips_hard_float) && __mips_fpr == 64
2961 assert(validFloatRegister(regNum
));
2962 return _floats
[regNum
- UNW_MIPS_F0
];
2965 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2969 inline void Registers_mips_o32::setFloatRegister(int regNum
,
2971 #if defined(__mips_hard_float) && __mips_fpr == 64
2972 assert(validFloatRegister(regNum
));
2973 _floats
[regNum
- UNW_MIPS_F0
] = value
;
2977 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2981 inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
2985 inline v128
Registers_mips_o32::getVectorRegister(int /* regNum */) const {
2986 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2989 inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128
/* value */) {
2990 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2993 inline const char *Registers_mips_o32::getRegisterName(int regNum
) {
3128 return "unknown register";
3131 #endif // _LIBUNWIND_TARGET_MIPS_O32
3133 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3134 /// Registers_mips_newabi holds the register state of a thread in a
3135 /// MIPS process using NEWABI (the N32 or N64 ABIs).
3136 class _LIBUNWIND_HIDDEN Registers_mips_newabi
{
3138 Registers_mips_newabi();
3139 Registers_mips_newabi(const void *registers
);
3141 bool validRegister(int num
) const;
3142 uint64_t getRegister(int num
) const;
3143 void setRegister(int num
, uint64_t value
);
3144 bool validFloatRegister(int num
) const;
3145 double getFloatRegister(int num
) const;
3146 void setFloatRegister(int num
, double value
);
3147 bool validVectorRegister(int num
) const;
3148 v128
getVectorRegister(int num
) const;
3149 void setVectorRegister(int num
, v128 value
);
3150 static const char *getRegisterName(int num
);
3152 static constexpr int lastDwarfRegNum() {
3153 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
;
3155 static int getArch() { return REGISTERS_MIPS_NEWABI
; }
3157 uint64_t getSP() const { return _registers
.__r
[29]; }
3158 void setSP(uint64_t value
) { _registers
.__r
[29] = value
; }
3159 uint64_t getIP() const { return _registers
.__pc
; }
3160 void setIP(uint64_t value
) { _registers
.__pc
= value
; }
3163 struct mips_newabi_thread_state_t
{
3170 mips_newabi_thread_state_t _registers
;
3171 #ifdef __mips_hard_float
3176 inline Registers_mips_newabi::Registers_mips_newabi(const void *registers
) {
3177 static_assert((check_fit
<Registers_mips_newabi
, unw_context_t
>::does_fit
),
3178 "mips_newabi registers do not fit into unw_context_t");
3179 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
3180 sizeof(_registers
));
3183 inline Registers_mips_newabi::Registers_mips_newabi() {
3184 memset(&_registers
, 0, sizeof(_registers
));
3187 inline bool Registers_mips_newabi::validRegister(int regNum
) const {
3188 if (regNum
== UNW_REG_IP
)
3190 if (regNum
== UNW_REG_SP
)
3194 if (regNum
<= UNW_MIPS_R31
)
3196 #if __mips_isa_rev != 6
3197 if (regNum
== UNW_MIPS_HI
)
3199 if (regNum
== UNW_MIPS_LO
)
3202 // FIXME: Hard float, DSP accumulator registers, MSA registers
3206 inline uint64_t Registers_mips_newabi::getRegister(int regNum
) const {
3207 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
)
3208 return _registers
.__r
[regNum
- UNW_MIPS_R0
];
3212 return _registers
.__pc
;
3214 return _registers
.__r
[29];
3216 return _registers
.__hi
;
3218 return _registers
.__lo
;
3220 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3223 inline void Registers_mips_newabi::setRegister(int regNum
, uint64_t value
) {
3224 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
) {
3225 _registers
.__r
[regNum
- UNW_MIPS_R0
] = value
;
3231 _registers
.__pc
= value
;
3234 _registers
.__r
[29] = value
;
3237 _registers
.__hi
= value
;
3240 _registers
.__lo
= value
;
3243 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3246 inline bool Registers_mips_newabi::validFloatRegister(int regNum
) const {
3247 #ifdef __mips_hard_float
3248 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
)
3256 inline double Registers_mips_newabi::getFloatRegister(int regNum
) const {
3257 #ifdef __mips_hard_float
3258 assert(validFloatRegister(regNum
));
3259 return _floats
[regNum
- UNW_MIPS_F0
];
3262 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3266 inline void Registers_mips_newabi::setFloatRegister(int regNum
,
3268 #ifdef __mips_hard_float
3269 assert(validFloatRegister(regNum
));
3270 _floats
[regNum
- UNW_MIPS_F0
] = value
;
3274 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3278 inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3282 inline v128
Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3283 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3286 inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128
/* value */) {
3287 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3290 inline const char *Registers_mips_newabi::getRegisterName(int regNum
) {
3425 return "unknown register";
3428 #endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3430 #if defined(_LIBUNWIND_TARGET_SPARC)
3431 /// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3433 class _LIBUNWIND_HIDDEN Registers_sparc
{
3436 Registers_sparc(const void *registers
);
3438 bool validRegister(int num
) const;
3439 uint32_t getRegister(int num
) const;
3440 void setRegister(int num
, uint32_t value
);
3441 bool validFloatRegister(int num
) const;
3442 double getFloatRegister(int num
) const;
3443 void setFloatRegister(int num
, double value
);
3444 bool validVectorRegister(int num
) const;
3445 v128
getVectorRegister(int num
) const;
3446 void setVectorRegister(int num
, v128 value
);
3447 static const char *getRegisterName(int num
);
3449 static constexpr int lastDwarfRegNum() {
3450 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
;
3452 static int getArch() { return REGISTERS_SPARC
; }
3454 uint64_t getSP() const { return _registers
.__regs
[UNW_SPARC_O6
]; }
3455 void setSP(uint32_t value
) { _registers
.__regs
[UNW_SPARC_O6
] = value
; }
3456 uint64_t getIP() const { return _registers
.__regs
[UNW_SPARC_O7
]; }
3457 void setIP(uint32_t value
) { _registers
.__regs
[UNW_SPARC_O7
] = value
; }
3460 struct sparc_thread_state_t
{
3461 unsigned int __regs
[32];
3464 sparc_thread_state_t _registers
;
3467 inline Registers_sparc::Registers_sparc(const void *registers
) {
3468 static_assert((check_fit
<Registers_sparc
, unw_context_t
>::does_fit
),
3469 "sparc registers do not fit into unw_context_t");
3470 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
3471 sizeof(_registers
));
3474 inline Registers_sparc::Registers_sparc() {
3475 memset(&_registers
, 0, sizeof(_registers
));
3478 inline bool Registers_sparc::validRegister(int regNum
) const {
3479 if (regNum
== UNW_REG_IP
)
3481 if (regNum
== UNW_REG_SP
)
3485 if (regNum
<= UNW_SPARC_I7
)
3490 inline uint32_t Registers_sparc::getRegister(int regNum
) const {
3491 if ((UNW_SPARC_G0
<= regNum
) && (regNum
<= UNW_SPARC_I7
)) {
3492 return _registers
.__regs
[regNum
];
3497 return _registers
.__regs
[UNW_SPARC_O7
];
3499 return _registers
.__regs
[UNW_SPARC_O6
];
3501 _LIBUNWIND_ABORT("unsupported sparc register");
3504 inline void Registers_sparc::setRegister(int regNum
, uint32_t value
) {
3505 if ((UNW_SPARC_G0
<= regNum
) && (regNum
<= UNW_SPARC_I7
)) {
3506 _registers
.__regs
[regNum
] = value
;
3512 _registers
.__regs
[UNW_SPARC_O7
] = value
;
3515 _registers
.__regs
[UNW_SPARC_O6
] = value
;
3518 _LIBUNWIND_ABORT("unsupported sparc register");
3521 inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3523 inline double Registers_sparc::getFloatRegister(int) const {
3524 _LIBUNWIND_ABORT("no Sparc float registers");
3527 inline void Registers_sparc::setFloatRegister(int, double) {
3528 _LIBUNWIND_ABORT("no Sparc float registers");
3531 inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3533 inline v128
Registers_sparc::getVectorRegister(int) const {
3534 _LIBUNWIND_ABORT("no Sparc vector registers");
3537 inline void Registers_sparc::setVectorRegister(int, v128
) {
3538 _LIBUNWIND_ABORT("no Sparc vector registers");
3541 inline const char *Registers_sparc::getRegisterName(int regNum
) {
3611 return "unknown register";
3614 #endif // _LIBUNWIND_TARGET_SPARC
3616 #if defined(_LIBUNWIND_TARGET_SPARC64)
3617 /// Registers_sparc64 holds the register state of a thread in a 64-bit
3619 class _LIBUNWIND_HIDDEN Registers_sparc64
{
3621 Registers_sparc64() = default;
3622 Registers_sparc64(const void *registers
);
3624 bool validRegister(int num
) const;
3625 uint64_t getRegister(int num
) const;
3626 void setRegister(int num
, uint64_t value
);
3627 bool validFloatRegister(int num
) const;
3628 double getFloatRegister(int num
) const;
3629 void setFloatRegister(int num
, double value
);
3630 bool validVectorRegister(int num
) const;
3631 v128
getVectorRegister(int num
) const;
3632 void setVectorRegister(int num
, v128 value
);
3633 const char *getRegisterName(int num
);
3635 static constexpr int lastDwarfRegNum() {
3636 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64
;
3638 static int getArch() { return REGISTERS_SPARC64
; }
3640 uint64_t getSP() const { return _registers
.__regs
[UNW_SPARC_O6
] + 2047; }
3641 void setSP(uint64_t value
) { _registers
.__regs
[UNW_SPARC_O6
] = value
- 2047; }
3642 uint64_t getIP() const { return _registers
.__regs
[UNW_SPARC_O7
]; }
3643 void setIP(uint64_t value
) { _registers
.__regs
[UNW_SPARC_O7
] = value
; }
3644 uint64_t getWCookie() const { return _wcookie
; }
3647 struct sparc64_thread_state_t
{
3648 uint64_t __regs
[32];
3651 sparc64_thread_state_t _registers
{};
3652 uint64_t _wcookie
= 0;
3655 inline Registers_sparc64::Registers_sparc64(const void *registers
) {
3656 static_assert((check_fit
<Registers_sparc64
, unw_context_t
>::does_fit
),
3657 "sparc64 registers do not fit into unw_context_t");
3658 memcpy(&_registers
, registers
, sizeof(_registers
));
3660 static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
3664 inline bool Registers_sparc64::validRegister(int regNum
) const {
3665 if (regNum
== UNW_REG_IP
)
3667 if (regNum
== UNW_REG_SP
)
3671 if (regNum
<= UNW_SPARC_I7
)
3676 inline uint64_t Registers_sparc64::getRegister(int regNum
) const {
3677 if (regNum
>= UNW_SPARC_G0
&& regNum
<= UNW_SPARC_I7
)
3678 return _registers
.__regs
[regNum
];
3682 return _registers
.__regs
[UNW_SPARC_O7
];
3684 return _registers
.__regs
[UNW_SPARC_O6
] + 2047;
3686 _LIBUNWIND_ABORT("unsupported sparc64 register");
3689 inline void Registers_sparc64::setRegister(int regNum
, uint64_t value
) {
3690 if (regNum
>= UNW_SPARC_G0
&& regNum
<= UNW_SPARC_I7
) {
3691 _registers
.__regs
[regNum
] = value
;
3697 _registers
.__regs
[UNW_SPARC_O7
] = value
;
3700 _registers
.__regs
[UNW_SPARC_O6
] = value
- 2047;
3703 _LIBUNWIND_ABORT("unsupported sparc64 register");
3706 inline bool Registers_sparc64::validFloatRegister(int) const { return false; }
3708 inline double Registers_sparc64::getFloatRegister(int) const {
3709 _LIBUNWIND_ABORT("no sparc64 float registers");
3712 inline void Registers_sparc64::setFloatRegister(int, double) {
3713 _LIBUNWIND_ABORT("no sparc64 float registers");
3716 inline bool Registers_sparc64::validVectorRegister(int) const { return false; }
3718 inline v128
Registers_sparc64::getVectorRegister(int) const {
3719 _LIBUNWIND_ABORT("no sparc64 vector registers");
3722 inline void Registers_sparc64::setVectorRegister(int, v128
) {
3723 _LIBUNWIND_ABORT("no sparc64 vector registers");
3726 inline const char *Registers_sparc64::getRegisterName(int regNum
) {
3796 return "unknown register";
3799 #endif // _LIBUNWIND_TARGET_SPARC64
3801 #if defined(_LIBUNWIND_TARGET_HEXAGON)
3802 /// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
3804 class _LIBUNWIND_HIDDEN Registers_hexagon
{
3806 Registers_hexagon();
3807 Registers_hexagon(const void *registers
);
3809 bool validRegister(int num
) const;
3810 uint32_t getRegister(int num
) const;
3811 void setRegister(int num
, uint32_t value
);
3812 bool validFloatRegister(int num
) const;
3813 double getFloatRegister(int num
) const;
3814 void setFloatRegister(int num
, double value
);
3815 bool validVectorRegister(int num
) const;
3816 v128
getVectorRegister(int num
) const;
3817 void setVectorRegister(int num
, v128 value
);
3818 const char *getRegisterName(int num
);
3820 static constexpr int lastDwarfRegNum() {
3821 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON
;
3823 static int getArch() { return REGISTERS_HEXAGON
; }
3825 uint32_t getSP() const { return _registers
.__r
[UNW_HEXAGON_R29
]; }
3826 void setSP(uint32_t value
) { _registers
.__r
[UNW_HEXAGON_R29
] = value
; }
3827 uint32_t getIP() const { return _registers
.__r
[UNW_HEXAGON_PC
]; }
3828 void setIP(uint32_t value
) { _registers
.__r
[UNW_HEXAGON_PC
] = value
; }
3831 struct hexagon_thread_state_t
{
3832 unsigned int __r
[35];
3835 hexagon_thread_state_t _registers
;
3838 inline Registers_hexagon::Registers_hexagon(const void *registers
) {
3839 static_assert((check_fit
<Registers_hexagon
, unw_context_t
>::does_fit
),
3840 "hexagon registers do not fit into unw_context_t");
3841 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
3842 sizeof(_registers
));
3845 inline Registers_hexagon::Registers_hexagon() {
3846 memset(&_registers
, 0, sizeof(_registers
));
3849 inline bool Registers_hexagon::validRegister(int regNum
) const {
3850 if (regNum
<= UNW_HEXAGON_R31
)
3855 inline uint32_t Registers_hexagon::getRegister(int regNum
) const {
3856 if (regNum
>= UNW_HEXAGON_R0
&& regNum
<= UNW_HEXAGON_R31
)
3857 return _registers
.__r
[regNum
- UNW_HEXAGON_R0
];
3861 return _registers
.__r
[UNW_HEXAGON_PC
];
3863 return _registers
.__r
[UNW_HEXAGON_R29
];
3865 _LIBUNWIND_ABORT("unsupported hexagon register");
3868 inline void Registers_hexagon::setRegister(int regNum
, uint32_t value
) {
3869 if (regNum
>= UNW_HEXAGON_R0
&& regNum
<= UNW_HEXAGON_R31
) {
3870 _registers
.__r
[regNum
- UNW_HEXAGON_R0
] = value
;
3876 _registers
.__r
[UNW_HEXAGON_PC
] = value
;
3879 _registers
.__r
[UNW_HEXAGON_R29
] = value
;
3882 _LIBUNWIND_ABORT("unsupported hexagon register");
3885 inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {
3889 inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {
3890 _LIBUNWIND_ABORT("hexagon float support not implemented");
3893 inline void Registers_hexagon::setFloatRegister(int /* regNum */,
3894 double /* value */) {
3895 _LIBUNWIND_ABORT("hexagon float support not implemented");
3898 inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {
3902 inline v128
Registers_hexagon::getVectorRegister(int /* regNum */) const {
3903 _LIBUNWIND_ABORT("hexagon vector support not implemented");
3906 inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128
/* value */) {
3907 _LIBUNWIND_ABORT("hexagon vector support not implemented");
3910 inline const char *Registers_hexagon::getRegisterName(int regNum
) {
3912 case UNW_HEXAGON_R0
:
3914 case UNW_HEXAGON_R1
:
3916 case UNW_HEXAGON_R2
:
3918 case UNW_HEXAGON_R3
:
3920 case UNW_HEXAGON_R4
:
3922 case UNW_HEXAGON_R5
:
3924 case UNW_HEXAGON_R6
:
3926 case UNW_HEXAGON_R7
:
3928 case UNW_HEXAGON_R8
:
3930 case UNW_HEXAGON_R9
:
3932 case UNW_HEXAGON_R10
:
3934 case UNW_HEXAGON_R11
:
3936 case UNW_HEXAGON_R12
:
3938 case UNW_HEXAGON_R13
:
3940 case UNW_HEXAGON_R14
:
3942 case UNW_HEXAGON_R15
:
3944 case UNW_HEXAGON_R16
:
3946 case UNW_HEXAGON_R17
:
3948 case UNW_HEXAGON_R18
:
3950 case UNW_HEXAGON_R19
:
3952 case UNW_HEXAGON_R20
:
3954 case UNW_HEXAGON_R21
:
3956 case UNW_HEXAGON_R22
:
3958 case UNW_HEXAGON_R23
:
3960 case UNW_HEXAGON_R24
:
3962 case UNW_HEXAGON_R25
:
3964 case UNW_HEXAGON_R26
:
3966 case UNW_HEXAGON_R27
:
3968 case UNW_HEXAGON_R28
:
3970 case UNW_HEXAGON_R29
:
3972 case UNW_HEXAGON_R30
:
3974 case UNW_HEXAGON_R31
:
3977 return "unknown register";
3981 #endif // _LIBUNWIND_TARGET_HEXAGON
3984 #if defined(_LIBUNWIND_TARGET_RISCV)
3985 /// Registers_riscv holds the register state of a thread in a RISC-V
3988 // This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.
3990 # if __riscv_xlen == 32
3991 typedef uint32_t reg_t
;
3992 # elif __riscv_xlen == 64
3993 typedef uint64_t reg_t
;
3995 # error "Unsupported __riscv_xlen"
3998 # if defined(__riscv_flen)
3999 # if __riscv_flen == 64
4000 typedef double fp_t
;
4001 # elif __riscv_flen == 32
4004 # error "Unsupported __riscv_flen"
4007 // This is just for suppressing undeclared error of fp_t.
4008 typedef double fp_t
;
4011 // Use Max possible width when cross unwinding
4012 typedef uint64_t reg_t
;
4013 typedef double fp_t
;
4014 # define __riscv_xlen 64
4015 # define __riscv_flen 64
4018 /// Registers_riscv holds the register state of a thread.
4019 class _LIBUNWIND_HIDDEN Registers_riscv
{
4022 Registers_riscv(const void *registers
);
4024 bool validRegister(int num
) const;
4025 reg_t
getRegister(int num
) const;
4026 void setRegister(int num
, reg_t value
);
4027 bool validFloatRegister(int num
) const;
4028 fp_t
getFloatRegister(int num
) const;
4029 void setFloatRegister(int num
, fp_t value
);
4030 bool validVectorRegister(int num
) const;
4031 v128
getVectorRegister(int num
) const;
4032 void setVectorRegister(int num
, v128 value
);
4033 static const char *getRegisterName(int num
);
4035 static constexpr int lastDwarfRegNum() {
4036 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV
;
4038 static int getArch() { return REGISTERS_RISCV
; }
4040 reg_t
getSP() const { return _registers
[2]; }
4041 void setSP(reg_t value
) { _registers
[2] = value
; }
4042 reg_t
getIP() const { return _registers
[0]; }
4043 void setIP(reg_t value
) { _registers
[0] = value
; }
4046 // _registers[0] holds the pc
4047 reg_t _registers
[32];
4048 # if defined(__riscv_flen)
4053 inline Registers_riscv::Registers_riscv(const void *registers
) {
4054 static_assert((check_fit
<Registers_riscv
, unw_context_t
>::does_fit
),
4055 "riscv registers do not fit into unw_context_t");
4056 memcpy(&_registers
, registers
, sizeof(_registers
));
4057 # if __riscv_xlen == 32
4058 static_assert(sizeof(_registers
) == 0x80,
4059 "expected float registers to be at offset 128");
4060 # elif __riscv_xlen == 64
4061 static_assert(sizeof(_registers
) == 0x100,
4062 "expected float registers to be at offset 256");
4064 # error "Unexpected float registers."
4067 # if defined(__riscv_flen)
4069 static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
4074 inline Registers_riscv::Registers_riscv() {
4075 memset(&_registers
, 0, sizeof(_registers
));
4076 # if defined(__riscv_flen)
4077 memset(&_floats
, 0, sizeof(_floats
));
4081 inline bool Registers_riscv::validRegister(int regNum
) const {
4082 if (regNum
== UNW_REG_IP
)
4084 if (regNum
== UNW_REG_SP
)
4088 if (regNum
== UNW_RISCV_VLENB
)
4090 if (regNum
> UNW_RISCV_F31
)
4095 inline reg_t
Registers_riscv::getRegister(int regNum
) const {
4096 if (regNum
== UNW_REG_IP
)
4097 return _registers
[0];
4098 if (regNum
== UNW_REG_SP
)
4099 return _registers
[2];
4100 if (regNum
== UNW_RISCV_X0
)
4102 if ((regNum
> 0) && (regNum
< 32))
4103 return _registers
[regNum
];
4104 if (regNum
== UNW_RISCV_VLENB
) {
4106 __asm__("csrr %0, 0xC22" : "=r"(vlenb
));
4109 _LIBUNWIND_ABORT("unsupported riscv register");
4112 inline void Registers_riscv::setRegister(int regNum
, reg_t value
) {
4113 if (regNum
== UNW_REG_IP
)
4114 _registers
[0] = value
;
4115 else if (regNum
== UNW_REG_SP
)
4116 _registers
[2] = value
;
4117 else if (regNum
== UNW_RISCV_X0
)
4118 /* x0 is hardwired to zero */
4120 else if ((regNum
> 0) && (regNum
< 32))
4121 _registers
[regNum
] = value
;
4123 _LIBUNWIND_ABORT("unsupported riscv register");
4126 inline const char *Registers_riscv::getRegisterName(int regNum
) {
4260 case UNW_RISCV_VLENB
:
4263 return "unknown register";
4267 inline bool Registers_riscv::validFloatRegister(int regNum
) const {
4268 # if defined(__riscv_flen)
4269 if (regNum
< UNW_RISCV_F0
)
4271 if (regNum
> UNW_RISCV_F31
)
4280 inline fp_t
Registers_riscv::getFloatRegister(int regNum
) const {
4281 # if defined(__riscv_flen)
4282 assert(validFloatRegister(regNum
));
4283 return _floats
[regNum
- UNW_RISCV_F0
];
4286 _LIBUNWIND_ABORT("libunwind not built with float support");
4290 inline void Registers_riscv::setFloatRegister(int regNum
, fp_t value
) {
4291 # if defined(__riscv_flen)
4292 assert(validFloatRegister(regNum
));
4293 _floats
[regNum
- UNW_RISCV_F0
] = value
;
4297 _LIBUNWIND_ABORT("libunwind not built with float support");
4301 inline bool Registers_riscv::validVectorRegister(int) const {
4305 inline v128
Registers_riscv::getVectorRegister(int) const {
4306 _LIBUNWIND_ABORT("no riscv vector register support yet");
4309 inline void Registers_riscv::setVectorRegister(int, v128
) {
4310 _LIBUNWIND_ABORT("no riscv vector register support yet");
4312 #endif // _LIBUNWIND_TARGET_RISCV
4314 #if defined(_LIBUNWIND_TARGET_VE)
4315 /// Registers_ve holds the register state of a thread in a VE process.
4316 class _LIBUNWIND_HIDDEN Registers_ve
{
4319 Registers_ve(const void *registers
);
4321 bool validRegister(int num
) const;
4322 uint64_t getRegister(int num
) const;
4323 void setRegister(int num
, uint64_t value
);
4324 bool validFloatRegister(int num
) const;
4325 double getFloatRegister(int num
) const;
4326 void setFloatRegister(int num
, double value
);
4327 bool validVectorRegister(int num
) const;
4328 v128
getVectorRegister(int num
) const;
4329 void setVectorRegister(int num
, v128 value
);
4330 static const char *getRegisterName(int num
);
4332 static constexpr int lastDwarfRegNum() {
4333 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE
;
4335 static int getArch() { return REGISTERS_VE
; }
4337 uint64_t getSP() const { return _registers
.__s
[11]; }
4338 void setSP(uint64_t value
) { _registers
.__s
[11] = value
; }
4339 uint64_t getIP() const { return _registers
.__ic
; }
4340 void setIP(uint64_t value
) { _registers
.__ic
= value
; }
4343 // FIXME: Need to store not only scalar registers but also vector and vector
4344 // mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes
4345 // 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for
4346 // SjLj exception support only, so Registers_ve is not implemented completely.
4347 struct ve_thread_state_t
{
4348 uint64_t __s
[64]; // s0-s64
4349 uint64_t __ic
; // Instruction counter (IC)
4350 uint64_t __vixr
; // Vector Index Register
4351 uint64_t __vl
; // Vector Length Register
4354 ve_thread_state_t _registers
; // total 67 registers
4356 // Currently no vector register is preserved.
4359 inline Registers_ve::Registers_ve(const void *registers
) {
4360 static_assert((check_fit
<Registers_ve
, unw_context_t
>::does_fit
),
4361 "ve registers do not fit into unw_context_t");
4362 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
4363 sizeof(_registers
));
4364 static_assert(sizeof(_registers
) == 536,
4365 "expected vector register offset to be 536");
4368 inline Registers_ve::Registers_ve() {
4369 memset(&_registers
, 0, sizeof(_registers
));
4372 inline bool Registers_ve::validRegister(int regNum
) const {
4373 if (regNum
>= UNW_VE_S0
&& regNum
<= UNW_VE_S63
)
4387 inline uint64_t Registers_ve::getRegister(int regNum
) const {
4388 if (regNum
>= UNW_VE_S0
&& regNum
<= UNW_VE_S63
)
4389 return _registers
.__s
[regNum
- UNW_VE_S0
];
4393 return _registers
.__ic
;
4395 return _registers
.__s
[11];
4397 return _registers
.__vixr
;
4399 return _registers
.__vl
;
4401 _LIBUNWIND_ABORT("unsupported ve register");
4404 inline void Registers_ve::setRegister(int regNum
, uint64_t value
) {
4405 if (regNum
>= UNW_VE_S0
&& regNum
<= UNW_VE_S63
) {
4406 _registers
.__s
[regNum
- UNW_VE_S0
] = value
;
4412 _registers
.__ic
= value
;
4415 _registers
.__s
[11] = value
;
4418 _registers
.__vixr
= value
;
4421 _registers
.__vl
= value
;
4424 _LIBUNWIND_ABORT("unsupported ve register");
4427 inline bool Registers_ve::validFloatRegister(int /* regNum */) const {
4431 inline double Registers_ve::getFloatRegister(int /* regNum */) const {
4432 _LIBUNWIND_ABORT("VE doesn't have float registers");
4435 inline void Registers_ve::setFloatRegister(int /* regNum */,
4436 double /* value */) {
4437 _LIBUNWIND_ABORT("VE doesn't have float registers");
4440 inline bool Registers_ve::validVectorRegister(int /* regNum */) const {
4444 inline v128
Registers_ve::getVectorRegister(int /* regNum */) const {
4445 _LIBUNWIND_ABORT("VE vector support not implemented");
4448 inline void Registers_ve::setVectorRegister(int /* regNum */,
4450 _LIBUNWIND_ABORT("VE vector support not implemented");
4453 inline const char *Registers_ve::getRegisterName(int regNum
) {
4752 return "unknown register";
4754 #endif // _LIBUNWIND_TARGET_VE
4756 #if defined(_LIBUNWIND_TARGET_S390X)
4757 /// Registers_s390x holds the register state of a thread in a
4758 /// 64-bit Linux on IBM zSystems process.
4759 class _LIBUNWIND_HIDDEN Registers_s390x
{
4762 Registers_s390x(const void *registers
);
4764 bool validRegister(int num
) const;
4765 uint64_t getRegister(int num
) const;
4766 void setRegister(int num
, uint64_t value
);
4767 bool validFloatRegister(int num
) const;
4768 double getFloatRegister(int num
) const;
4769 void setFloatRegister(int num
, double value
);
4770 bool validVectorRegister(int num
) const;
4771 v128
getVectorRegister(int num
) const;
4772 void setVectorRegister(int num
, v128 value
);
4773 static const char *getRegisterName(int num
);
4775 static constexpr int lastDwarfRegNum() {
4776 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X
;
4778 static int getArch() { return REGISTERS_S390X
; }
4780 uint64_t getSP() const { return _registers
.__gpr
[15]; }
4781 void setSP(uint64_t value
) { _registers
.__gpr
[15] = value
; }
4782 uint64_t getIP() const { return _registers
.__pswa
; }
4783 void setIP(uint64_t value
) { _registers
.__pswa
= value
; }
4786 struct s390x_thread_state_t
{
4787 uint64_t __pswm
; // Problem Status Word: Mask
4788 uint64_t __pswa
; // Problem Status Word: Address (PC)
4789 uint64_t __gpr
[16]; // General Purpose Registers
4790 double __fpr
[16]; // Floating-Point Registers
4793 s390x_thread_state_t _registers
;
4796 inline Registers_s390x::Registers_s390x(const void *registers
) {
4797 static_assert((check_fit
<Registers_s390x
, unw_context_t
>::does_fit
),
4798 "s390x registers do not fit into unw_context_t");
4799 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
4800 sizeof(_registers
));
4803 inline Registers_s390x::Registers_s390x() {
4804 memset(&_registers
, 0, sizeof(_registers
));
4807 inline bool Registers_s390x::validRegister(int regNum
) const {
4809 case UNW_S390X_PSWM
:
4810 case UNW_S390X_PSWA
:
4816 if (regNum
>= UNW_S390X_R0
&& regNum
<= UNW_S390X_R15
)
4822 inline uint64_t Registers_s390x::getRegister(int regNum
) const {
4823 if (regNum
>= UNW_S390X_R0
&& regNum
<= UNW_S390X_R15
)
4824 return _registers
.__gpr
[regNum
- UNW_S390X_R0
];
4827 case UNW_S390X_PSWM
:
4828 return _registers
.__pswm
;
4829 case UNW_S390X_PSWA
:
4831 return _registers
.__pswa
;
4833 return _registers
.__gpr
[15];
4835 _LIBUNWIND_ABORT("unsupported s390x register");
4838 inline void Registers_s390x::setRegister(int regNum
, uint64_t value
) {
4839 if (regNum
>= UNW_S390X_R0
&& regNum
<= UNW_S390X_R15
) {
4840 _registers
.__gpr
[regNum
- UNW_S390X_R0
] = value
;
4845 case UNW_S390X_PSWM
:
4846 _registers
.__pswm
= value
;
4848 case UNW_S390X_PSWA
:
4850 _registers
.__pswa
= value
;
4853 _registers
.__gpr
[15] = value
;
4856 _LIBUNWIND_ABORT("unsupported s390x register");
4859 inline bool Registers_s390x::validFloatRegister(int regNum
) const {
4860 return regNum
>= UNW_S390X_F0
&& regNum
<= UNW_S390X_F15
;
4863 inline double Registers_s390x::getFloatRegister(int regNum
) const {
4864 // NOTE: FPR DWARF register numbers are not consecutive.
4867 return _registers
.__fpr
[0];
4869 return _registers
.__fpr
[1];
4871 return _registers
.__fpr
[2];
4873 return _registers
.__fpr
[3];
4875 return _registers
.__fpr
[4];
4877 return _registers
.__fpr
[5];
4879 return _registers
.__fpr
[6];
4881 return _registers
.__fpr
[7];
4883 return _registers
.__fpr
[8];
4885 return _registers
.__fpr
[9];
4887 return _registers
.__fpr
[10];
4889 return _registers
.__fpr
[11];
4891 return _registers
.__fpr
[12];
4893 return _registers
.__fpr
[13];
4895 return _registers
.__fpr
[14];
4897 return _registers
.__fpr
[15];
4899 _LIBUNWIND_ABORT("unsupported s390x register");
4902 inline void Registers_s390x::setFloatRegister(int regNum
, double value
) {
4903 // NOTE: FPR DWARF register numbers are not consecutive.
4906 _registers
.__fpr
[0] = value
;
4909 _registers
.__fpr
[1] = value
;
4912 _registers
.__fpr
[2] = value
;
4915 _registers
.__fpr
[3] = value
;
4918 _registers
.__fpr
[4] = value
;
4921 _registers
.__fpr
[5] = value
;
4924 _registers
.__fpr
[6] = value
;
4927 _registers
.__fpr
[7] = value
;
4930 _registers
.__fpr
[8] = value
;
4933 _registers
.__fpr
[9] = value
;
4936 _registers
.__fpr
[10] = value
;
4939 _registers
.__fpr
[11] = value
;
4942 _registers
.__fpr
[12] = value
;
4945 _registers
.__fpr
[13] = value
;
4948 _registers
.__fpr
[14] = value
;
4951 _registers
.__fpr
[15] = value
;
4954 _LIBUNWIND_ABORT("unsupported s390x register");
4957 inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
4961 inline v128
Registers_s390x::getVectorRegister(int /*regNum*/) const {
4962 _LIBUNWIND_ABORT("s390x vector support not implemented");
4965 inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128
/*value*/) {
4966 _LIBUNWIND_ABORT("s390x vector support not implemented");
4969 inline const char *Registers_s390x::getRegisterName(int regNum
) {
5040 return "unknown register";
5042 #endif // _LIBUNWIND_TARGET_S390X
5044 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
5045 /// Registers_loongarch holds the register state of a thread in a 64-bit
5046 /// LoongArch process.
5047 class _LIBUNWIND_HIDDEN Registers_loongarch
{
5049 Registers_loongarch();
5050 Registers_loongarch(const void *registers
);
5052 bool validRegister(int num
) const;
5053 uint64_t getRegister(int num
) const;
5054 void setRegister(int num
, uint64_t value
);
5055 bool validFloatRegister(int num
) const;
5056 double getFloatRegister(int num
) const;
5057 void setFloatRegister(int num
, double value
);
5058 bool validVectorRegister(int num
) const;
5059 v128
getVectorRegister(int num
) const;
5060 void setVectorRegister(int num
, v128 value
);
5061 static const char *getRegisterName(int num
);
5063 static constexpr int lastDwarfRegNum() {
5064 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH
;
5066 static int getArch() { return REGISTERS_LOONGARCH
; }
5068 uint64_t getSP() const { return _registers
.__r
[3]; }
5069 void setSP(uint64_t value
) { _registers
.__r
[3] = value
; }
5070 uint64_t getIP() const { return _registers
.__pc
; }
5071 void setIP(uint64_t value
) { _registers
.__pc
= value
; }
5074 struct loongarch_thread_state_t
{
5079 loongarch_thread_state_t _registers
;
5080 #if __loongarch_frlen == 64
5085 inline Registers_loongarch::Registers_loongarch(const void *registers
) {
5086 static_assert((check_fit
<Registers_loongarch
, unw_context_t
>::does_fit
),
5087 "loongarch registers do not fit into unw_context_t");
5088 memcpy(&_registers
, registers
, sizeof(_registers
));
5089 static_assert(sizeof(_registers
) == 0x108,
5090 "expected float registers to be at offset 264");
5091 #if __loongarch_frlen == 64
5092 memcpy(_floats
, static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
5097 inline Registers_loongarch::Registers_loongarch() {
5098 memset(&_registers
, 0, sizeof(_registers
));
5099 #if __loongarch_frlen == 64
5100 memset(&_floats
, 0, sizeof(_floats
));
5104 inline bool Registers_loongarch::validRegister(int regNum
) const {
5105 if (regNum
== UNW_REG_IP
|| regNum
== UNW_REG_SP
)
5107 if (regNum
< 0 || regNum
> UNW_LOONGARCH_F31
)
5112 inline uint64_t Registers_loongarch::getRegister(int regNum
) const {
5113 if (regNum
>= UNW_LOONGARCH_R0
&& regNum
<= UNW_LOONGARCH_R31
)
5114 return _registers
.__r
[regNum
- UNW_LOONGARCH_R0
];
5116 if (regNum
== UNW_REG_IP
)
5117 return _registers
.__pc
;
5118 if (regNum
== UNW_REG_SP
)
5119 return _registers
.__r
[3];
5120 _LIBUNWIND_ABORT("unsupported loongarch register");
5123 inline void Registers_loongarch::setRegister(int regNum
, uint64_t value
) {
5124 if (regNum
>= UNW_LOONGARCH_R0
&& regNum
<= UNW_LOONGARCH_R31
)
5125 _registers
.__r
[regNum
- UNW_LOONGARCH_R0
] = value
;
5126 else if (regNum
== UNW_REG_IP
)
5127 _registers
.__pc
= value
;
5128 else if (regNum
== UNW_REG_SP
)
5129 _registers
.__r
[3] = value
;
5131 _LIBUNWIND_ABORT("unsupported loongarch register");
5134 inline const char *Registers_loongarch::getRegisterName(int regNum
) {
5140 case UNW_LOONGARCH_R0
:
5142 case UNW_LOONGARCH_R1
:
5144 case UNW_LOONGARCH_R2
:
5146 case UNW_LOONGARCH_R3
:
5148 case UNW_LOONGARCH_R4
:
5150 case UNW_LOONGARCH_R5
:
5152 case UNW_LOONGARCH_R6
:
5154 case UNW_LOONGARCH_R7
:
5156 case UNW_LOONGARCH_R8
:
5158 case UNW_LOONGARCH_R9
:
5160 case UNW_LOONGARCH_R10
:
5162 case UNW_LOONGARCH_R11
:
5164 case UNW_LOONGARCH_R12
:
5166 case UNW_LOONGARCH_R13
:
5168 case UNW_LOONGARCH_R14
:
5170 case UNW_LOONGARCH_R15
:
5172 case UNW_LOONGARCH_R16
:
5174 case UNW_LOONGARCH_R17
:
5176 case UNW_LOONGARCH_R18
:
5178 case UNW_LOONGARCH_R19
:
5180 case UNW_LOONGARCH_R20
:
5182 case UNW_LOONGARCH_R21
:
5184 case UNW_LOONGARCH_R22
:
5186 case UNW_LOONGARCH_R23
:
5188 case UNW_LOONGARCH_R24
:
5190 case UNW_LOONGARCH_R25
:
5192 case UNW_LOONGARCH_R26
:
5194 case UNW_LOONGARCH_R27
:
5196 case UNW_LOONGARCH_R28
:
5198 case UNW_LOONGARCH_R29
:
5200 case UNW_LOONGARCH_R30
:
5202 case UNW_LOONGARCH_R31
:
5204 case UNW_LOONGARCH_F0
:
5206 case UNW_LOONGARCH_F1
:
5208 case UNW_LOONGARCH_F2
:
5210 case UNW_LOONGARCH_F3
:
5212 case UNW_LOONGARCH_F4
:
5214 case UNW_LOONGARCH_F5
:
5216 case UNW_LOONGARCH_F6
:
5218 case UNW_LOONGARCH_F7
:
5220 case UNW_LOONGARCH_F8
:
5222 case UNW_LOONGARCH_F9
:
5224 case UNW_LOONGARCH_F10
:
5226 case UNW_LOONGARCH_F11
:
5228 case UNW_LOONGARCH_F12
:
5230 case UNW_LOONGARCH_F13
:
5232 case UNW_LOONGARCH_F14
:
5234 case UNW_LOONGARCH_F15
:
5236 case UNW_LOONGARCH_F16
:
5238 case UNW_LOONGARCH_F17
:
5240 case UNW_LOONGARCH_F18
:
5242 case UNW_LOONGARCH_F19
:
5244 case UNW_LOONGARCH_F20
:
5246 case UNW_LOONGARCH_F21
:
5248 case UNW_LOONGARCH_F22
:
5250 case UNW_LOONGARCH_F23
:
5252 case UNW_LOONGARCH_F24
:
5254 case UNW_LOONGARCH_F25
:
5256 case UNW_LOONGARCH_F26
:
5258 case UNW_LOONGARCH_F27
:
5260 case UNW_LOONGARCH_F28
:
5262 case UNW_LOONGARCH_F29
:
5264 case UNW_LOONGARCH_F30
:
5266 case UNW_LOONGARCH_F31
:
5269 return "unknown register";
5273 inline bool Registers_loongarch::validFloatRegister(int regNum
) const {
5274 if (regNum
< UNW_LOONGARCH_F0
|| regNum
> UNW_LOONGARCH_F31
)
5279 inline double Registers_loongarch::getFloatRegister(int regNum
) const {
5280 #if __loongarch_frlen == 64
5281 assert(validFloatRegister(regNum
));
5282 return _floats
[regNum
- UNW_LOONGARCH_F0
];
5284 _LIBUNWIND_ABORT("libunwind not built with float support");
5288 inline void Registers_loongarch::setFloatRegister(int regNum
, double value
) {
5289 #if __loongarch_frlen == 64
5290 assert(validFloatRegister(regNum
));
5291 _floats
[regNum
- UNW_LOONGARCH_F0
] = value
;
5293 _LIBUNWIND_ABORT("libunwind not built with float support");
5297 inline bool Registers_loongarch::validVectorRegister(int) const {
5301 inline v128
Registers_loongarch::getVectorRegister(int) const {
5302 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5305 inline void Registers_loongarch::setVectorRegister(int, v128
) {
5306 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5308 #endif //_LIBUNWIND_TARGET_LOONGARCH
5310 } // namespace libunwind
5312 #endif // __REGISTERS_HPP__