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
; }
622 uint64_t getLR() const { return _registers
.__lr
; }
623 void setLR(uint32_t value
) { _registers
.__lr
= value
; }
626 struct ppc_thread_state_t
{
627 unsigned int __srr0
; /* Instruction address register (PC) */
628 unsigned int __srr1
; /* Machine state register (supervisor) */
661 unsigned int __cr
; /* Condition register */
662 unsigned int __xer
; /* User's integer exception register */
663 unsigned int __lr
; /* Link register */
664 unsigned int __ctr
; /* Count register */
665 unsigned int __mq
; /* MQ register (601 only) */
666 unsigned int __vrsave
; /* Vector Save Register */
669 struct ppc_float_state_t
{
672 unsigned int __fpscr_pad
; /* fpscr is 64 bits, 32 bits of rubbish */
673 unsigned int __fpscr
; /* floating point status register */
676 ppc_thread_state_t _registers
;
677 ppc_float_state_t _floatRegisters
;
678 v128 _vectorRegisters
[32]; // offset 424
681 inline Registers_ppc::Registers_ppc(const void *registers
) {
682 static_assert((check_fit
<Registers_ppc
, unw_context_t
>::does_fit
),
683 "ppc registers do not fit into unw_context_t");
684 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
686 static_assert(sizeof(ppc_thread_state_t
) == 160,
687 "expected float register offset to be 160");
688 memcpy(&_floatRegisters
,
689 static_cast<const uint8_t *>(registers
) + sizeof(ppc_thread_state_t
),
690 sizeof(_floatRegisters
));
691 static_assert(sizeof(ppc_thread_state_t
) + sizeof(ppc_float_state_t
) == 424,
692 "expected vector register offset to be 424 bytes");
693 memcpy(_vectorRegisters
,
694 static_cast<const uint8_t *>(registers
) + sizeof(ppc_thread_state_t
) +
695 sizeof(ppc_float_state_t
),
696 sizeof(_vectorRegisters
));
699 inline Registers_ppc::Registers_ppc() {
700 memset(&_registers
, 0, sizeof(_registers
));
701 memset(&_floatRegisters
, 0, sizeof(_floatRegisters
));
702 memset(&_vectorRegisters
, 0, sizeof(_vectorRegisters
));
705 inline bool Registers_ppc::validRegister(int regNum
) const {
706 if (regNum
== UNW_REG_IP
)
708 if (regNum
== UNW_REG_SP
)
710 if (regNum
== UNW_PPC_VRSAVE
)
714 if (regNum
<= UNW_PPC_R31
)
716 if (regNum
== UNW_PPC_MQ
)
718 if (regNum
== UNW_PPC_LR
)
720 if (regNum
== UNW_PPC_CTR
)
722 if ((UNW_PPC_CR0
<= regNum
) && (regNum
<= UNW_PPC_CR7
))
727 inline uint32_t Registers_ppc::getRegister(int regNum
) const {
730 return _registers
.__srr0
;
732 return _registers
.__r1
;
734 return _registers
.__r0
;
736 return _registers
.__r1
;
738 return _registers
.__r2
;
740 return _registers
.__r3
;
742 return _registers
.__r4
;
744 return _registers
.__r5
;
746 return _registers
.__r6
;
748 return _registers
.__r7
;
750 return _registers
.__r8
;
752 return _registers
.__r9
;
754 return _registers
.__r10
;
756 return _registers
.__r11
;
758 return _registers
.__r12
;
760 return _registers
.__r13
;
762 return _registers
.__r14
;
764 return _registers
.__r15
;
766 return _registers
.__r16
;
768 return _registers
.__r17
;
770 return _registers
.__r18
;
772 return _registers
.__r19
;
774 return _registers
.__r20
;
776 return _registers
.__r21
;
778 return _registers
.__r22
;
780 return _registers
.__r23
;
782 return _registers
.__r24
;
784 return _registers
.__r25
;
786 return _registers
.__r26
;
788 return _registers
.__r27
;
790 return _registers
.__r28
;
792 return _registers
.__r29
;
794 return _registers
.__r30
;
796 return _registers
.__r31
;
798 return _registers
.__lr
;
800 return (_registers
.__cr
& 0xF0000000);
802 return (_registers
.__cr
& 0x0F000000);
804 return (_registers
.__cr
& 0x00F00000);
806 return (_registers
.__cr
& 0x000F0000);
808 return (_registers
.__cr
& 0x0000F000);
810 return (_registers
.__cr
& 0x00000F00);
812 return (_registers
.__cr
& 0x000000F0);
814 return (_registers
.__cr
& 0x0000000F);
816 return _registers
.__vrsave
;
818 _LIBUNWIND_ABORT("unsupported ppc register");
821 inline void Registers_ppc::setRegister(int regNum
, uint32_t value
) {
822 //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
825 _registers
.__srr0
= value
;
828 _registers
.__r1
= value
;
831 _registers
.__r0
= value
;
834 _registers
.__r1
= value
;
837 _registers
.__r2
= value
;
840 _registers
.__r3
= value
;
843 _registers
.__r4
= value
;
846 _registers
.__r5
= value
;
849 _registers
.__r6
= value
;
852 _registers
.__r7
= value
;
855 _registers
.__r8
= value
;
858 _registers
.__r9
= value
;
861 _registers
.__r10
= value
;
864 _registers
.__r11
= value
;
867 _registers
.__r12
= value
;
870 _registers
.__r13
= value
;
873 _registers
.__r14
= value
;
876 _registers
.__r15
= value
;
879 _registers
.__r16
= value
;
882 _registers
.__r17
= value
;
885 _registers
.__r18
= value
;
888 _registers
.__r19
= value
;
891 _registers
.__r20
= value
;
894 _registers
.__r21
= value
;
897 _registers
.__r22
= value
;
900 _registers
.__r23
= value
;
903 _registers
.__r24
= value
;
906 _registers
.__r25
= value
;
909 _registers
.__r26
= value
;
912 _registers
.__r27
= value
;
915 _registers
.__r28
= value
;
918 _registers
.__r29
= value
;
921 _registers
.__r30
= value
;
924 _registers
.__r31
= value
;
927 _registers
.__mq
= value
;
930 _registers
.__lr
= value
;
933 _registers
.__ctr
= value
;
936 _registers
.__cr
&= 0x0FFFFFFF;
937 _registers
.__cr
|= (value
& 0xF0000000);
940 _registers
.__cr
&= 0xF0FFFFFF;
941 _registers
.__cr
|= (value
& 0x0F000000);
944 _registers
.__cr
&= 0xFF0FFFFF;
945 _registers
.__cr
|= (value
& 0x00F00000);
948 _registers
.__cr
&= 0xFFF0FFFF;
949 _registers
.__cr
|= (value
& 0x000F0000);
952 _registers
.__cr
&= 0xFFFF0FFF;
953 _registers
.__cr
|= (value
& 0x0000F000);
956 _registers
.__cr
&= 0xFFFFF0FF;
957 _registers
.__cr
|= (value
& 0x00000F00);
960 _registers
.__cr
&= 0xFFFFFF0F;
961 _registers
.__cr
|= (value
& 0x000000F0);
964 _registers
.__cr
&= 0xFFFFFFF0;
965 _registers
.__cr
|= (value
& 0x0000000F);
968 _registers
.__vrsave
= value
;
973 _registers
.__xer
= value
;
977 case UNW_PPC_SPEFSCR
:
981 _LIBUNWIND_ABORT("unsupported ppc register");
984 inline bool Registers_ppc::validFloatRegister(int regNum
) const {
985 if (regNum
< UNW_PPC_F0
)
987 if (regNum
> UNW_PPC_F31
)
992 inline double Registers_ppc::getFloatRegister(int regNum
) const {
993 assert(validFloatRegister(regNum
));
994 return _floatRegisters
.__fpregs
[regNum
- UNW_PPC_F0
];
997 inline void Registers_ppc::setFloatRegister(int regNum
, double value
) {
998 assert(validFloatRegister(regNum
));
999 _floatRegisters
.__fpregs
[regNum
- UNW_PPC_F0
] = value
;
1002 inline bool Registers_ppc::validVectorRegister(int regNum
) const {
1003 if (regNum
< UNW_PPC_V0
)
1005 if (regNum
> UNW_PPC_V31
)
1010 inline v128
Registers_ppc::getVectorRegister(int regNum
) const {
1011 assert(validVectorRegister(regNum
));
1012 v128 result
= _vectorRegisters
[regNum
- UNW_PPC_V0
];
1016 inline void Registers_ppc::setVectorRegister(int regNum
, v128 value
) {
1017 assert(validVectorRegister(regNum
));
1018 _vectorRegisters
[regNum
- UNW_PPC_V0
] = value
;
1021 inline const char *Registers_ppc::getRegisterName(int regNum
) {
1158 return "unknown register";
1162 #endif // _LIBUNWIND_TARGET_PPC
1164 #if defined(_LIBUNWIND_TARGET_PPC64)
1165 /// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
1167 class _LIBUNWIND_HIDDEN Registers_ppc64
{
1170 Registers_ppc64(const void *registers
);
1172 bool validRegister(int num
) const;
1173 uint64_t getRegister(int num
) const;
1174 void setRegister(int num
, uint64_t value
);
1175 bool validFloatRegister(int num
) const;
1176 double getFloatRegister(int num
) const;
1177 void setFloatRegister(int num
, double value
);
1178 bool validVectorRegister(int num
) const;
1179 v128
getVectorRegister(int num
) const;
1180 void setVectorRegister(int num
, v128 value
);
1181 static const char *getRegisterName(int num
);
1183 static constexpr int lastDwarfRegNum() {
1184 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64
;
1186 static int getArch() { return REGISTERS_PPC64
; }
1188 uint64_t getSP() const { return _registers
.__r1
; }
1189 void setSP(uint64_t value
) { _registers
.__r1
= value
; }
1190 uint64_t getIP() const { return _registers
.__srr0
; }
1191 void setIP(uint64_t value
) { _registers
.__srr0
= value
; }
1192 uint64_t getCR() const { return _registers
.__cr
; }
1193 void setCR(uint64_t value
) { _registers
.__cr
= value
; }
1194 uint64_t getLR() const { return _registers
.__lr
; }
1195 void setLR(uint64_t value
) { _registers
.__lr
= value
; }
1198 struct ppc64_thread_state_t
{
1199 uint64_t __srr0
; // Instruction address register (PC)
1200 uint64_t __srr1
; // Machine state register (supervisor)
1233 uint64_t __cr
; // Condition register
1234 uint64_t __xer
; // User's integer exception register
1235 uint64_t __lr
; // Link register
1236 uint64_t __ctr
; // Count register
1237 uint64_t __vrsave
; // Vector Save Register
1248 ppc64_thread_state_t _registers
;
1249 ppc64_vsr_t _vectorScalarRegisters
[64];
1251 static int getVectorRegNum(int num
);
1254 inline Registers_ppc64::Registers_ppc64(const void *registers
) {
1255 static_assert((check_fit
<Registers_ppc64
, unw_context_t
>::does_fit
),
1256 "ppc64 registers do not fit into unw_context_t");
1257 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
1258 sizeof(_registers
));
1259 static_assert(sizeof(_registers
) == 312,
1260 "expected vector scalar register offset to be 312");
1261 memcpy(&_vectorScalarRegisters
,
1262 static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
1263 sizeof(_vectorScalarRegisters
));
1264 static_assert(sizeof(_registers
) +
1265 sizeof(_vectorScalarRegisters
) == 1336,
1266 "expected vector register offset to be 1336 bytes");
1269 inline Registers_ppc64::Registers_ppc64() {
1270 memset(&_registers
, 0, sizeof(_registers
));
1271 memset(&_vectorScalarRegisters
, 0, sizeof(_vectorScalarRegisters
));
1274 inline bool Registers_ppc64::validRegister(int regNum
) const {
1281 case UNW_PPC64_VRSAVE
:
1285 if (regNum
>= UNW_PPC64_R0
&& regNum
<= UNW_PPC64_R31
)
1287 if (regNum
>= UNW_PPC64_CR0
&& regNum
<= UNW_PPC64_CR7
)
1293 inline uint64_t Registers_ppc64::getRegister(int regNum
) const {
1296 return _registers
.__srr0
;
1298 return _registers
.__r0
;
1301 return _registers
.__r1
;
1303 return _registers
.__r2
;
1305 return _registers
.__r3
;
1307 return _registers
.__r4
;
1309 return _registers
.__r5
;
1311 return _registers
.__r6
;
1313 return _registers
.__r7
;
1315 return _registers
.__r8
;
1317 return _registers
.__r9
;
1319 return _registers
.__r10
;
1321 return _registers
.__r11
;
1323 return _registers
.__r12
;
1325 return _registers
.__r13
;
1327 return _registers
.__r14
;
1329 return _registers
.__r15
;
1331 return _registers
.__r16
;
1333 return _registers
.__r17
;
1335 return _registers
.__r18
;
1337 return _registers
.__r19
;
1339 return _registers
.__r20
;
1341 return _registers
.__r21
;
1343 return _registers
.__r22
;
1345 return _registers
.__r23
;
1347 return _registers
.__r24
;
1349 return _registers
.__r25
;
1351 return _registers
.__r26
;
1353 return _registers
.__r27
;
1355 return _registers
.__r28
;
1357 return _registers
.__r29
;
1359 return _registers
.__r30
;
1361 return _registers
.__r31
;
1363 return (_registers
.__cr
& 0xF0000000);
1365 return (_registers
.__cr
& 0x0F000000);
1367 return (_registers
.__cr
& 0x00F00000);
1369 return (_registers
.__cr
& 0x000F0000);
1371 return (_registers
.__cr
& 0x0000F000);
1373 return (_registers
.__cr
& 0x00000F00);
1375 return (_registers
.__cr
& 0x000000F0);
1377 return (_registers
.__cr
& 0x0000000F);
1379 return _registers
.__xer
;
1381 return _registers
.__lr
;
1383 return _registers
.__ctr
;
1384 case UNW_PPC64_VRSAVE
:
1385 return _registers
.__vrsave
;
1387 _LIBUNWIND_ABORT("unsupported ppc64 register");
1390 inline void Registers_ppc64::setRegister(int regNum
, uint64_t value
) {
1393 _registers
.__srr0
= value
;
1396 _registers
.__r0
= value
;
1400 _registers
.__r1
= value
;
1403 _registers
.__r2
= value
;
1406 _registers
.__r3
= value
;
1409 _registers
.__r4
= value
;
1412 _registers
.__r5
= value
;
1415 _registers
.__r6
= value
;
1418 _registers
.__r7
= value
;
1421 _registers
.__r8
= value
;
1424 _registers
.__r9
= value
;
1427 _registers
.__r10
= value
;
1430 _registers
.__r11
= value
;
1433 _registers
.__r12
= value
;
1436 _registers
.__r13
= value
;
1439 _registers
.__r14
= value
;
1442 _registers
.__r15
= value
;
1445 _registers
.__r16
= value
;
1448 _registers
.__r17
= value
;
1451 _registers
.__r18
= value
;
1454 _registers
.__r19
= value
;
1457 _registers
.__r20
= value
;
1460 _registers
.__r21
= value
;
1463 _registers
.__r22
= value
;
1466 _registers
.__r23
= value
;
1469 _registers
.__r24
= value
;
1472 _registers
.__r25
= value
;
1475 _registers
.__r26
= value
;
1478 _registers
.__r27
= value
;
1481 _registers
.__r28
= value
;
1484 _registers
.__r29
= value
;
1487 _registers
.__r30
= value
;
1490 _registers
.__r31
= value
;
1493 _registers
.__cr
&= 0x0FFFFFFF;
1494 _registers
.__cr
|= (value
& 0xF0000000);
1497 _registers
.__cr
&= 0xF0FFFFFF;
1498 _registers
.__cr
|= (value
& 0x0F000000);
1501 _registers
.__cr
&= 0xFF0FFFFF;
1502 _registers
.__cr
|= (value
& 0x00F00000);
1505 _registers
.__cr
&= 0xFFF0FFFF;
1506 _registers
.__cr
|= (value
& 0x000F0000);
1509 _registers
.__cr
&= 0xFFFF0FFF;
1510 _registers
.__cr
|= (value
& 0x0000F000);
1513 _registers
.__cr
&= 0xFFFFF0FF;
1514 _registers
.__cr
|= (value
& 0x00000F00);
1517 _registers
.__cr
&= 0xFFFFFF0F;
1518 _registers
.__cr
|= (value
& 0x000000F0);
1521 _registers
.__cr
&= 0xFFFFFFF0;
1522 _registers
.__cr
|= (value
& 0x0000000F);
1525 _registers
.__xer
= value
;
1528 _registers
.__lr
= value
;
1531 _registers
.__ctr
= value
;
1533 case UNW_PPC64_VRSAVE
:
1534 _registers
.__vrsave
= value
;
1537 _LIBUNWIND_ABORT("unsupported ppc64 register");
1540 inline bool Registers_ppc64::validFloatRegister(int regNum
) const {
1541 return regNum
>= UNW_PPC64_F0
&& regNum
<= UNW_PPC64_F31
;
1544 inline double Registers_ppc64::getFloatRegister(int regNum
) const {
1545 assert(validFloatRegister(regNum
));
1546 return _vectorScalarRegisters
[regNum
- UNW_PPC64_F0
].asfloat
.f
;
1549 inline void Registers_ppc64::setFloatRegister(int regNum
, double value
) {
1550 assert(validFloatRegister(regNum
));
1551 _vectorScalarRegisters
[regNum
- UNW_PPC64_F0
].asfloat
.f
= value
;
1554 inline bool Registers_ppc64::validVectorRegister(int regNum
) const {
1555 #if defined(__VSX__)
1556 if (regNum
>= UNW_PPC64_VS0
&& regNum
<= UNW_PPC64_VS31
)
1558 if (regNum
>= UNW_PPC64_VS32
&& regNum
<= UNW_PPC64_VS63
)
1560 #elif defined(__ALTIVEC__)
1561 if (regNum
>= UNW_PPC64_V0
&& regNum
<= UNW_PPC64_V31
)
1567 inline int Registers_ppc64::getVectorRegNum(int num
)
1569 if (num
>= UNW_PPC64_VS0
&& num
<= UNW_PPC64_VS31
)
1570 return num
- UNW_PPC64_VS0
;
1572 return num
- UNW_PPC64_VS32
+ 32;
1575 inline v128
Registers_ppc64::getVectorRegister(int regNum
) const {
1576 assert(validVectorRegister(regNum
));
1577 return _vectorScalarRegisters
[getVectorRegNum(regNum
)].v
;
1580 inline void Registers_ppc64::setVectorRegister(int regNum
, v128 value
) {
1581 assert(validVectorRegister(regNum
));
1582 _vectorScalarRegisters
[getVectorRegNum(regNum
)].v
= value
;
1585 inline const char *Registers_ppc64::getRegisterName(int regNum
) {
1677 case UNW_PPC64_VRSAVE
:
1808 return "unknown register";
1810 #endif // _LIBUNWIND_TARGET_PPC64
1813 #if defined(_LIBUNWIND_TARGET_AARCH64)
1814 /// Registers_arm64 holds the register state of a thread in a 64-bit arm
1816 class _LIBUNWIND_HIDDEN Registers_arm64
;
1817 extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64
*);
1819 #if defined(_LIBUNWIND_USE_GCS)
1820 extern "C" void *__libunwind_cet_get_jump_target() {
1821 return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto
);
1825 class _LIBUNWIND_HIDDEN Registers_arm64
{
1828 Registers_arm64(const void *registers
);
1830 bool validRegister(int num
) const;
1831 uint64_t getRegister(int num
) const;
1832 void setRegister(int num
, uint64_t value
);
1833 bool validFloatRegister(int num
) const;
1834 double getFloatRegister(int num
) const;
1835 void setFloatRegister(int num
, double value
);
1836 bool validVectorRegister(int num
) const;
1837 v128
getVectorRegister(int num
) const;
1838 void setVectorRegister(int num
, v128 value
);
1839 static const char *getRegisterName(int num
);
1840 void jumpto() { __libunwind_Registers_arm64_jumpto(this); }
1841 static constexpr int lastDwarfRegNum() {
1842 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
;
1844 static int getArch() { return REGISTERS_ARM64
; }
1846 uint64_t getSP() const { return _registers
.__sp
; }
1847 void setSP(uint64_t value
) { _registers
.__sp
= value
; }
1848 uint64_t getIP() const { return _registers
.__pc
; }
1849 void setIP(uint64_t value
) { _registers
.__pc
= value
; }
1850 uint64_t getFP() const { return _registers
.__fp
; }
1851 void setFP(uint64_t value
) { _registers
.__fp
= value
; }
1855 uint64_t __x
[29]; // x0-x28
1856 uint64_t __fp
; // Frame pointer x29
1857 uint64_t __lr
; // Link register x30
1858 uint64_t __sp
; // Stack pointer x31
1859 uint64_t __pc
; // Program counter
1860 uint64_t __ra_sign_state
; // RA sign state register
1864 double _vectorHalfRegisters
[32];
1865 // Currently only the lower double in 128-bit vectore registers
1866 // is perserved during unwinding. We could define new register
1867 // numbers (> 96) which mean whole vector registers, then this
1868 // struct would need to change to contain whole vector registers.
1871 inline Registers_arm64::Registers_arm64(const void *registers
) {
1872 static_assert((check_fit
<Registers_arm64
, unw_context_t
>::does_fit
),
1873 "arm64 registers do not fit into unw_context_t");
1874 memcpy(&_registers
, registers
, sizeof(_registers
));
1875 static_assert(sizeof(GPRs
) == 0x110,
1876 "expected VFP registers to be at offset 272");
1877 memcpy(_vectorHalfRegisters
,
1878 static_cast<const uint8_t *>(registers
) + sizeof(GPRs
),
1879 sizeof(_vectorHalfRegisters
));
1882 inline Registers_arm64::Registers_arm64() {
1883 memset(&_registers
, 0, sizeof(_registers
));
1884 memset(&_vectorHalfRegisters
, 0, sizeof(_vectorHalfRegisters
));
1887 inline bool Registers_arm64::validRegister(int regNum
) const {
1888 if (regNum
== UNW_REG_IP
)
1890 if (regNum
== UNW_REG_SP
)
1896 if (regNum
== UNW_AARCH64_RA_SIGN_STATE
)
1898 if ((regNum
> 32) && (regNum
< 64))
1903 inline uint64_t Registers_arm64::getRegister(int regNum
) const {
1904 if (regNum
== UNW_REG_IP
|| regNum
== UNW_AARCH64_PC
)
1905 return _registers
.__pc
;
1906 if (regNum
== UNW_REG_SP
|| regNum
== UNW_AARCH64_SP
)
1907 return _registers
.__sp
;
1908 if (regNum
== UNW_AARCH64_RA_SIGN_STATE
)
1909 return _registers
.__ra_sign_state
;
1910 if (regNum
== UNW_AARCH64_FP
)
1911 return _registers
.__fp
;
1912 if (regNum
== UNW_AARCH64_LR
)
1913 return _registers
.__lr
;
1914 if ((regNum
>= 0) && (regNum
< 29))
1915 return _registers
.__x
[regNum
];
1916 _LIBUNWIND_ABORT("unsupported arm64 register");
1919 inline void Registers_arm64::setRegister(int regNum
, uint64_t value
) {
1920 if (regNum
== UNW_REG_IP
|| regNum
== UNW_AARCH64_PC
)
1921 _registers
.__pc
= value
;
1922 else if (regNum
== UNW_REG_SP
|| regNum
== UNW_AARCH64_SP
)
1923 _registers
.__sp
= value
;
1924 else if (regNum
== UNW_AARCH64_RA_SIGN_STATE
)
1925 _registers
.__ra_sign_state
= value
;
1926 else if (regNum
== UNW_AARCH64_FP
)
1927 _registers
.__fp
= value
;
1928 else if (regNum
== UNW_AARCH64_LR
)
1929 _registers
.__lr
= value
;
1930 else if ((regNum
>= 0) && (regNum
< 29))
1931 _registers
.__x
[regNum
] = value
;
1933 _LIBUNWIND_ABORT("unsupported arm64 register");
1936 inline const char *Registers_arm64::getRegisterName(int regNum
) {
1942 case UNW_AARCH64_X0
:
1944 case UNW_AARCH64_X1
:
1946 case UNW_AARCH64_X2
:
1948 case UNW_AARCH64_X3
:
1950 case UNW_AARCH64_X4
:
1952 case UNW_AARCH64_X5
:
1954 case UNW_AARCH64_X6
:
1956 case UNW_AARCH64_X7
:
1958 case UNW_AARCH64_X8
:
1960 case UNW_AARCH64_X9
:
1962 case UNW_AARCH64_X10
:
1964 case UNW_AARCH64_X11
:
1966 case UNW_AARCH64_X12
:
1968 case UNW_AARCH64_X13
:
1970 case UNW_AARCH64_X14
:
1972 case UNW_AARCH64_X15
:
1974 case UNW_AARCH64_X16
:
1976 case UNW_AARCH64_X17
:
1978 case UNW_AARCH64_X18
:
1980 case UNW_AARCH64_X19
:
1982 case UNW_AARCH64_X20
:
1984 case UNW_AARCH64_X21
:
1986 case UNW_AARCH64_X22
:
1988 case UNW_AARCH64_X23
:
1990 case UNW_AARCH64_X24
:
1992 case UNW_AARCH64_X25
:
1994 case UNW_AARCH64_X26
:
1996 case UNW_AARCH64_X27
:
1998 case UNW_AARCH64_X28
:
2000 case UNW_AARCH64_FP
:
2002 case UNW_AARCH64_LR
:
2004 case UNW_AARCH64_SP
:
2006 case UNW_AARCH64_PC
:
2008 case UNW_AARCH64_V0
:
2010 case UNW_AARCH64_V1
:
2012 case UNW_AARCH64_V2
:
2014 case UNW_AARCH64_V3
:
2016 case UNW_AARCH64_V4
:
2018 case UNW_AARCH64_V5
:
2020 case UNW_AARCH64_V6
:
2022 case UNW_AARCH64_V7
:
2024 case UNW_AARCH64_V8
:
2026 case UNW_AARCH64_V9
:
2028 case UNW_AARCH64_V10
:
2030 case UNW_AARCH64_V11
:
2032 case UNW_AARCH64_V12
:
2034 case UNW_AARCH64_V13
:
2036 case UNW_AARCH64_V14
:
2038 case UNW_AARCH64_V15
:
2040 case UNW_AARCH64_V16
:
2042 case UNW_AARCH64_V17
:
2044 case UNW_AARCH64_V18
:
2046 case UNW_AARCH64_V19
:
2048 case UNW_AARCH64_V20
:
2050 case UNW_AARCH64_V21
:
2052 case UNW_AARCH64_V22
:
2054 case UNW_AARCH64_V23
:
2056 case UNW_AARCH64_V24
:
2058 case UNW_AARCH64_V25
:
2060 case UNW_AARCH64_V26
:
2062 case UNW_AARCH64_V27
:
2064 case UNW_AARCH64_V28
:
2066 case UNW_AARCH64_V29
:
2068 case UNW_AARCH64_V30
:
2070 case UNW_AARCH64_V31
:
2073 return "unknown register";
2077 inline bool Registers_arm64::validFloatRegister(int regNum
) const {
2078 if (regNum
< UNW_AARCH64_V0
)
2080 if (regNum
> UNW_AARCH64_V31
)
2085 inline double Registers_arm64::getFloatRegister(int regNum
) const {
2086 assert(validFloatRegister(regNum
));
2087 return _vectorHalfRegisters
[regNum
- UNW_AARCH64_V0
];
2090 inline void Registers_arm64::setFloatRegister(int regNum
, double value
) {
2091 assert(validFloatRegister(regNum
));
2092 _vectorHalfRegisters
[regNum
- UNW_AARCH64_V0
] = value
;
2095 inline bool Registers_arm64::validVectorRegister(int) const {
2099 inline v128
Registers_arm64::getVectorRegister(int) const {
2100 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2103 inline void Registers_arm64::setVectorRegister(int, v128
) {
2104 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2106 #endif // _LIBUNWIND_TARGET_AARCH64
2108 #if defined(_LIBUNWIND_TARGET_ARM)
2109 /// Registers_arm holds the register state of a thread in a 32-bit arm
2112 /// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2113 /// this uses more memory than required.
2114 class _LIBUNWIND_HIDDEN Registers_arm
{
2117 Registers_arm(const void *registers
);
2119 bool validRegister(int num
) const;
2120 uint32_t getRegister(int num
) const;
2121 void setRegister(int num
, uint32_t value
);
2122 bool validFloatRegister(int num
) const;
2123 unw_fpreg_t
getFloatRegister(int num
);
2124 void setFloatRegister(int num
, unw_fpreg_t value
);
2125 bool validVectorRegister(int num
) const;
2126 v128
getVectorRegister(int num
) const;
2127 void setVectorRegister(int num
, v128 value
);
2128 static const char *getRegisterName(int num
);
2130 restoreSavedFloatRegisters();
2131 restoreCoreAndJumpTo();
2133 static constexpr int lastDwarfRegNum() {
2134 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM
;
2136 static int getArch() { return REGISTERS_ARM
; }
2138 uint32_t getSP() const { return _registers
.__sp
; }
2139 void setSP(uint32_t value
) { _registers
.__sp
= value
; }
2140 uint32_t getIP() const { return _registers
.__pc
; }
2141 void setIP(uint32_t value
) { _registers
.__pc
= value
; }
2144 assert(_use_X_for_vfp_save
|| !_saved_vfp_d0_d15
);
2145 _use_X_for_vfp_save
= true;
2148 void restoreSavedFloatRegisters() {
2149 if (_saved_vfp_d0_d15
) {
2150 if (_use_X_for_vfp_save
)
2151 restoreVFPWithFLDMX(_vfp_d0_d15_pad
);
2153 restoreVFPWithFLDMD(_vfp_d0_d15_pad
);
2155 if (_saved_vfp_d16_d31
)
2156 restoreVFPv3(_vfp_d16_d31
);
2157 #if defined(__ARM_WMMX)
2159 restoreiWMMX(_iwmmx
);
2160 if (_saved_iwmmx_control
)
2161 restoreiWMMXControl(_iwmmx_control
);
2167 uint32_t __r
[13]; // r0-r12
2168 uint32_t __sp
; // Stack pointer r13
2169 uint32_t __lr
; // Link register r14
2170 uint32_t __pc
; // Program counter r15
2173 struct PseudoRegisters
{
2174 uint32_t __pac
; // Return Authentication Code (PAC)
2177 static void saveVFPWithFSTMD(void*);
2178 static void saveVFPWithFSTMX(void*);
2179 static void saveVFPv3(void*);
2180 static void restoreVFPWithFLDMD(void*);
2181 static void restoreVFPWithFLDMX(void*);
2182 static void restoreVFPv3(void*);
2183 #if defined(__ARM_WMMX)
2184 static void saveiWMMX(void*);
2185 static void saveiWMMXControl(uint32_t*);
2186 static void restoreiWMMX(void*);
2187 static void restoreiWMMXControl(uint32_t*);
2189 void restoreCoreAndJumpTo();
2193 PseudoRegisters _pseudo_registers
;
2195 // We save floating point registers lazily because we can't know ahead of
2196 // time which ones are used. See EHABI #4.7.
2198 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2200 // See EHABI #7.5 that explains how matching instruction sequences for load
2201 // and store need to be used to correctly restore the exact register bits.
2202 bool _use_X_for_vfp_save
;
2203 // Whether VFP D0-D15 are saved.
2204 bool _saved_vfp_d0_d15
;
2205 // Whether VFPv3 D16-D31 are saved.
2206 bool _saved_vfp_d16_d31
;
2207 // VFP registers D0-D15, + padding if saved using FSTMX
2208 unw_fpreg_t _vfp_d0_d15_pad
[17];
2209 // VFPv3 registers D16-D31, always saved using FSTMD
2210 unw_fpreg_t _vfp_d16_d31
[16];
2211 #if defined(__ARM_WMMX)
2212 // Whether iWMMX data registers are saved.
2214 // Whether iWMMX control registers are saved.
2215 mutable bool _saved_iwmmx_control
;
2217 unw_fpreg_t _iwmmx
[16];
2218 // iWMMX control registers
2219 mutable uint32_t _iwmmx_control
[4];
2223 inline Registers_arm::Registers_arm(const void *registers
)
2224 : _use_X_for_vfp_save(false),
2225 _saved_vfp_d0_d15(false),
2226 _saved_vfp_d16_d31(false) {
2227 static_assert((check_fit
<Registers_arm
, unw_context_t
>::does_fit
),
2228 "arm registers do not fit into unw_context_t");
2229 // See __unw_getcontext() note about data.
2230 memcpy(&_registers
, registers
, sizeof(_registers
));
2231 memset(&_pseudo_registers
, 0, sizeof(_pseudo_registers
));
2232 memset(&_vfp_d0_d15_pad
, 0, sizeof(_vfp_d0_d15_pad
));
2233 memset(&_vfp_d16_d31
, 0, sizeof(_vfp_d16_d31
));
2234 #if defined(__ARM_WMMX)
2235 _saved_iwmmx
= false;
2236 _saved_iwmmx_control
= false;
2237 memset(&_iwmmx
, 0, sizeof(_iwmmx
));
2238 memset(&_iwmmx_control
, 0, sizeof(_iwmmx_control
));
2242 inline Registers_arm::Registers_arm()
2243 : _use_X_for_vfp_save(false),
2244 _saved_vfp_d0_d15(false),
2245 _saved_vfp_d16_d31(false) {
2246 memset(&_registers
, 0, sizeof(_registers
));
2247 memset(&_pseudo_registers
, 0, sizeof(_pseudo_registers
));
2248 memset(&_vfp_d0_d15_pad
, 0, sizeof(_vfp_d0_d15_pad
));
2249 memset(&_vfp_d16_d31
, 0, sizeof(_vfp_d16_d31
));
2250 #if defined(__ARM_WMMX)
2251 _saved_iwmmx
= false;
2252 _saved_iwmmx_control
= false;
2253 memset(&_iwmmx
, 0, sizeof(_iwmmx
));
2254 memset(&_iwmmx_control
, 0, sizeof(_iwmmx_control
));
2258 inline bool Registers_arm::validRegister(int regNum
) const {
2259 // Returns true for all non-VFP registers supported by the EHABI
2260 // virtual register set (VRS).
2261 if (regNum
== UNW_REG_IP
)
2264 if (regNum
== UNW_REG_SP
)
2267 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R15
)
2270 #if defined(__ARM_WMMX)
2271 if (regNum
>= UNW_ARM_WC0
&& regNum
<= UNW_ARM_WC3
)
2275 #ifdef __ARM_FEATURE_PAUTH
2276 if (regNum
== UNW_ARM_RA_AUTH_CODE
)
2283 inline uint32_t Registers_arm::getRegister(int regNum
) const {
2284 if (regNum
== UNW_REG_SP
|| regNum
== UNW_ARM_SP
)
2285 return _registers
.__sp
;
2287 if (regNum
== UNW_ARM_LR
)
2288 return _registers
.__lr
;
2290 if (regNum
== UNW_REG_IP
|| regNum
== UNW_ARM_IP
)
2291 return _registers
.__pc
;
2293 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R12
)
2294 return _registers
.__r
[regNum
];
2296 #if defined(__ARM_WMMX)
2297 if (regNum
>= UNW_ARM_WC0
&& regNum
<= UNW_ARM_WC3
) {
2298 if (!_saved_iwmmx_control
) {
2299 _saved_iwmmx_control
= true;
2300 saveiWMMXControl(_iwmmx_control
);
2302 return _iwmmx_control
[regNum
- UNW_ARM_WC0
];
2306 #ifdef __ARM_FEATURE_PAUTH
2307 if (regNum
== UNW_ARM_RA_AUTH_CODE
)
2308 return _pseudo_registers
.__pac
;
2311 _LIBUNWIND_ABORT("unsupported arm register");
2314 inline void Registers_arm::setRegister(int regNum
, uint32_t value
) {
2315 if (regNum
== UNW_REG_SP
|| regNum
== UNW_ARM_SP
) {
2316 _registers
.__sp
= value
;
2320 if (regNum
== UNW_ARM_LR
) {
2321 _registers
.__lr
= value
;
2325 if (regNum
== UNW_REG_IP
|| regNum
== UNW_ARM_IP
) {
2326 _registers
.__pc
= value
;
2330 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R12
) {
2331 _registers
.__r
[regNum
] = value
;
2335 #if defined(__ARM_WMMX)
2336 if (regNum
>= UNW_ARM_WC0
&& regNum
<= UNW_ARM_WC3
) {
2337 if (!_saved_iwmmx_control
) {
2338 _saved_iwmmx_control
= true;
2339 saveiWMMXControl(_iwmmx_control
);
2341 _iwmmx_control
[regNum
- UNW_ARM_WC0
] = value
;
2346 if (regNum
== UNW_ARM_RA_AUTH_CODE
) {
2347 _pseudo_registers
.__pac
= value
;
2351 _LIBUNWIND_ABORT("unsupported arm register");
2354 inline const char *Registers_arm::getRegisterName(int regNum
) {
2357 case UNW_ARM_IP
: // UNW_ARM_R15 is alias
2359 case UNW_ARM_LR
: // UNW_ARM_R14 is alias
2362 case UNW_ARM_SP
: // UNW_ARM_R13 is alias
2519 return "unknown register";
2523 inline bool Registers_arm::validFloatRegister(int regNum
) const {
2524 // NOTE: Consider the intel MMX registers floating points so the
2525 // __unw_get_fpreg can be used to transmit the 64-bit data back.
2526 return ((regNum
>= UNW_ARM_D0
) && (regNum
<= UNW_ARM_D31
))
2527 #if defined(__ARM_WMMX)
2528 || ((regNum
>= UNW_ARM_WR0
) && (regNum
<= UNW_ARM_WR15
))
2533 inline unw_fpreg_t
Registers_arm::getFloatRegister(int regNum
) {
2534 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D15
) {
2535 if (!_saved_vfp_d0_d15
) {
2536 _saved_vfp_d0_d15
= true;
2537 if (_use_X_for_vfp_save
)
2538 saveVFPWithFSTMX(_vfp_d0_d15_pad
);
2540 saveVFPWithFSTMD(_vfp_d0_d15_pad
);
2542 return _vfp_d0_d15_pad
[regNum
- UNW_ARM_D0
];
2545 if (regNum
>= UNW_ARM_D16
&& regNum
<= UNW_ARM_D31
) {
2546 if (!_saved_vfp_d16_d31
) {
2547 _saved_vfp_d16_d31
= true;
2548 saveVFPv3(_vfp_d16_d31
);
2550 return _vfp_d16_d31
[regNum
- UNW_ARM_D16
];
2553 #if defined(__ARM_WMMX)
2554 if (regNum
>= UNW_ARM_WR0
&& regNum
<= UNW_ARM_WR15
) {
2555 if (!_saved_iwmmx
) {
2556 _saved_iwmmx
= true;
2559 return _iwmmx
[regNum
- UNW_ARM_WR0
];
2563 _LIBUNWIND_ABORT("Unknown ARM float register");
2566 inline void Registers_arm::setFloatRegister(int regNum
, unw_fpreg_t value
) {
2567 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D15
) {
2568 if (!_saved_vfp_d0_d15
) {
2569 _saved_vfp_d0_d15
= true;
2570 if (_use_X_for_vfp_save
)
2571 saveVFPWithFSTMX(_vfp_d0_d15_pad
);
2573 saveVFPWithFSTMD(_vfp_d0_d15_pad
);
2575 _vfp_d0_d15_pad
[regNum
- UNW_ARM_D0
] = value
;
2579 if (regNum
>= UNW_ARM_D16
&& regNum
<= UNW_ARM_D31
) {
2580 if (!_saved_vfp_d16_d31
) {
2581 _saved_vfp_d16_d31
= true;
2582 saveVFPv3(_vfp_d16_d31
);
2584 _vfp_d16_d31
[regNum
- UNW_ARM_D16
] = value
;
2588 #if defined(__ARM_WMMX)
2589 if (regNum
>= UNW_ARM_WR0
&& regNum
<= UNW_ARM_WR15
) {
2590 if (!_saved_iwmmx
) {
2591 _saved_iwmmx
= true;
2594 _iwmmx
[regNum
- UNW_ARM_WR0
] = value
;
2599 _LIBUNWIND_ABORT("Unknown ARM float register");
2602 inline bool Registers_arm::validVectorRegister(int) const {
2606 inline v128
Registers_arm::getVectorRegister(int) const {
2607 _LIBUNWIND_ABORT("ARM vector support not implemented");
2610 inline void Registers_arm::setVectorRegister(int, v128
) {
2611 _LIBUNWIND_ABORT("ARM vector support not implemented");
2613 #endif // _LIBUNWIND_TARGET_ARM
2616 #if defined(_LIBUNWIND_TARGET_OR1K)
2617 /// Registers_or1k holds the register state of a thread in an OpenRISC1000
2619 class _LIBUNWIND_HIDDEN Registers_or1k
{
2622 Registers_or1k(const void *registers
);
2624 bool validRegister(int num
) const;
2625 uint32_t getRegister(int num
) const;
2626 void setRegister(int num
, uint32_t value
);
2627 bool validFloatRegister(int num
) const;
2628 double getFloatRegister(int num
) const;
2629 void setFloatRegister(int num
, double value
);
2630 bool validVectorRegister(int num
) const;
2631 v128
getVectorRegister(int num
) const;
2632 void setVectorRegister(int num
, v128 value
);
2633 static const char *getRegisterName(int num
);
2635 static constexpr int lastDwarfRegNum() {
2636 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K
;
2638 static int getArch() { return REGISTERS_OR1K
; }
2640 uint64_t getSP() const { return _registers
.__r
[1]; }
2641 void setSP(uint32_t value
) { _registers
.__r
[1] = value
; }
2642 uint64_t getIP() const { return _registers
.__pc
; }
2643 void setIP(uint32_t value
) { _registers
.__pc
= value
; }
2646 struct or1k_thread_state_t
{
2647 unsigned int __r
[32]; // r0-r31
2648 unsigned int __pc
; // Program counter
2649 unsigned int __epcr
; // Program counter at exception
2652 or1k_thread_state_t _registers
;
2655 inline Registers_or1k::Registers_or1k(const void *registers
) {
2656 static_assert((check_fit
<Registers_or1k
, unw_context_t
>::does_fit
),
2657 "or1k registers do not fit into unw_context_t");
2658 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
2659 sizeof(_registers
));
2662 inline Registers_or1k::Registers_or1k() {
2663 memset(&_registers
, 0, sizeof(_registers
));
2666 inline bool Registers_or1k::validRegister(int regNum
) const {
2667 if (regNum
== UNW_REG_IP
)
2669 if (regNum
== UNW_REG_SP
)
2673 if (regNum
<= UNW_OR1K_R31
)
2675 if (regNum
== UNW_OR1K_EPCR
)
2680 inline uint32_t Registers_or1k::getRegister(int regNum
) const {
2681 if (regNum
>= UNW_OR1K_R0
&& regNum
<= UNW_OR1K_R31
)
2682 return _registers
.__r
[regNum
- UNW_OR1K_R0
];
2686 return _registers
.__pc
;
2688 return _registers
.__r
[1];
2690 return _registers
.__epcr
;
2692 _LIBUNWIND_ABORT("unsupported or1k register");
2695 inline void Registers_or1k::setRegister(int regNum
, uint32_t value
) {
2696 if (regNum
>= UNW_OR1K_R0
&& regNum
<= UNW_OR1K_R31
) {
2697 _registers
.__r
[regNum
- UNW_OR1K_R0
] = value
;
2703 _registers
.__pc
= value
;
2706 _registers
.__r
[1] = value
;
2709 _registers
.__epcr
= value
;
2712 _LIBUNWIND_ABORT("unsupported or1k register");
2715 inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2719 inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2720 _LIBUNWIND_ABORT("or1k float support not implemented");
2723 inline void Registers_or1k::setFloatRegister(int /* regNum */,
2724 double /* value */) {
2725 _LIBUNWIND_ABORT("or1k float support not implemented");
2728 inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2732 inline v128
Registers_or1k::getVectorRegister(int /* regNum */) const {
2733 _LIBUNWIND_ABORT("or1k vector support not implemented");
2736 inline void Registers_or1k::setVectorRegister(int /* regNum */, v128
/* value */) {
2737 _LIBUNWIND_ABORT("or1k vector support not implemented");
2740 inline const char *Registers_or1k::getRegisterName(int regNum
) {
2809 return "unknown register";
2813 #endif // _LIBUNWIND_TARGET_OR1K
2815 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
2816 /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2818 class _LIBUNWIND_HIDDEN Registers_mips_o32
{
2820 Registers_mips_o32();
2821 Registers_mips_o32(const void *registers
);
2823 bool validRegister(int num
) const;
2824 uint32_t getRegister(int num
) const;
2825 void setRegister(int num
, uint32_t value
);
2826 bool validFloatRegister(int num
) const;
2827 double getFloatRegister(int num
) const;
2828 void setFloatRegister(int num
, double value
);
2829 bool validVectorRegister(int num
) const;
2830 v128
getVectorRegister(int num
) const;
2831 void setVectorRegister(int num
, v128 value
);
2832 static const char *getRegisterName(int num
);
2834 static constexpr int lastDwarfRegNum() {
2835 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
;
2837 static int getArch() { return REGISTERS_MIPS_O32
; }
2839 uint32_t getSP() const { return _registers
.__r
[29]; }
2840 void setSP(uint32_t value
) { _registers
.__r
[29] = value
; }
2841 uint32_t getIP() const { return _registers
.__pc
; }
2842 void setIP(uint32_t value
) { _registers
.__pc
= value
; }
2845 struct mips_o32_thread_state_t
{
2852 mips_o32_thread_state_t _registers
;
2853 #ifdef __mips_hard_float
2854 /// O32 with 32-bit floating point registers only uses half of this
2855 /// space. However, using the same layout for 32-bit vs 64-bit
2856 /// floating point registers results in a single context size for
2857 /// O32 with hard float.
2863 inline Registers_mips_o32::Registers_mips_o32(const void *registers
) {
2864 static_assert((check_fit
<Registers_mips_o32
, unw_context_t
>::does_fit
),
2865 "mips_o32 registers do not fit into unw_context_t");
2866 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
2867 sizeof(_registers
));
2870 inline Registers_mips_o32::Registers_mips_o32() {
2871 memset(&_registers
, 0, sizeof(_registers
));
2874 inline bool Registers_mips_o32::validRegister(int regNum
) const {
2875 if (regNum
== UNW_REG_IP
)
2877 if (regNum
== UNW_REG_SP
)
2881 if (regNum
<= UNW_MIPS_R31
)
2883 #if __mips_isa_rev < 6
2884 if (regNum
== UNW_MIPS_HI
)
2886 if (regNum
== UNW_MIPS_LO
)
2889 #if defined(__mips_hard_float) && __mips_fpr == 32
2890 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
)
2893 // FIXME: DSP accumulator registers, MSA registers
2897 inline uint32_t Registers_mips_o32::getRegister(int regNum
) const {
2898 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
)
2899 return _registers
.__r
[regNum
- UNW_MIPS_R0
];
2900 #if defined(__mips_hard_float) && __mips_fpr == 32
2901 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
) {
2904 if (regNum
% 2 == 0)
2905 p
= (uint32_t *)&_floats
[regNum
- UNW_MIPS_F0
];
2907 p
= (uint32_t *)&_floats
[(regNum
- 1) - UNW_MIPS_F0
] + 1;
2914 return _registers
.__pc
;
2916 return _registers
.__r
[29];
2917 #if __mips_isa_rev < 6
2919 return _registers
.__hi
;
2921 return _registers
.__lo
;
2924 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2927 inline void Registers_mips_o32::setRegister(int regNum
, uint32_t value
) {
2928 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
) {
2929 _registers
.__r
[regNum
- UNW_MIPS_R0
] = value
;
2932 #if defined(__mips_hard_float) && __mips_fpr == 32
2933 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
) {
2936 if (regNum
% 2 == 0)
2937 p
= (uint32_t *)&_floats
[regNum
- UNW_MIPS_F0
];
2939 p
= (uint32_t *)&_floats
[(regNum
- 1) - UNW_MIPS_F0
] + 1;
2947 _registers
.__pc
= value
;
2950 _registers
.__r
[29] = value
;
2952 #if __mips_isa_rev < 6
2954 _registers
.__hi
= value
;
2957 _registers
.__lo
= value
;
2961 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2964 inline bool Registers_mips_o32::validFloatRegister(int regNum
) const {
2965 #if defined(__mips_hard_float) && __mips_fpr == 64
2966 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
)
2974 inline double Registers_mips_o32::getFloatRegister(int regNum
) const {
2975 #if defined(__mips_hard_float) && __mips_fpr == 64
2976 assert(validFloatRegister(regNum
));
2977 return _floats
[regNum
- UNW_MIPS_F0
];
2980 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2984 inline void Registers_mips_o32::setFloatRegister(int regNum
,
2986 #if defined(__mips_hard_float) && __mips_fpr == 64
2987 assert(validFloatRegister(regNum
));
2988 _floats
[regNum
- UNW_MIPS_F0
] = value
;
2992 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2996 inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
3000 inline v128
Registers_mips_o32::getVectorRegister(int /* regNum */) const {
3001 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
3004 inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128
/* value */) {
3005 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
3008 inline const char *Registers_mips_o32::getRegisterName(int regNum
) {
3138 #if __mips_isa_rev < 6
3145 return "unknown register";
3148 #endif // _LIBUNWIND_TARGET_MIPS_O32
3150 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3151 /// Registers_mips_newabi holds the register state of a thread in a
3152 /// MIPS process using NEWABI (the N32 or N64 ABIs).
3153 class _LIBUNWIND_HIDDEN Registers_mips_newabi
{
3155 Registers_mips_newabi();
3156 Registers_mips_newabi(const void *registers
);
3158 bool validRegister(int num
) const;
3159 uint64_t getRegister(int num
) const;
3160 void setRegister(int num
, uint64_t value
);
3161 bool validFloatRegister(int num
) const;
3162 double getFloatRegister(int num
) const;
3163 void setFloatRegister(int num
, double value
);
3164 bool validVectorRegister(int num
) const;
3165 v128
getVectorRegister(int num
) const;
3166 void setVectorRegister(int num
, v128 value
);
3167 static const char *getRegisterName(int num
);
3169 static constexpr int lastDwarfRegNum() {
3170 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
;
3172 static int getArch() { return REGISTERS_MIPS_NEWABI
; }
3174 uint64_t getSP() const { return _registers
.__r
[29]; }
3175 void setSP(uint64_t value
) { _registers
.__r
[29] = value
; }
3176 uint64_t getIP() const { return _registers
.__pc
; }
3177 void setIP(uint64_t value
) { _registers
.__pc
= value
; }
3180 struct mips_newabi_thread_state_t
{
3187 mips_newabi_thread_state_t _registers
;
3188 #ifdef __mips_hard_float
3193 inline Registers_mips_newabi::Registers_mips_newabi(const void *registers
) {
3194 static_assert((check_fit
<Registers_mips_newabi
, unw_context_t
>::does_fit
),
3195 "mips_newabi registers do not fit into unw_context_t");
3196 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
3197 sizeof(_registers
));
3200 inline Registers_mips_newabi::Registers_mips_newabi() {
3201 memset(&_registers
, 0, sizeof(_registers
));
3204 inline bool Registers_mips_newabi::validRegister(int regNum
) const {
3205 if (regNum
== UNW_REG_IP
)
3207 if (regNum
== UNW_REG_SP
)
3211 if (regNum
<= UNW_MIPS_R31
)
3213 #if __mips_isa_rev < 6
3214 if (regNum
== UNW_MIPS_HI
)
3216 if (regNum
== UNW_MIPS_LO
)
3219 // FIXME: Hard float, DSP accumulator registers, MSA registers
3223 inline uint64_t Registers_mips_newabi::getRegister(int regNum
) const {
3224 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
)
3225 return _registers
.__r
[regNum
- UNW_MIPS_R0
];
3229 return _registers
.__pc
;
3231 return _registers
.__r
[29];
3232 #if __mips_isa_rev < 6
3234 return _registers
.__hi
;
3236 return _registers
.__lo
;
3239 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3242 inline void Registers_mips_newabi::setRegister(int regNum
, uint64_t value
) {
3243 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
) {
3244 _registers
.__r
[regNum
- UNW_MIPS_R0
] = value
;
3250 _registers
.__pc
= value
;
3253 _registers
.__r
[29] = value
;
3255 #if __mips_isa_rev < 6
3257 _registers
.__hi
= value
;
3260 _registers
.__lo
= value
;
3264 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3267 inline bool Registers_mips_newabi::validFloatRegister(int regNum
) const {
3268 #ifdef __mips_hard_float
3269 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
)
3277 inline double Registers_mips_newabi::getFloatRegister(int regNum
) const {
3278 #ifdef __mips_hard_float
3279 assert(validFloatRegister(regNum
));
3280 return _floats
[regNum
- UNW_MIPS_F0
];
3283 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3287 inline void Registers_mips_newabi::setFloatRegister(int regNum
,
3289 #ifdef __mips_hard_float
3290 assert(validFloatRegister(regNum
));
3291 _floats
[regNum
- UNW_MIPS_F0
] = value
;
3295 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3299 inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3303 inline v128
Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3304 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3307 inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128
/* value */) {
3308 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3311 inline const char *Registers_mips_newabi::getRegisterName(int regNum
) {
3441 #if __mips_isa_rev < 6
3448 return "unknown register";
3451 #endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3453 #if defined(_LIBUNWIND_TARGET_SPARC)
3454 /// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3456 class _LIBUNWIND_HIDDEN Registers_sparc
{
3459 Registers_sparc(const void *registers
);
3461 bool validRegister(int num
) const;
3462 uint32_t getRegister(int num
) const;
3463 void setRegister(int num
, uint32_t value
);
3464 bool validFloatRegister(int num
) const;
3465 double getFloatRegister(int num
) const;
3466 void setFloatRegister(int num
, double value
);
3467 bool validVectorRegister(int num
) const;
3468 v128
getVectorRegister(int num
) const;
3469 void setVectorRegister(int num
, v128 value
);
3470 static const char *getRegisterName(int num
);
3472 static constexpr int lastDwarfRegNum() {
3473 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
;
3475 static int getArch() { return REGISTERS_SPARC
; }
3477 uint64_t getSP() const { return _registers
.__regs
[UNW_SPARC_O6
]; }
3478 void setSP(uint32_t value
) { _registers
.__regs
[UNW_SPARC_O6
] = value
; }
3479 uint64_t getIP() const { return _registers
.__regs
[UNW_SPARC_O7
]; }
3480 void setIP(uint32_t value
) { _registers
.__regs
[UNW_SPARC_O7
] = value
; }
3483 struct sparc_thread_state_t
{
3484 unsigned int __regs
[32];
3487 sparc_thread_state_t _registers
;
3490 inline Registers_sparc::Registers_sparc(const void *registers
) {
3491 static_assert((check_fit
<Registers_sparc
, unw_context_t
>::does_fit
),
3492 "sparc registers do not fit into unw_context_t");
3493 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
3494 sizeof(_registers
));
3497 inline Registers_sparc::Registers_sparc() {
3498 memset(&_registers
, 0, sizeof(_registers
));
3501 inline bool Registers_sparc::validRegister(int regNum
) const {
3502 if (regNum
== UNW_REG_IP
)
3504 if (regNum
== UNW_REG_SP
)
3508 if (regNum
<= UNW_SPARC_I7
)
3513 inline uint32_t Registers_sparc::getRegister(int regNum
) const {
3514 if ((UNW_SPARC_G0
<= regNum
) && (regNum
<= UNW_SPARC_I7
)) {
3515 return _registers
.__regs
[regNum
];
3520 return _registers
.__regs
[UNW_SPARC_O7
];
3522 return _registers
.__regs
[UNW_SPARC_O6
];
3524 _LIBUNWIND_ABORT("unsupported sparc register");
3527 inline void Registers_sparc::setRegister(int regNum
, uint32_t value
) {
3528 if ((UNW_SPARC_G0
<= regNum
) && (regNum
<= UNW_SPARC_I7
)) {
3529 _registers
.__regs
[regNum
] = value
;
3535 _registers
.__regs
[UNW_SPARC_O7
] = value
;
3538 _registers
.__regs
[UNW_SPARC_O6
] = value
;
3541 _LIBUNWIND_ABORT("unsupported sparc register");
3544 inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3546 inline double Registers_sparc::getFloatRegister(int) const {
3547 _LIBUNWIND_ABORT("no Sparc float registers");
3550 inline void Registers_sparc::setFloatRegister(int, double) {
3551 _LIBUNWIND_ABORT("no Sparc float registers");
3554 inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3556 inline v128
Registers_sparc::getVectorRegister(int) const {
3557 _LIBUNWIND_ABORT("no Sparc vector registers");
3560 inline void Registers_sparc::setVectorRegister(int, v128
) {
3561 _LIBUNWIND_ABORT("no Sparc vector registers");
3564 inline const char *Registers_sparc::getRegisterName(int regNum
) {
3634 return "unknown register";
3637 #endif // _LIBUNWIND_TARGET_SPARC
3639 #if defined(_LIBUNWIND_TARGET_SPARC64)
3640 /// Registers_sparc64 holds the register state of a thread in a 64-bit
3642 class _LIBUNWIND_HIDDEN Registers_sparc64
{
3644 Registers_sparc64() = default;
3645 Registers_sparc64(const void *registers
);
3647 bool validRegister(int num
) const;
3648 uint64_t getRegister(int num
) const;
3649 void setRegister(int num
, uint64_t value
);
3650 bool validFloatRegister(int num
) const;
3651 double getFloatRegister(int num
) const;
3652 void setFloatRegister(int num
, double value
);
3653 bool validVectorRegister(int num
) const;
3654 v128
getVectorRegister(int num
) const;
3655 void setVectorRegister(int num
, v128 value
);
3656 const char *getRegisterName(int num
);
3658 static constexpr int lastDwarfRegNum() {
3659 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64
;
3661 static int getArch() { return REGISTERS_SPARC64
; }
3663 uint64_t getSP() const { return _registers
.__regs
[UNW_SPARC_O6
] + 2047; }
3664 void setSP(uint64_t value
) { _registers
.__regs
[UNW_SPARC_O6
] = value
- 2047; }
3665 uint64_t getIP() const { return _registers
.__regs
[UNW_SPARC_O7
]; }
3666 void setIP(uint64_t value
) { _registers
.__regs
[UNW_SPARC_O7
] = value
; }
3667 uint64_t getWCookie() const { return _wcookie
; }
3670 struct sparc64_thread_state_t
{
3671 uint64_t __regs
[32];
3674 sparc64_thread_state_t _registers
{};
3675 uint64_t _wcookie
= 0;
3678 inline Registers_sparc64::Registers_sparc64(const void *registers
) {
3679 static_assert((check_fit
<Registers_sparc64
, unw_context_t
>::does_fit
),
3680 "sparc64 registers do not fit into unw_context_t");
3681 memcpy(&_registers
, registers
, sizeof(_registers
));
3683 static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
3687 inline bool Registers_sparc64::validRegister(int regNum
) const {
3688 if (regNum
== UNW_REG_IP
)
3690 if (regNum
== UNW_REG_SP
)
3694 if (regNum
<= UNW_SPARC_I7
)
3699 inline uint64_t Registers_sparc64::getRegister(int regNum
) const {
3700 if (regNum
>= UNW_SPARC_G0
&& regNum
<= UNW_SPARC_I7
)
3701 return _registers
.__regs
[regNum
];
3705 return _registers
.__regs
[UNW_SPARC_O7
];
3707 return _registers
.__regs
[UNW_SPARC_O6
] + 2047;
3709 _LIBUNWIND_ABORT("unsupported sparc64 register");
3712 inline void Registers_sparc64::setRegister(int regNum
, uint64_t value
) {
3713 if (regNum
>= UNW_SPARC_G0
&& regNum
<= UNW_SPARC_I7
) {
3714 _registers
.__regs
[regNum
] = value
;
3720 _registers
.__regs
[UNW_SPARC_O7
] = value
;
3723 _registers
.__regs
[UNW_SPARC_O6
] = value
- 2047;
3726 _LIBUNWIND_ABORT("unsupported sparc64 register");
3729 inline bool Registers_sparc64::validFloatRegister(int) const { return false; }
3731 inline double Registers_sparc64::getFloatRegister(int) const {
3732 _LIBUNWIND_ABORT("no sparc64 float registers");
3735 inline void Registers_sparc64::setFloatRegister(int, double) {
3736 _LIBUNWIND_ABORT("no sparc64 float registers");
3739 inline bool Registers_sparc64::validVectorRegister(int) const { return false; }
3741 inline v128
Registers_sparc64::getVectorRegister(int) const {
3742 _LIBUNWIND_ABORT("no sparc64 vector registers");
3745 inline void Registers_sparc64::setVectorRegister(int, v128
) {
3746 _LIBUNWIND_ABORT("no sparc64 vector registers");
3749 inline const char *Registers_sparc64::getRegisterName(int regNum
) {
3819 return "unknown register";
3822 #endif // _LIBUNWIND_TARGET_SPARC64
3824 #if defined(_LIBUNWIND_TARGET_HEXAGON)
3825 /// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
3827 class _LIBUNWIND_HIDDEN Registers_hexagon
{
3829 Registers_hexagon();
3830 Registers_hexagon(const void *registers
);
3832 bool validRegister(int num
) const;
3833 uint32_t getRegister(int num
) const;
3834 void setRegister(int num
, uint32_t value
);
3835 bool validFloatRegister(int num
) const;
3836 double getFloatRegister(int num
) const;
3837 void setFloatRegister(int num
, double value
);
3838 bool validVectorRegister(int num
) const;
3839 v128
getVectorRegister(int num
) const;
3840 void setVectorRegister(int num
, v128 value
);
3841 const char *getRegisterName(int num
);
3843 static constexpr int lastDwarfRegNum() {
3844 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON
;
3846 static int getArch() { return REGISTERS_HEXAGON
; }
3848 uint32_t getSP() const { return _registers
.__r
[UNW_HEXAGON_R29
]; }
3849 void setSP(uint32_t value
) { _registers
.__r
[UNW_HEXAGON_R29
] = value
; }
3850 uint32_t getIP() const { return _registers
.__r
[UNW_HEXAGON_PC
]; }
3851 void setIP(uint32_t value
) { _registers
.__r
[UNW_HEXAGON_PC
] = value
; }
3854 struct hexagon_thread_state_t
{
3855 unsigned int __r
[35];
3858 hexagon_thread_state_t _registers
;
3861 inline Registers_hexagon::Registers_hexagon(const void *registers
) {
3862 static_assert((check_fit
<Registers_hexagon
, unw_context_t
>::does_fit
),
3863 "hexagon registers do not fit into unw_context_t");
3864 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
3865 sizeof(_registers
));
3868 inline Registers_hexagon::Registers_hexagon() {
3869 memset(&_registers
, 0, sizeof(_registers
));
3872 inline bool Registers_hexagon::validRegister(int regNum
) const {
3873 if (regNum
<= UNW_HEXAGON_R31
)
3878 inline uint32_t Registers_hexagon::getRegister(int regNum
) const {
3879 if (regNum
>= UNW_HEXAGON_R0
&& regNum
<= UNW_HEXAGON_R31
)
3880 return _registers
.__r
[regNum
- UNW_HEXAGON_R0
];
3884 return _registers
.__r
[UNW_HEXAGON_PC
];
3886 return _registers
.__r
[UNW_HEXAGON_R29
];
3888 _LIBUNWIND_ABORT("unsupported hexagon register");
3891 inline void Registers_hexagon::setRegister(int regNum
, uint32_t value
) {
3892 if (regNum
>= UNW_HEXAGON_R0
&& regNum
<= UNW_HEXAGON_R31
) {
3893 _registers
.__r
[regNum
- UNW_HEXAGON_R0
] = value
;
3899 _registers
.__r
[UNW_HEXAGON_PC
] = value
;
3902 _registers
.__r
[UNW_HEXAGON_R29
] = value
;
3905 _LIBUNWIND_ABORT("unsupported hexagon register");
3908 inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {
3912 inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {
3913 _LIBUNWIND_ABORT("hexagon float support not implemented");
3916 inline void Registers_hexagon::setFloatRegister(int /* regNum */,
3917 double /* value */) {
3918 _LIBUNWIND_ABORT("hexagon float support not implemented");
3921 inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {
3925 inline v128
Registers_hexagon::getVectorRegister(int /* regNum */) const {
3926 _LIBUNWIND_ABORT("hexagon vector support not implemented");
3929 inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128
/* value */) {
3930 _LIBUNWIND_ABORT("hexagon vector support not implemented");
3933 inline const char *Registers_hexagon::getRegisterName(int regNum
) {
3935 case UNW_HEXAGON_R0
:
3937 case UNW_HEXAGON_R1
:
3939 case UNW_HEXAGON_R2
:
3941 case UNW_HEXAGON_R3
:
3943 case UNW_HEXAGON_R4
:
3945 case UNW_HEXAGON_R5
:
3947 case UNW_HEXAGON_R6
:
3949 case UNW_HEXAGON_R7
:
3951 case UNW_HEXAGON_R8
:
3953 case UNW_HEXAGON_R9
:
3955 case UNW_HEXAGON_R10
:
3957 case UNW_HEXAGON_R11
:
3959 case UNW_HEXAGON_R12
:
3961 case UNW_HEXAGON_R13
:
3963 case UNW_HEXAGON_R14
:
3965 case UNW_HEXAGON_R15
:
3967 case UNW_HEXAGON_R16
:
3969 case UNW_HEXAGON_R17
:
3971 case UNW_HEXAGON_R18
:
3973 case UNW_HEXAGON_R19
:
3975 case UNW_HEXAGON_R20
:
3977 case UNW_HEXAGON_R21
:
3979 case UNW_HEXAGON_R22
:
3981 case UNW_HEXAGON_R23
:
3983 case UNW_HEXAGON_R24
:
3985 case UNW_HEXAGON_R25
:
3987 case UNW_HEXAGON_R26
:
3989 case UNW_HEXAGON_R27
:
3991 case UNW_HEXAGON_R28
:
3993 case UNW_HEXAGON_R29
:
3995 case UNW_HEXAGON_R30
:
3997 case UNW_HEXAGON_R31
:
4000 return "unknown register";
4004 #endif // _LIBUNWIND_TARGET_HEXAGON
4007 #if defined(_LIBUNWIND_TARGET_RISCV)
4008 /// Registers_riscv holds the register state of a thread in a RISC-V
4011 // This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.
4013 # if __riscv_xlen == 32
4014 typedef uint32_t reg_t
;
4015 # elif __riscv_xlen == 64
4016 typedef uint64_t reg_t
;
4018 # error "Unsupported __riscv_xlen"
4021 # if defined(__riscv_flen)
4022 # if __riscv_flen == 64
4023 typedef double fp_t
;
4024 # elif __riscv_flen == 32
4027 # error "Unsupported __riscv_flen"
4030 // This is just for suppressing undeclared error of fp_t.
4031 typedef double fp_t
;
4034 // Use Max possible width when cross unwinding
4035 typedef uint64_t reg_t
;
4036 typedef double fp_t
;
4037 # define __riscv_xlen 64
4038 # define __riscv_flen 64
4041 /// Registers_riscv holds the register state of a thread.
4042 class _LIBUNWIND_HIDDEN Registers_riscv
{
4045 Registers_riscv(const void *registers
);
4047 bool validRegister(int num
) const;
4048 reg_t
getRegister(int num
) const;
4049 void setRegister(int num
, reg_t value
);
4050 bool validFloatRegister(int num
) const;
4051 fp_t
getFloatRegister(int num
) const;
4052 void setFloatRegister(int num
, fp_t value
);
4053 bool validVectorRegister(int num
) const;
4054 v128
getVectorRegister(int num
) const;
4055 void setVectorRegister(int num
, v128 value
);
4056 static const char *getRegisterName(int num
);
4058 static constexpr int lastDwarfRegNum() {
4059 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV
;
4061 static int getArch() { return REGISTERS_RISCV
; }
4063 reg_t
getSP() const { return _registers
[2]; }
4064 void setSP(reg_t value
) { _registers
[2] = value
; }
4065 reg_t
getIP() const { return _registers
[0]; }
4066 void setIP(reg_t value
) { _registers
[0] = value
; }
4069 // _registers[0] holds the pc
4070 reg_t _registers
[32];
4071 # if defined(__riscv_flen)
4076 inline Registers_riscv::Registers_riscv(const void *registers
) {
4077 static_assert((check_fit
<Registers_riscv
, unw_context_t
>::does_fit
),
4078 "riscv registers do not fit into unw_context_t");
4079 memcpy(&_registers
, registers
, sizeof(_registers
));
4080 # if __riscv_xlen == 32
4081 static_assert(sizeof(_registers
) == 0x80,
4082 "expected float registers to be at offset 128");
4083 # elif __riscv_xlen == 64
4084 static_assert(sizeof(_registers
) == 0x100,
4085 "expected float registers to be at offset 256");
4087 # error "Unexpected float registers."
4090 # if defined(__riscv_flen)
4092 static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
4097 inline Registers_riscv::Registers_riscv() {
4098 memset(&_registers
, 0, sizeof(_registers
));
4099 # if defined(__riscv_flen)
4100 memset(&_floats
, 0, sizeof(_floats
));
4104 inline bool Registers_riscv::validRegister(int regNum
) const {
4105 if (regNum
== UNW_REG_IP
)
4107 if (regNum
== UNW_REG_SP
)
4111 if (regNum
== UNW_RISCV_VLENB
)
4113 if (regNum
> UNW_RISCV_F31
)
4118 inline reg_t
Registers_riscv::getRegister(int regNum
) const {
4119 if (regNum
== UNW_REG_IP
)
4120 return _registers
[0];
4121 if (regNum
== UNW_REG_SP
)
4122 return _registers
[2];
4123 if (regNum
== UNW_RISCV_X0
)
4125 if ((regNum
> 0) && (regNum
< 32))
4126 return _registers
[regNum
];
4127 if (regNum
== UNW_RISCV_VLENB
) {
4129 __asm__("csrr %0, 0xC22" : "=r"(vlenb
));
4132 _LIBUNWIND_ABORT("unsupported riscv register");
4135 inline void Registers_riscv::setRegister(int regNum
, reg_t value
) {
4136 if (regNum
== UNW_REG_IP
)
4137 _registers
[0] = value
;
4138 else if (regNum
== UNW_REG_SP
)
4139 _registers
[2] = value
;
4140 else if (regNum
== UNW_RISCV_X0
)
4141 /* x0 is hardwired to zero */
4143 else if ((regNum
> 0) && (regNum
< 32))
4144 _registers
[regNum
] = value
;
4146 _LIBUNWIND_ABORT("unsupported riscv register");
4149 inline const char *Registers_riscv::getRegisterName(int regNum
) {
4283 case UNW_RISCV_VLENB
:
4286 return "unknown register";
4290 inline bool Registers_riscv::validFloatRegister(int regNum
) const {
4291 # if defined(__riscv_flen)
4292 if (regNum
< UNW_RISCV_F0
)
4294 if (regNum
> UNW_RISCV_F31
)
4303 inline fp_t
Registers_riscv::getFloatRegister(int regNum
) const {
4304 # if defined(__riscv_flen)
4305 assert(validFloatRegister(regNum
));
4306 return _floats
[regNum
- UNW_RISCV_F0
];
4309 _LIBUNWIND_ABORT("libunwind not built with float support");
4313 inline void Registers_riscv::setFloatRegister(int regNum
, fp_t value
) {
4314 # if defined(__riscv_flen)
4315 assert(validFloatRegister(regNum
));
4316 _floats
[regNum
- UNW_RISCV_F0
] = value
;
4320 _LIBUNWIND_ABORT("libunwind not built with float support");
4324 inline bool Registers_riscv::validVectorRegister(int) const {
4328 inline v128
Registers_riscv::getVectorRegister(int) const {
4329 _LIBUNWIND_ABORT("no riscv vector register support yet");
4332 inline void Registers_riscv::setVectorRegister(int, v128
) {
4333 _LIBUNWIND_ABORT("no riscv vector register support yet");
4335 #endif // _LIBUNWIND_TARGET_RISCV
4337 #if defined(_LIBUNWIND_TARGET_VE)
4338 /// Registers_ve holds the register state of a thread in a VE process.
4339 class _LIBUNWIND_HIDDEN Registers_ve
{
4342 Registers_ve(const void *registers
);
4344 bool validRegister(int num
) const;
4345 uint64_t getRegister(int num
) const;
4346 void setRegister(int num
, uint64_t value
);
4347 bool validFloatRegister(int num
) const;
4348 double getFloatRegister(int num
) const;
4349 void setFloatRegister(int num
, double value
);
4350 bool validVectorRegister(int num
) const;
4351 v128
getVectorRegister(int num
) const;
4352 void setVectorRegister(int num
, v128 value
);
4353 static const char *getRegisterName(int num
);
4355 static constexpr int lastDwarfRegNum() {
4356 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE
;
4358 static int getArch() { return REGISTERS_VE
; }
4360 uint64_t getSP() const { return _registers
.__s
[11]; }
4361 void setSP(uint64_t value
) { _registers
.__s
[11] = value
; }
4362 uint64_t getIP() const { return _registers
.__ic
; }
4363 void setIP(uint64_t value
) { _registers
.__ic
= value
; }
4366 // FIXME: Need to store not only scalar registers but also vector and vector
4367 // mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes
4368 // 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for
4369 // SjLj exception support only, so Registers_ve is not implemented completely.
4370 struct ve_thread_state_t
{
4371 uint64_t __s
[64]; // s0-s64
4372 uint64_t __ic
; // Instruction counter (IC)
4373 uint64_t __vixr
; // Vector Index Register
4374 uint64_t __vl
; // Vector Length Register
4377 ve_thread_state_t _registers
; // total 67 registers
4379 // Currently no vector register is preserved.
4382 inline Registers_ve::Registers_ve(const void *registers
) {
4383 static_assert((check_fit
<Registers_ve
, unw_context_t
>::does_fit
),
4384 "ve registers do not fit into unw_context_t");
4385 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
4386 sizeof(_registers
));
4387 static_assert(sizeof(_registers
) == 536,
4388 "expected vector register offset to be 536");
4391 inline Registers_ve::Registers_ve() {
4392 memset(&_registers
, 0, sizeof(_registers
));
4395 inline bool Registers_ve::validRegister(int regNum
) const {
4396 if (regNum
>= UNW_VE_S0
&& regNum
<= UNW_VE_S63
)
4410 inline uint64_t Registers_ve::getRegister(int regNum
) const {
4411 if (regNum
>= UNW_VE_S0
&& regNum
<= UNW_VE_S63
)
4412 return _registers
.__s
[regNum
- UNW_VE_S0
];
4416 return _registers
.__ic
;
4418 return _registers
.__s
[11];
4420 return _registers
.__vixr
;
4422 return _registers
.__vl
;
4424 _LIBUNWIND_ABORT("unsupported ve register");
4427 inline void Registers_ve::setRegister(int regNum
, uint64_t value
) {
4428 if (regNum
>= UNW_VE_S0
&& regNum
<= UNW_VE_S63
) {
4429 _registers
.__s
[regNum
- UNW_VE_S0
] = value
;
4435 _registers
.__ic
= value
;
4438 _registers
.__s
[11] = value
;
4441 _registers
.__vixr
= value
;
4444 _registers
.__vl
= value
;
4447 _LIBUNWIND_ABORT("unsupported ve register");
4450 inline bool Registers_ve::validFloatRegister(int /* regNum */) const {
4454 inline double Registers_ve::getFloatRegister(int /* regNum */) const {
4455 _LIBUNWIND_ABORT("VE doesn't have float registers");
4458 inline void Registers_ve::setFloatRegister(int /* regNum */,
4459 double /* value */) {
4460 _LIBUNWIND_ABORT("VE doesn't have float registers");
4463 inline bool Registers_ve::validVectorRegister(int /* regNum */) const {
4467 inline v128
Registers_ve::getVectorRegister(int /* regNum */) const {
4468 _LIBUNWIND_ABORT("VE vector support not implemented");
4471 inline void Registers_ve::setVectorRegister(int /* regNum */,
4473 _LIBUNWIND_ABORT("VE vector support not implemented");
4476 inline const char *Registers_ve::getRegisterName(int regNum
) {
4775 return "unknown register";
4777 #endif // _LIBUNWIND_TARGET_VE
4779 #if defined(_LIBUNWIND_TARGET_S390X)
4780 /// Registers_s390x holds the register state of a thread in a
4781 /// 64-bit Linux on IBM zSystems process.
4782 class _LIBUNWIND_HIDDEN Registers_s390x
{
4785 Registers_s390x(const void *registers
);
4787 bool validRegister(int num
) const;
4788 uint64_t getRegister(int num
) const;
4789 void setRegister(int num
, uint64_t value
);
4790 bool validFloatRegister(int num
) const;
4791 double getFloatRegister(int num
) const;
4792 void setFloatRegister(int num
, double value
);
4793 bool validVectorRegister(int num
) const;
4794 v128
getVectorRegister(int num
) const;
4795 void setVectorRegister(int num
, v128 value
);
4796 static const char *getRegisterName(int num
);
4798 static constexpr int lastDwarfRegNum() {
4799 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X
;
4801 static int getArch() { return REGISTERS_S390X
; }
4803 uint64_t getSP() const { return _registers
.__gpr
[15]; }
4804 void setSP(uint64_t value
) { _registers
.__gpr
[15] = value
; }
4805 uint64_t getIP() const { return _registers
.__pswa
; }
4806 void setIP(uint64_t value
) { _registers
.__pswa
= value
; }
4809 struct s390x_thread_state_t
{
4810 uint64_t __pswm
; // Problem Status Word: Mask
4811 uint64_t __pswa
; // Problem Status Word: Address (PC)
4812 uint64_t __gpr
[16]; // General Purpose Registers
4813 double __fpr
[16]; // Floating-Point Registers
4816 s390x_thread_state_t _registers
;
4819 inline Registers_s390x::Registers_s390x(const void *registers
) {
4820 static_assert((check_fit
<Registers_s390x
, unw_context_t
>::does_fit
),
4821 "s390x registers do not fit into unw_context_t");
4822 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
4823 sizeof(_registers
));
4826 inline Registers_s390x::Registers_s390x() {
4827 memset(&_registers
, 0, sizeof(_registers
));
4830 inline bool Registers_s390x::validRegister(int regNum
) const {
4832 case UNW_S390X_PSWM
:
4833 case UNW_S390X_PSWA
:
4839 if (regNum
>= UNW_S390X_R0
&& regNum
<= UNW_S390X_R15
)
4845 inline uint64_t Registers_s390x::getRegister(int regNum
) const {
4846 if (regNum
>= UNW_S390X_R0
&& regNum
<= UNW_S390X_R15
)
4847 return _registers
.__gpr
[regNum
- UNW_S390X_R0
];
4850 case UNW_S390X_PSWM
:
4851 return _registers
.__pswm
;
4852 case UNW_S390X_PSWA
:
4854 return _registers
.__pswa
;
4856 return _registers
.__gpr
[15];
4858 _LIBUNWIND_ABORT("unsupported s390x register");
4861 inline void Registers_s390x::setRegister(int regNum
, uint64_t value
) {
4862 if (regNum
>= UNW_S390X_R0
&& regNum
<= UNW_S390X_R15
) {
4863 _registers
.__gpr
[regNum
- UNW_S390X_R0
] = value
;
4868 case UNW_S390X_PSWM
:
4869 _registers
.__pswm
= value
;
4871 case UNW_S390X_PSWA
:
4873 _registers
.__pswa
= value
;
4876 _registers
.__gpr
[15] = value
;
4879 _LIBUNWIND_ABORT("unsupported s390x register");
4882 inline bool Registers_s390x::validFloatRegister(int regNum
) const {
4883 return regNum
>= UNW_S390X_F0
&& regNum
<= UNW_S390X_F15
;
4886 inline double Registers_s390x::getFloatRegister(int regNum
) const {
4887 // NOTE: FPR DWARF register numbers are not consecutive.
4890 return _registers
.__fpr
[0];
4892 return _registers
.__fpr
[1];
4894 return _registers
.__fpr
[2];
4896 return _registers
.__fpr
[3];
4898 return _registers
.__fpr
[4];
4900 return _registers
.__fpr
[5];
4902 return _registers
.__fpr
[6];
4904 return _registers
.__fpr
[7];
4906 return _registers
.__fpr
[8];
4908 return _registers
.__fpr
[9];
4910 return _registers
.__fpr
[10];
4912 return _registers
.__fpr
[11];
4914 return _registers
.__fpr
[12];
4916 return _registers
.__fpr
[13];
4918 return _registers
.__fpr
[14];
4920 return _registers
.__fpr
[15];
4922 _LIBUNWIND_ABORT("unsupported s390x register");
4925 inline void Registers_s390x::setFloatRegister(int regNum
, double value
) {
4926 // NOTE: FPR DWARF register numbers are not consecutive.
4929 _registers
.__fpr
[0] = value
;
4932 _registers
.__fpr
[1] = value
;
4935 _registers
.__fpr
[2] = value
;
4938 _registers
.__fpr
[3] = value
;
4941 _registers
.__fpr
[4] = value
;
4944 _registers
.__fpr
[5] = value
;
4947 _registers
.__fpr
[6] = value
;
4950 _registers
.__fpr
[7] = value
;
4953 _registers
.__fpr
[8] = value
;
4956 _registers
.__fpr
[9] = value
;
4959 _registers
.__fpr
[10] = value
;
4962 _registers
.__fpr
[11] = value
;
4965 _registers
.__fpr
[12] = value
;
4968 _registers
.__fpr
[13] = value
;
4971 _registers
.__fpr
[14] = value
;
4974 _registers
.__fpr
[15] = value
;
4977 _LIBUNWIND_ABORT("unsupported s390x register");
4980 inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
4984 inline v128
Registers_s390x::getVectorRegister(int /*regNum*/) const {
4985 _LIBUNWIND_ABORT("s390x vector support not implemented");
4988 inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128
/*value*/) {
4989 _LIBUNWIND_ABORT("s390x vector support not implemented");
4992 inline const char *Registers_s390x::getRegisterName(int regNum
) {
5063 return "unknown register";
5065 #endif // _LIBUNWIND_TARGET_S390X
5067 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
5068 /// Registers_loongarch holds the register state of a thread in a 64-bit
5069 /// LoongArch process.
5070 class _LIBUNWIND_HIDDEN Registers_loongarch
{
5072 Registers_loongarch();
5073 Registers_loongarch(const void *registers
);
5075 bool validRegister(int num
) const;
5076 uint64_t getRegister(int num
) const;
5077 void setRegister(int num
, uint64_t value
);
5078 bool validFloatRegister(int num
) const;
5079 double getFloatRegister(int num
) const;
5080 void setFloatRegister(int num
, double value
);
5081 bool validVectorRegister(int num
) const;
5082 v128
getVectorRegister(int num
) const;
5083 void setVectorRegister(int num
, v128 value
);
5084 static const char *getRegisterName(int num
);
5086 static constexpr int lastDwarfRegNum() {
5087 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH
;
5089 static int getArch() { return REGISTERS_LOONGARCH
; }
5091 uint64_t getSP() const { return _registers
.__r
[3]; }
5092 void setSP(uint64_t value
) { _registers
.__r
[3] = value
; }
5093 uint64_t getIP() const { return _registers
.__pc
; }
5094 void setIP(uint64_t value
) { _registers
.__pc
= value
; }
5097 struct loongarch_thread_state_t
{
5102 loongarch_thread_state_t _registers
;
5103 #if __loongarch_frlen == 64
5108 inline Registers_loongarch::Registers_loongarch(const void *registers
) {
5109 static_assert((check_fit
<Registers_loongarch
, unw_context_t
>::does_fit
),
5110 "loongarch registers do not fit into unw_context_t");
5111 memcpy(&_registers
, registers
, sizeof(_registers
));
5112 static_assert(sizeof(_registers
) == 0x108,
5113 "expected float registers to be at offset 264");
5114 #if __loongarch_frlen == 64
5115 memcpy(_floats
, static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
5120 inline Registers_loongarch::Registers_loongarch() {
5121 memset(&_registers
, 0, sizeof(_registers
));
5122 #if __loongarch_frlen == 64
5123 memset(&_floats
, 0, sizeof(_floats
));
5127 inline bool Registers_loongarch::validRegister(int regNum
) const {
5128 if (regNum
== UNW_REG_IP
|| regNum
== UNW_REG_SP
)
5130 if (regNum
< 0 || regNum
> UNW_LOONGARCH_F31
)
5135 inline uint64_t Registers_loongarch::getRegister(int regNum
) const {
5136 if (regNum
>= UNW_LOONGARCH_R0
&& regNum
<= UNW_LOONGARCH_R31
)
5137 return _registers
.__r
[regNum
- UNW_LOONGARCH_R0
];
5139 if (regNum
== UNW_REG_IP
)
5140 return _registers
.__pc
;
5141 if (regNum
== UNW_REG_SP
)
5142 return _registers
.__r
[3];
5143 _LIBUNWIND_ABORT("unsupported loongarch register");
5146 inline void Registers_loongarch::setRegister(int regNum
, uint64_t value
) {
5147 if (regNum
>= UNW_LOONGARCH_R0
&& regNum
<= UNW_LOONGARCH_R31
)
5148 _registers
.__r
[regNum
- UNW_LOONGARCH_R0
] = value
;
5149 else if (regNum
== UNW_REG_IP
)
5150 _registers
.__pc
= value
;
5151 else if (regNum
== UNW_REG_SP
)
5152 _registers
.__r
[3] = value
;
5154 _LIBUNWIND_ABORT("unsupported loongarch register");
5157 inline const char *Registers_loongarch::getRegisterName(int regNum
) {
5163 case UNW_LOONGARCH_R0
:
5165 case UNW_LOONGARCH_R1
:
5167 case UNW_LOONGARCH_R2
:
5169 case UNW_LOONGARCH_R3
:
5171 case UNW_LOONGARCH_R4
:
5173 case UNW_LOONGARCH_R5
:
5175 case UNW_LOONGARCH_R6
:
5177 case UNW_LOONGARCH_R7
:
5179 case UNW_LOONGARCH_R8
:
5181 case UNW_LOONGARCH_R9
:
5183 case UNW_LOONGARCH_R10
:
5185 case UNW_LOONGARCH_R11
:
5187 case UNW_LOONGARCH_R12
:
5189 case UNW_LOONGARCH_R13
:
5191 case UNW_LOONGARCH_R14
:
5193 case UNW_LOONGARCH_R15
:
5195 case UNW_LOONGARCH_R16
:
5197 case UNW_LOONGARCH_R17
:
5199 case UNW_LOONGARCH_R18
:
5201 case UNW_LOONGARCH_R19
:
5203 case UNW_LOONGARCH_R20
:
5205 case UNW_LOONGARCH_R21
:
5207 case UNW_LOONGARCH_R22
:
5209 case UNW_LOONGARCH_R23
:
5211 case UNW_LOONGARCH_R24
:
5213 case UNW_LOONGARCH_R25
:
5215 case UNW_LOONGARCH_R26
:
5217 case UNW_LOONGARCH_R27
:
5219 case UNW_LOONGARCH_R28
:
5221 case UNW_LOONGARCH_R29
:
5223 case UNW_LOONGARCH_R30
:
5225 case UNW_LOONGARCH_R31
:
5227 case UNW_LOONGARCH_F0
:
5229 case UNW_LOONGARCH_F1
:
5231 case UNW_LOONGARCH_F2
:
5233 case UNW_LOONGARCH_F3
:
5235 case UNW_LOONGARCH_F4
:
5237 case UNW_LOONGARCH_F5
:
5239 case UNW_LOONGARCH_F6
:
5241 case UNW_LOONGARCH_F7
:
5243 case UNW_LOONGARCH_F8
:
5245 case UNW_LOONGARCH_F9
:
5247 case UNW_LOONGARCH_F10
:
5249 case UNW_LOONGARCH_F11
:
5251 case UNW_LOONGARCH_F12
:
5253 case UNW_LOONGARCH_F13
:
5255 case UNW_LOONGARCH_F14
:
5257 case UNW_LOONGARCH_F15
:
5259 case UNW_LOONGARCH_F16
:
5261 case UNW_LOONGARCH_F17
:
5263 case UNW_LOONGARCH_F18
:
5265 case UNW_LOONGARCH_F19
:
5267 case UNW_LOONGARCH_F20
:
5269 case UNW_LOONGARCH_F21
:
5271 case UNW_LOONGARCH_F22
:
5273 case UNW_LOONGARCH_F23
:
5275 case UNW_LOONGARCH_F24
:
5277 case UNW_LOONGARCH_F25
:
5279 case UNW_LOONGARCH_F26
:
5281 case UNW_LOONGARCH_F27
:
5283 case UNW_LOONGARCH_F28
:
5285 case UNW_LOONGARCH_F29
:
5287 case UNW_LOONGARCH_F30
:
5289 case UNW_LOONGARCH_F31
:
5292 return "unknown register";
5296 inline bool Registers_loongarch::validFloatRegister(int regNum
) const {
5297 if (regNum
< UNW_LOONGARCH_F0
|| regNum
> UNW_LOONGARCH_F31
)
5302 inline double Registers_loongarch::getFloatRegister(int regNum
) const {
5303 #if __loongarch_frlen == 64
5304 assert(validFloatRegister(regNum
));
5305 return _floats
[regNum
- UNW_LOONGARCH_F0
];
5307 _LIBUNWIND_ABORT("libunwind not built with float support");
5311 inline void Registers_loongarch::setFloatRegister(int regNum
, double value
) {
5312 #if __loongarch_frlen == 64
5313 assert(validFloatRegister(regNum
));
5314 _floats
[regNum
- UNW_LOONGARCH_F0
] = value
;
5316 _LIBUNWIND_ABORT("libunwind not built with float support");
5320 inline bool Registers_loongarch::validVectorRegister(int) const {
5324 inline v128
Registers_loongarch::getVectorRegister(int) const {
5325 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5328 inline void Registers_loongarch::setVectorRegister(int, v128
) {
5329 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5331 #endif //_LIBUNWIND_TARGET_LOONGARCH
5333 } // namespace libunwind
5335 #endif // __REGISTERS_HPP__