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
*);
1818 class _LIBUNWIND_HIDDEN Registers_arm64
{
1821 Registers_arm64(const void *registers
);
1823 bool validRegister(int num
) const;
1824 uint64_t getRegister(int num
) const;
1825 void setRegister(int num
, uint64_t value
);
1826 bool validFloatRegister(int num
) const;
1827 double getFloatRegister(int num
) const;
1828 void setFloatRegister(int num
, double value
);
1829 bool validVectorRegister(int num
) const;
1830 v128
getVectorRegister(int num
) const;
1831 void setVectorRegister(int num
, v128 value
);
1832 static const char *getRegisterName(int num
);
1833 void jumpto() { __libunwind_Registers_arm64_jumpto(this); }
1834 static constexpr int lastDwarfRegNum() {
1835 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
;
1837 static int getArch() { return REGISTERS_ARM64
; }
1839 uint64_t getSP() const { return _registers
.__sp
; }
1840 void setSP(uint64_t value
) { _registers
.__sp
= value
; }
1841 uint64_t getIP() const { return _registers
.__pc
; }
1842 void setIP(uint64_t value
) { _registers
.__pc
= value
; }
1843 uint64_t getFP() const { return _registers
.__fp
; }
1844 void setFP(uint64_t value
) { _registers
.__fp
= value
; }
1848 uint64_t __x
[29]; // x0-x28
1849 uint64_t __fp
; // Frame pointer x29
1850 uint64_t __lr
; // Link register x30
1851 uint64_t __sp
; // Stack pointer x31
1852 uint64_t __pc
; // Program counter
1853 uint64_t __ra_sign_state
; // RA sign state register
1857 double _vectorHalfRegisters
[32];
1858 // Currently only the lower double in 128-bit vectore registers
1859 // is perserved during unwinding. We could define new register
1860 // numbers (> 96) which mean whole vector registers, then this
1861 // struct would need to change to contain whole vector registers.
1864 inline Registers_arm64::Registers_arm64(const void *registers
) {
1865 static_assert((check_fit
<Registers_arm64
, unw_context_t
>::does_fit
),
1866 "arm64 registers do not fit into unw_context_t");
1867 memcpy(&_registers
, registers
, sizeof(_registers
));
1868 static_assert(sizeof(GPRs
) == 0x110,
1869 "expected VFP registers to be at offset 272");
1870 memcpy(_vectorHalfRegisters
,
1871 static_cast<const uint8_t *>(registers
) + sizeof(GPRs
),
1872 sizeof(_vectorHalfRegisters
));
1875 inline Registers_arm64::Registers_arm64() {
1876 memset(&_registers
, 0, sizeof(_registers
));
1877 memset(&_vectorHalfRegisters
, 0, sizeof(_vectorHalfRegisters
));
1880 inline bool Registers_arm64::validRegister(int regNum
) const {
1881 if (regNum
== UNW_REG_IP
)
1883 if (regNum
== UNW_REG_SP
)
1889 if (regNum
== UNW_AARCH64_RA_SIGN_STATE
)
1891 if ((regNum
> 32) && (regNum
< 64))
1896 inline uint64_t Registers_arm64::getRegister(int regNum
) const {
1897 if (regNum
== UNW_REG_IP
|| regNum
== UNW_AARCH64_PC
)
1898 return _registers
.__pc
;
1899 if (regNum
== UNW_REG_SP
|| regNum
== UNW_AARCH64_SP
)
1900 return _registers
.__sp
;
1901 if (regNum
== UNW_AARCH64_RA_SIGN_STATE
)
1902 return _registers
.__ra_sign_state
;
1903 if (regNum
== UNW_AARCH64_FP
)
1904 return _registers
.__fp
;
1905 if (regNum
== UNW_AARCH64_LR
)
1906 return _registers
.__lr
;
1907 if ((regNum
>= 0) && (regNum
< 29))
1908 return _registers
.__x
[regNum
];
1909 _LIBUNWIND_ABORT("unsupported arm64 register");
1912 inline void Registers_arm64::setRegister(int regNum
, uint64_t value
) {
1913 if (regNum
== UNW_REG_IP
|| regNum
== UNW_AARCH64_PC
)
1914 _registers
.__pc
= value
;
1915 else if (regNum
== UNW_REG_SP
|| regNum
== UNW_AARCH64_SP
)
1916 _registers
.__sp
= value
;
1917 else if (regNum
== UNW_AARCH64_RA_SIGN_STATE
)
1918 _registers
.__ra_sign_state
= value
;
1919 else if (regNum
== UNW_AARCH64_FP
)
1920 _registers
.__fp
= value
;
1921 else if (regNum
== UNW_AARCH64_LR
)
1922 _registers
.__lr
= value
;
1923 else if ((regNum
>= 0) && (regNum
< 29))
1924 _registers
.__x
[regNum
] = value
;
1926 _LIBUNWIND_ABORT("unsupported arm64 register");
1929 inline const char *Registers_arm64::getRegisterName(int regNum
) {
1935 case UNW_AARCH64_X0
:
1937 case UNW_AARCH64_X1
:
1939 case UNW_AARCH64_X2
:
1941 case UNW_AARCH64_X3
:
1943 case UNW_AARCH64_X4
:
1945 case UNW_AARCH64_X5
:
1947 case UNW_AARCH64_X6
:
1949 case UNW_AARCH64_X7
:
1951 case UNW_AARCH64_X8
:
1953 case UNW_AARCH64_X9
:
1955 case UNW_AARCH64_X10
:
1957 case UNW_AARCH64_X11
:
1959 case UNW_AARCH64_X12
:
1961 case UNW_AARCH64_X13
:
1963 case UNW_AARCH64_X14
:
1965 case UNW_AARCH64_X15
:
1967 case UNW_AARCH64_X16
:
1969 case UNW_AARCH64_X17
:
1971 case UNW_AARCH64_X18
:
1973 case UNW_AARCH64_X19
:
1975 case UNW_AARCH64_X20
:
1977 case UNW_AARCH64_X21
:
1979 case UNW_AARCH64_X22
:
1981 case UNW_AARCH64_X23
:
1983 case UNW_AARCH64_X24
:
1985 case UNW_AARCH64_X25
:
1987 case UNW_AARCH64_X26
:
1989 case UNW_AARCH64_X27
:
1991 case UNW_AARCH64_X28
:
1993 case UNW_AARCH64_FP
:
1995 case UNW_AARCH64_LR
:
1997 case UNW_AARCH64_SP
:
1999 case UNW_AARCH64_PC
:
2001 case UNW_AARCH64_V0
:
2003 case UNW_AARCH64_V1
:
2005 case UNW_AARCH64_V2
:
2007 case UNW_AARCH64_V3
:
2009 case UNW_AARCH64_V4
:
2011 case UNW_AARCH64_V5
:
2013 case UNW_AARCH64_V6
:
2015 case UNW_AARCH64_V7
:
2017 case UNW_AARCH64_V8
:
2019 case UNW_AARCH64_V9
:
2021 case UNW_AARCH64_V10
:
2023 case UNW_AARCH64_V11
:
2025 case UNW_AARCH64_V12
:
2027 case UNW_AARCH64_V13
:
2029 case UNW_AARCH64_V14
:
2031 case UNW_AARCH64_V15
:
2033 case UNW_AARCH64_V16
:
2035 case UNW_AARCH64_V17
:
2037 case UNW_AARCH64_V18
:
2039 case UNW_AARCH64_V19
:
2041 case UNW_AARCH64_V20
:
2043 case UNW_AARCH64_V21
:
2045 case UNW_AARCH64_V22
:
2047 case UNW_AARCH64_V23
:
2049 case UNW_AARCH64_V24
:
2051 case UNW_AARCH64_V25
:
2053 case UNW_AARCH64_V26
:
2055 case UNW_AARCH64_V27
:
2057 case UNW_AARCH64_V28
:
2059 case UNW_AARCH64_V29
:
2061 case UNW_AARCH64_V30
:
2063 case UNW_AARCH64_V31
:
2066 return "unknown register";
2070 inline bool Registers_arm64::validFloatRegister(int regNum
) const {
2071 if (regNum
< UNW_AARCH64_V0
)
2073 if (regNum
> UNW_AARCH64_V31
)
2078 inline double Registers_arm64::getFloatRegister(int regNum
) const {
2079 assert(validFloatRegister(regNum
));
2080 return _vectorHalfRegisters
[regNum
- UNW_AARCH64_V0
];
2083 inline void Registers_arm64::setFloatRegister(int regNum
, double value
) {
2084 assert(validFloatRegister(regNum
));
2085 _vectorHalfRegisters
[regNum
- UNW_AARCH64_V0
] = value
;
2088 inline bool Registers_arm64::validVectorRegister(int) const {
2092 inline v128
Registers_arm64::getVectorRegister(int) const {
2093 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2096 inline void Registers_arm64::setVectorRegister(int, v128
) {
2097 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2099 #endif // _LIBUNWIND_TARGET_AARCH64
2101 #if defined(_LIBUNWIND_TARGET_ARM)
2102 /// Registers_arm holds the register state of a thread in a 32-bit arm
2105 /// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2106 /// this uses more memory than required.
2107 class _LIBUNWIND_HIDDEN Registers_arm
{
2110 Registers_arm(const void *registers
);
2112 bool validRegister(int num
) const;
2113 uint32_t getRegister(int num
) const;
2114 void setRegister(int num
, uint32_t value
);
2115 bool validFloatRegister(int num
) const;
2116 unw_fpreg_t
getFloatRegister(int num
);
2117 void setFloatRegister(int num
, unw_fpreg_t value
);
2118 bool validVectorRegister(int num
) const;
2119 v128
getVectorRegister(int num
) const;
2120 void setVectorRegister(int num
, v128 value
);
2121 static const char *getRegisterName(int num
);
2123 restoreSavedFloatRegisters();
2124 restoreCoreAndJumpTo();
2126 static constexpr int lastDwarfRegNum() {
2127 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM
;
2129 static int getArch() { return REGISTERS_ARM
; }
2131 uint32_t getSP() const { return _registers
.__sp
; }
2132 void setSP(uint32_t value
) { _registers
.__sp
= value
; }
2133 uint32_t getIP() const { return _registers
.__pc
; }
2134 void setIP(uint32_t value
) { _registers
.__pc
= value
; }
2137 assert(_use_X_for_vfp_save
|| !_saved_vfp_d0_d15
);
2138 _use_X_for_vfp_save
= true;
2141 void restoreSavedFloatRegisters() {
2142 if (_saved_vfp_d0_d15
) {
2143 if (_use_X_for_vfp_save
)
2144 restoreVFPWithFLDMX(_vfp_d0_d15_pad
);
2146 restoreVFPWithFLDMD(_vfp_d0_d15_pad
);
2148 if (_saved_vfp_d16_d31
)
2149 restoreVFPv3(_vfp_d16_d31
);
2150 #if defined(__ARM_WMMX)
2152 restoreiWMMX(_iwmmx
);
2153 if (_saved_iwmmx_control
)
2154 restoreiWMMXControl(_iwmmx_control
);
2160 uint32_t __r
[13]; // r0-r12
2161 uint32_t __sp
; // Stack pointer r13
2162 uint32_t __lr
; // Link register r14
2163 uint32_t __pc
; // Program counter r15
2166 struct PseudoRegisters
{
2167 uint32_t __pac
; // Return Authentication Code (PAC)
2170 static void saveVFPWithFSTMD(void*);
2171 static void saveVFPWithFSTMX(void*);
2172 static void saveVFPv3(void*);
2173 static void restoreVFPWithFLDMD(void*);
2174 static void restoreVFPWithFLDMX(void*);
2175 static void restoreVFPv3(void*);
2176 #if defined(__ARM_WMMX)
2177 static void saveiWMMX(void*);
2178 static void saveiWMMXControl(uint32_t*);
2179 static void restoreiWMMX(void*);
2180 static void restoreiWMMXControl(uint32_t*);
2182 void restoreCoreAndJumpTo();
2186 PseudoRegisters _pseudo_registers
;
2188 // We save floating point registers lazily because we can't know ahead of
2189 // time which ones are used. See EHABI #4.7.
2191 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2193 // See EHABI #7.5 that explains how matching instruction sequences for load
2194 // and store need to be used to correctly restore the exact register bits.
2195 bool _use_X_for_vfp_save
;
2196 // Whether VFP D0-D15 are saved.
2197 bool _saved_vfp_d0_d15
;
2198 // Whether VFPv3 D16-D31 are saved.
2199 bool _saved_vfp_d16_d31
;
2200 // VFP registers D0-D15, + padding if saved using FSTMX
2201 unw_fpreg_t _vfp_d0_d15_pad
[17];
2202 // VFPv3 registers D16-D31, always saved using FSTMD
2203 unw_fpreg_t _vfp_d16_d31
[16];
2204 #if defined(__ARM_WMMX)
2205 // Whether iWMMX data registers are saved.
2207 // Whether iWMMX control registers are saved.
2208 mutable bool _saved_iwmmx_control
;
2210 unw_fpreg_t _iwmmx
[16];
2211 // iWMMX control registers
2212 mutable uint32_t _iwmmx_control
[4];
2216 inline Registers_arm::Registers_arm(const void *registers
)
2217 : _use_X_for_vfp_save(false),
2218 _saved_vfp_d0_d15(false),
2219 _saved_vfp_d16_d31(false) {
2220 static_assert((check_fit
<Registers_arm
, unw_context_t
>::does_fit
),
2221 "arm registers do not fit into unw_context_t");
2222 // See __unw_getcontext() note about data.
2223 memcpy(&_registers
, registers
, sizeof(_registers
));
2224 memset(&_pseudo_registers
, 0, sizeof(_pseudo_registers
));
2225 memset(&_vfp_d0_d15_pad
, 0, sizeof(_vfp_d0_d15_pad
));
2226 memset(&_vfp_d16_d31
, 0, sizeof(_vfp_d16_d31
));
2227 #if defined(__ARM_WMMX)
2228 _saved_iwmmx
= false;
2229 _saved_iwmmx_control
= false;
2230 memset(&_iwmmx
, 0, sizeof(_iwmmx
));
2231 memset(&_iwmmx_control
, 0, sizeof(_iwmmx_control
));
2235 inline Registers_arm::Registers_arm()
2236 : _use_X_for_vfp_save(false),
2237 _saved_vfp_d0_d15(false),
2238 _saved_vfp_d16_d31(false) {
2239 memset(&_registers
, 0, sizeof(_registers
));
2240 memset(&_pseudo_registers
, 0, sizeof(_pseudo_registers
));
2241 memset(&_vfp_d0_d15_pad
, 0, sizeof(_vfp_d0_d15_pad
));
2242 memset(&_vfp_d16_d31
, 0, sizeof(_vfp_d16_d31
));
2243 #if defined(__ARM_WMMX)
2244 _saved_iwmmx
= false;
2245 _saved_iwmmx_control
= false;
2246 memset(&_iwmmx
, 0, sizeof(_iwmmx
));
2247 memset(&_iwmmx_control
, 0, sizeof(_iwmmx_control
));
2251 inline bool Registers_arm::validRegister(int regNum
) const {
2252 // Returns true for all non-VFP registers supported by the EHABI
2253 // virtual register set (VRS).
2254 if (regNum
== UNW_REG_IP
)
2257 if (regNum
== UNW_REG_SP
)
2260 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R15
)
2263 #if defined(__ARM_WMMX)
2264 if (regNum
>= UNW_ARM_WC0
&& regNum
<= UNW_ARM_WC3
)
2268 #ifdef __ARM_FEATURE_PAUTH
2269 if (regNum
== UNW_ARM_RA_AUTH_CODE
)
2276 inline uint32_t Registers_arm::getRegister(int regNum
) const {
2277 if (regNum
== UNW_REG_SP
|| regNum
== UNW_ARM_SP
)
2278 return _registers
.__sp
;
2280 if (regNum
== UNW_ARM_LR
)
2281 return _registers
.__lr
;
2283 if (regNum
== UNW_REG_IP
|| regNum
== UNW_ARM_IP
)
2284 return _registers
.__pc
;
2286 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R12
)
2287 return _registers
.__r
[regNum
];
2289 #if defined(__ARM_WMMX)
2290 if (regNum
>= UNW_ARM_WC0
&& regNum
<= UNW_ARM_WC3
) {
2291 if (!_saved_iwmmx_control
) {
2292 _saved_iwmmx_control
= true;
2293 saveiWMMXControl(_iwmmx_control
);
2295 return _iwmmx_control
[regNum
- UNW_ARM_WC0
];
2299 #ifdef __ARM_FEATURE_PAUTH
2300 if (regNum
== UNW_ARM_RA_AUTH_CODE
)
2301 return _pseudo_registers
.__pac
;
2304 _LIBUNWIND_ABORT("unsupported arm register");
2307 inline void Registers_arm::setRegister(int regNum
, uint32_t value
) {
2308 if (regNum
== UNW_REG_SP
|| regNum
== UNW_ARM_SP
) {
2309 _registers
.__sp
= value
;
2313 if (regNum
== UNW_ARM_LR
) {
2314 _registers
.__lr
= value
;
2318 if (regNum
== UNW_REG_IP
|| regNum
== UNW_ARM_IP
) {
2319 _registers
.__pc
= value
;
2323 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R12
) {
2324 _registers
.__r
[regNum
] = value
;
2328 #if defined(__ARM_WMMX)
2329 if (regNum
>= UNW_ARM_WC0
&& regNum
<= UNW_ARM_WC3
) {
2330 if (!_saved_iwmmx_control
) {
2331 _saved_iwmmx_control
= true;
2332 saveiWMMXControl(_iwmmx_control
);
2334 _iwmmx_control
[regNum
- UNW_ARM_WC0
] = value
;
2339 if (regNum
== UNW_ARM_RA_AUTH_CODE
) {
2340 _pseudo_registers
.__pac
= value
;
2344 _LIBUNWIND_ABORT("unsupported arm register");
2347 inline const char *Registers_arm::getRegisterName(int regNum
) {
2350 case UNW_ARM_IP
: // UNW_ARM_R15 is alias
2352 case UNW_ARM_LR
: // UNW_ARM_R14 is alias
2355 case UNW_ARM_SP
: // UNW_ARM_R13 is alias
2512 return "unknown register";
2516 inline bool Registers_arm::validFloatRegister(int regNum
) const {
2517 // NOTE: Consider the intel MMX registers floating points so the
2518 // __unw_get_fpreg can be used to transmit the 64-bit data back.
2519 return ((regNum
>= UNW_ARM_D0
) && (regNum
<= UNW_ARM_D31
))
2520 #if defined(__ARM_WMMX)
2521 || ((regNum
>= UNW_ARM_WR0
) && (regNum
<= UNW_ARM_WR15
))
2526 inline unw_fpreg_t
Registers_arm::getFloatRegister(int regNum
) {
2527 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D15
) {
2528 if (!_saved_vfp_d0_d15
) {
2529 _saved_vfp_d0_d15
= true;
2530 if (_use_X_for_vfp_save
)
2531 saveVFPWithFSTMX(_vfp_d0_d15_pad
);
2533 saveVFPWithFSTMD(_vfp_d0_d15_pad
);
2535 return _vfp_d0_d15_pad
[regNum
- UNW_ARM_D0
];
2538 if (regNum
>= UNW_ARM_D16
&& regNum
<= UNW_ARM_D31
) {
2539 if (!_saved_vfp_d16_d31
) {
2540 _saved_vfp_d16_d31
= true;
2541 saveVFPv3(_vfp_d16_d31
);
2543 return _vfp_d16_d31
[regNum
- UNW_ARM_D16
];
2546 #if defined(__ARM_WMMX)
2547 if (regNum
>= UNW_ARM_WR0
&& regNum
<= UNW_ARM_WR15
) {
2548 if (!_saved_iwmmx
) {
2549 _saved_iwmmx
= true;
2552 return _iwmmx
[regNum
- UNW_ARM_WR0
];
2556 _LIBUNWIND_ABORT("Unknown ARM float register");
2559 inline void Registers_arm::setFloatRegister(int regNum
, unw_fpreg_t value
) {
2560 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D15
) {
2561 if (!_saved_vfp_d0_d15
) {
2562 _saved_vfp_d0_d15
= true;
2563 if (_use_X_for_vfp_save
)
2564 saveVFPWithFSTMX(_vfp_d0_d15_pad
);
2566 saveVFPWithFSTMD(_vfp_d0_d15_pad
);
2568 _vfp_d0_d15_pad
[regNum
- UNW_ARM_D0
] = value
;
2572 if (regNum
>= UNW_ARM_D16
&& regNum
<= UNW_ARM_D31
) {
2573 if (!_saved_vfp_d16_d31
) {
2574 _saved_vfp_d16_d31
= true;
2575 saveVFPv3(_vfp_d16_d31
);
2577 _vfp_d16_d31
[regNum
- UNW_ARM_D16
] = value
;
2581 #if defined(__ARM_WMMX)
2582 if (regNum
>= UNW_ARM_WR0
&& regNum
<= UNW_ARM_WR15
) {
2583 if (!_saved_iwmmx
) {
2584 _saved_iwmmx
= true;
2587 _iwmmx
[regNum
- UNW_ARM_WR0
] = value
;
2592 _LIBUNWIND_ABORT("Unknown ARM float register");
2595 inline bool Registers_arm::validVectorRegister(int) const {
2599 inline v128
Registers_arm::getVectorRegister(int) const {
2600 _LIBUNWIND_ABORT("ARM vector support not implemented");
2603 inline void Registers_arm::setVectorRegister(int, v128
) {
2604 _LIBUNWIND_ABORT("ARM vector support not implemented");
2606 #endif // _LIBUNWIND_TARGET_ARM
2609 #if defined(_LIBUNWIND_TARGET_OR1K)
2610 /// Registers_or1k holds the register state of a thread in an OpenRISC1000
2612 class _LIBUNWIND_HIDDEN Registers_or1k
{
2615 Registers_or1k(const void *registers
);
2617 bool validRegister(int num
) const;
2618 uint32_t getRegister(int num
) const;
2619 void setRegister(int num
, uint32_t value
);
2620 bool validFloatRegister(int num
) const;
2621 double getFloatRegister(int num
) const;
2622 void setFloatRegister(int num
, double value
);
2623 bool validVectorRegister(int num
) const;
2624 v128
getVectorRegister(int num
) const;
2625 void setVectorRegister(int num
, v128 value
);
2626 static const char *getRegisterName(int num
);
2628 static constexpr int lastDwarfRegNum() {
2629 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K
;
2631 static int getArch() { return REGISTERS_OR1K
; }
2633 uint64_t getSP() const { return _registers
.__r
[1]; }
2634 void setSP(uint32_t value
) { _registers
.__r
[1] = value
; }
2635 uint64_t getIP() const { return _registers
.__pc
; }
2636 void setIP(uint32_t value
) { _registers
.__pc
= value
; }
2639 struct or1k_thread_state_t
{
2640 unsigned int __r
[32]; // r0-r31
2641 unsigned int __pc
; // Program counter
2642 unsigned int __epcr
; // Program counter at exception
2645 or1k_thread_state_t _registers
;
2648 inline Registers_or1k::Registers_or1k(const void *registers
) {
2649 static_assert((check_fit
<Registers_or1k
, unw_context_t
>::does_fit
),
2650 "or1k registers do not fit into unw_context_t");
2651 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
2652 sizeof(_registers
));
2655 inline Registers_or1k::Registers_or1k() {
2656 memset(&_registers
, 0, sizeof(_registers
));
2659 inline bool Registers_or1k::validRegister(int regNum
) const {
2660 if (regNum
== UNW_REG_IP
)
2662 if (regNum
== UNW_REG_SP
)
2666 if (regNum
<= UNW_OR1K_R31
)
2668 if (regNum
== UNW_OR1K_EPCR
)
2673 inline uint32_t Registers_or1k::getRegister(int regNum
) const {
2674 if (regNum
>= UNW_OR1K_R0
&& regNum
<= UNW_OR1K_R31
)
2675 return _registers
.__r
[regNum
- UNW_OR1K_R0
];
2679 return _registers
.__pc
;
2681 return _registers
.__r
[1];
2683 return _registers
.__epcr
;
2685 _LIBUNWIND_ABORT("unsupported or1k register");
2688 inline void Registers_or1k::setRegister(int regNum
, uint32_t value
) {
2689 if (regNum
>= UNW_OR1K_R0
&& regNum
<= UNW_OR1K_R31
) {
2690 _registers
.__r
[regNum
- UNW_OR1K_R0
] = value
;
2696 _registers
.__pc
= value
;
2699 _registers
.__r
[1] = value
;
2702 _registers
.__epcr
= value
;
2705 _LIBUNWIND_ABORT("unsupported or1k register");
2708 inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2712 inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2713 _LIBUNWIND_ABORT("or1k float support not implemented");
2716 inline void Registers_or1k::setFloatRegister(int /* regNum */,
2717 double /* value */) {
2718 _LIBUNWIND_ABORT("or1k float support not implemented");
2721 inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2725 inline v128
Registers_or1k::getVectorRegister(int /* regNum */) const {
2726 _LIBUNWIND_ABORT("or1k vector support not implemented");
2729 inline void Registers_or1k::setVectorRegister(int /* regNum */, v128
/* value */) {
2730 _LIBUNWIND_ABORT("or1k vector support not implemented");
2733 inline const char *Registers_or1k::getRegisterName(int regNum
) {
2802 return "unknown register";
2806 #endif // _LIBUNWIND_TARGET_OR1K
2808 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
2809 /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2811 class _LIBUNWIND_HIDDEN Registers_mips_o32
{
2813 Registers_mips_o32();
2814 Registers_mips_o32(const void *registers
);
2816 bool validRegister(int num
) const;
2817 uint32_t getRegister(int num
) const;
2818 void setRegister(int num
, uint32_t value
);
2819 bool validFloatRegister(int num
) const;
2820 double getFloatRegister(int num
) const;
2821 void setFloatRegister(int num
, double value
);
2822 bool validVectorRegister(int num
) const;
2823 v128
getVectorRegister(int num
) const;
2824 void setVectorRegister(int num
, v128 value
);
2825 static const char *getRegisterName(int num
);
2827 static constexpr int lastDwarfRegNum() {
2828 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
;
2830 static int getArch() { return REGISTERS_MIPS_O32
; }
2832 uint32_t getSP() const { return _registers
.__r
[29]; }
2833 void setSP(uint32_t value
) { _registers
.__r
[29] = value
; }
2834 uint32_t getIP() const { return _registers
.__pc
; }
2835 void setIP(uint32_t value
) { _registers
.__pc
= value
; }
2838 struct mips_o32_thread_state_t
{
2845 mips_o32_thread_state_t _registers
;
2846 #ifdef __mips_hard_float
2847 /// O32 with 32-bit floating point registers only uses half of this
2848 /// space. However, using the same layout for 32-bit vs 64-bit
2849 /// floating point registers results in a single context size for
2850 /// O32 with hard float.
2856 inline Registers_mips_o32::Registers_mips_o32(const void *registers
) {
2857 static_assert((check_fit
<Registers_mips_o32
, unw_context_t
>::does_fit
),
2858 "mips_o32 registers do not fit into unw_context_t");
2859 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
2860 sizeof(_registers
));
2863 inline Registers_mips_o32::Registers_mips_o32() {
2864 memset(&_registers
, 0, sizeof(_registers
));
2867 inline bool Registers_mips_o32::validRegister(int regNum
) const {
2868 if (regNum
== UNW_REG_IP
)
2870 if (regNum
== UNW_REG_SP
)
2874 if (regNum
<= UNW_MIPS_R31
)
2876 #if __mips_isa_rev < 6
2877 if (regNum
== UNW_MIPS_HI
)
2879 if (regNum
== UNW_MIPS_LO
)
2882 #if defined(__mips_hard_float) && __mips_fpr == 32
2883 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
)
2886 // FIXME: DSP accumulator registers, MSA registers
2890 inline uint32_t Registers_mips_o32::getRegister(int regNum
) const {
2891 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
)
2892 return _registers
.__r
[regNum
- UNW_MIPS_R0
];
2893 #if defined(__mips_hard_float) && __mips_fpr == 32
2894 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
) {
2897 if (regNum
% 2 == 0)
2898 p
= (uint32_t *)&_floats
[regNum
- UNW_MIPS_F0
];
2900 p
= (uint32_t *)&_floats
[(regNum
- 1) - UNW_MIPS_F0
] + 1;
2907 return _registers
.__pc
;
2909 return _registers
.__r
[29];
2910 #if __mips_isa_rev < 6
2912 return _registers
.__hi
;
2914 return _registers
.__lo
;
2917 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2920 inline void Registers_mips_o32::setRegister(int regNum
, uint32_t value
) {
2921 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
) {
2922 _registers
.__r
[regNum
- UNW_MIPS_R0
] = value
;
2925 #if defined(__mips_hard_float) && __mips_fpr == 32
2926 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
) {
2929 if (regNum
% 2 == 0)
2930 p
= (uint32_t *)&_floats
[regNum
- UNW_MIPS_F0
];
2932 p
= (uint32_t *)&_floats
[(regNum
- 1) - UNW_MIPS_F0
] + 1;
2940 _registers
.__pc
= value
;
2943 _registers
.__r
[29] = value
;
2945 #if __mips_isa_rev < 6
2947 _registers
.__hi
= value
;
2950 _registers
.__lo
= value
;
2954 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2957 inline bool Registers_mips_o32::validFloatRegister(int regNum
) const {
2958 #if defined(__mips_hard_float) && __mips_fpr == 64
2959 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
)
2967 inline double Registers_mips_o32::getFloatRegister(int regNum
) const {
2968 #if defined(__mips_hard_float) && __mips_fpr == 64
2969 assert(validFloatRegister(regNum
));
2970 return _floats
[regNum
- UNW_MIPS_F0
];
2973 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2977 inline void Registers_mips_o32::setFloatRegister(int regNum
,
2979 #if defined(__mips_hard_float) && __mips_fpr == 64
2980 assert(validFloatRegister(regNum
));
2981 _floats
[regNum
- UNW_MIPS_F0
] = value
;
2985 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2989 inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
2993 inline v128
Registers_mips_o32::getVectorRegister(int /* regNum */) const {
2994 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2997 inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128
/* value */) {
2998 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
3001 inline const char *Registers_mips_o32::getRegisterName(int regNum
) {
3131 #if __mips_isa_rev < 6
3138 return "unknown register";
3141 #endif // _LIBUNWIND_TARGET_MIPS_O32
3143 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3144 /// Registers_mips_newabi holds the register state of a thread in a
3145 /// MIPS process using NEWABI (the N32 or N64 ABIs).
3146 class _LIBUNWIND_HIDDEN Registers_mips_newabi
{
3148 Registers_mips_newabi();
3149 Registers_mips_newabi(const void *registers
);
3151 bool validRegister(int num
) const;
3152 uint64_t getRegister(int num
) const;
3153 void setRegister(int num
, uint64_t value
);
3154 bool validFloatRegister(int num
) const;
3155 double getFloatRegister(int num
) const;
3156 void setFloatRegister(int num
, double value
);
3157 bool validVectorRegister(int num
) const;
3158 v128
getVectorRegister(int num
) const;
3159 void setVectorRegister(int num
, v128 value
);
3160 static const char *getRegisterName(int num
);
3162 static constexpr int lastDwarfRegNum() {
3163 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
;
3165 static int getArch() { return REGISTERS_MIPS_NEWABI
; }
3167 uint64_t getSP() const { return _registers
.__r
[29]; }
3168 void setSP(uint64_t value
) { _registers
.__r
[29] = value
; }
3169 uint64_t getIP() const { return _registers
.__pc
; }
3170 void setIP(uint64_t value
) { _registers
.__pc
= value
; }
3173 struct mips_newabi_thread_state_t
{
3180 mips_newabi_thread_state_t _registers
;
3181 #ifdef __mips_hard_float
3186 inline Registers_mips_newabi::Registers_mips_newabi(const void *registers
) {
3187 static_assert((check_fit
<Registers_mips_newabi
, unw_context_t
>::does_fit
),
3188 "mips_newabi registers do not fit into unw_context_t");
3189 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
3190 sizeof(_registers
));
3193 inline Registers_mips_newabi::Registers_mips_newabi() {
3194 memset(&_registers
, 0, sizeof(_registers
));
3197 inline bool Registers_mips_newabi::validRegister(int regNum
) const {
3198 if (regNum
== UNW_REG_IP
)
3200 if (regNum
== UNW_REG_SP
)
3204 if (regNum
<= UNW_MIPS_R31
)
3206 #if __mips_isa_rev < 6
3207 if (regNum
== UNW_MIPS_HI
)
3209 if (regNum
== UNW_MIPS_LO
)
3212 // FIXME: Hard float, DSP accumulator registers, MSA registers
3216 inline uint64_t Registers_mips_newabi::getRegister(int regNum
) const {
3217 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
)
3218 return _registers
.__r
[regNum
- UNW_MIPS_R0
];
3222 return _registers
.__pc
;
3224 return _registers
.__r
[29];
3225 #if __mips_isa_rev < 6
3227 return _registers
.__hi
;
3229 return _registers
.__lo
;
3232 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3235 inline void Registers_mips_newabi::setRegister(int regNum
, uint64_t value
) {
3236 if (regNum
>= UNW_MIPS_R0
&& regNum
<= UNW_MIPS_R31
) {
3237 _registers
.__r
[regNum
- UNW_MIPS_R0
] = value
;
3243 _registers
.__pc
= value
;
3246 _registers
.__r
[29] = value
;
3248 #if __mips_isa_rev < 6
3250 _registers
.__hi
= value
;
3253 _registers
.__lo
= value
;
3257 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3260 inline bool Registers_mips_newabi::validFloatRegister(int regNum
) const {
3261 #ifdef __mips_hard_float
3262 if (regNum
>= UNW_MIPS_F0
&& regNum
<= UNW_MIPS_F31
)
3270 inline double Registers_mips_newabi::getFloatRegister(int regNum
) const {
3271 #ifdef __mips_hard_float
3272 assert(validFloatRegister(regNum
));
3273 return _floats
[regNum
- UNW_MIPS_F0
];
3276 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3280 inline void Registers_mips_newabi::setFloatRegister(int regNum
,
3282 #ifdef __mips_hard_float
3283 assert(validFloatRegister(regNum
));
3284 _floats
[regNum
- UNW_MIPS_F0
] = value
;
3288 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3292 inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3296 inline v128
Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3297 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3300 inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128
/* value */) {
3301 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3304 inline const char *Registers_mips_newabi::getRegisterName(int regNum
) {
3434 #if __mips_isa_rev < 6
3441 return "unknown register";
3444 #endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3446 #if defined(_LIBUNWIND_TARGET_SPARC)
3447 /// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3449 class _LIBUNWIND_HIDDEN Registers_sparc
{
3452 Registers_sparc(const void *registers
);
3454 bool validRegister(int num
) const;
3455 uint32_t getRegister(int num
) const;
3456 void setRegister(int num
, uint32_t value
);
3457 bool validFloatRegister(int num
) const;
3458 double getFloatRegister(int num
) const;
3459 void setFloatRegister(int num
, double value
);
3460 bool validVectorRegister(int num
) const;
3461 v128
getVectorRegister(int num
) const;
3462 void setVectorRegister(int num
, v128 value
);
3463 static const char *getRegisterName(int num
);
3465 static constexpr int lastDwarfRegNum() {
3466 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
;
3468 static int getArch() { return REGISTERS_SPARC
; }
3470 uint64_t getSP() const { return _registers
.__regs
[UNW_SPARC_O6
]; }
3471 void setSP(uint32_t value
) { _registers
.__regs
[UNW_SPARC_O6
] = value
; }
3472 uint64_t getIP() const { return _registers
.__regs
[UNW_SPARC_O7
]; }
3473 void setIP(uint32_t value
) { _registers
.__regs
[UNW_SPARC_O7
] = value
; }
3476 struct sparc_thread_state_t
{
3477 unsigned int __regs
[32];
3480 sparc_thread_state_t _registers
;
3483 inline Registers_sparc::Registers_sparc(const void *registers
) {
3484 static_assert((check_fit
<Registers_sparc
, unw_context_t
>::does_fit
),
3485 "sparc registers do not fit into unw_context_t");
3486 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
3487 sizeof(_registers
));
3490 inline Registers_sparc::Registers_sparc() {
3491 memset(&_registers
, 0, sizeof(_registers
));
3494 inline bool Registers_sparc::validRegister(int regNum
) const {
3495 if (regNum
== UNW_REG_IP
)
3497 if (regNum
== UNW_REG_SP
)
3501 if (regNum
<= UNW_SPARC_I7
)
3506 inline uint32_t Registers_sparc::getRegister(int regNum
) const {
3507 if ((UNW_SPARC_G0
<= regNum
) && (regNum
<= UNW_SPARC_I7
)) {
3508 return _registers
.__regs
[regNum
];
3513 return _registers
.__regs
[UNW_SPARC_O7
];
3515 return _registers
.__regs
[UNW_SPARC_O6
];
3517 _LIBUNWIND_ABORT("unsupported sparc register");
3520 inline void Registers_sparc::setRegister(int regNum
, uint32_t value
) {
3521 if ((UNW_SPARC_G0
<= regNum
) && (regNum
<= UNW_SPARC_I7
)) {
3522 _registers
.__regs
[regNum
] = value
;
3528 _registers
.__regs
[UNW_SPARC_O7
] = value
;
3531 _registers
.__regs
[UNW_SPARC_O6
] = value
;
3534 _LIBUNWIND_ABORT("unsupported sparc register");
3537 inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3539 inline double Registers_sparc::getFloatRegister(int) const {
3540 _LIBUNWIND_ABORT("no Sparc float registers");
3543 inline void Registers_sparc::setFloatRegister(int, double) {
3544 _LIBUNWIND_ABORT("no Sparc float registers");
3547 inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3549 inline v128
Registers_sparc::getVectorRegister(int) const {
3550 _LIBUNWIND_ABORT("no Sparc vector registers");
3553 inline void Registers_sparc::setVectorRegister(int, v128
) {
3554 _LIBUNWIND_ABORT("no Sparc vector registers");
3557 inline const char *Registers_sparc::getRegisterName(int regNum
) {
3627 return "unknown register";
3630 #endif // _LIBUNWIND_TARGET_SPARC
3632 #if defined(_LIBUNWIND_TARGET_SPARC64)
3633 /// Registers_sparc64 holds the register state of a thread in a 64-bit
3635 class _LIBUNWIND_HIDDEN Registers_sparc64
{
3637 Registers_sparc64() = default;
3638 Registers_sparc64(const void *registers
);
3640 bool validRegister(int num
) const;
3641 uint64_t getRegister(int num
) const;
3642 void setRegister(int num
, uint64_t value
);
3643 bool validFloatRegister(int num
) const;
3644 double getFloatRegister(int num
) const;
3645 void setFloatRegister(int num
, double value
);
3646 bool validVectorRegister(int num
) const;
3647 v128
getVectorRegister(int num
) const;
3648 void setVectorRegister(int num
, v128 value
);
3649 const char *getRegisterName(int num
);
3651 static constexpr int lastDwarfRegNum() {
3652 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64
;
3654 static int getArch() { return REGISTERS_SPARC64
; }
3656 uint64_t getSP() const { return _registers
.__regs
[UNW_SPARC_O6
] + 2047; }
3657 void setSP(uint64_t value
) { _registers
.__regs
[UNW_SPARC_O6
] = value
- 2047; }
3658 uint64_t getIP() const { return _registers
.__regs
[UNW_SPARC_O7
]; }
3659 void setIP(uint64_t value
) { _registers
.__regs
[UNW_SPARC_O7
] = value
; }
3660 uint64_t getWCookie() const { return _wcookie
; }
3663 struct sparc64_thread_state_t
{
3664 uint64_t __regs
[32];
3667 sparc64_thread_state_t _registers
{};
3668 uint64_t _wcookie
= 0;
3671 inline Registers_sparc64::Registers_sparc64(const void *registers
) {
3672 static_assert((check_fit
<Registers_sparc64
, unw_context_t
>::does_fit
),
3673 "sparc64 registers do not fit into unw_context_t");
3674 memcpy(&_registers
, registers
, sizeof(_registers
));
3676 static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
3680 inline bool Registers_sparc64::validRegister(int regNum
) const {
3681 if (regNum
== UNW_REG_IP
)
3683 if (regNum
== UNW_REG_SP
)
3687 if (regNum
<= UNW_SPARC_I7
)
3692 inline uint64_t Registers_sparc64::getRegister(int regNum
) const {
3693 if (regNum
>= UNW_SPARC_G0
&& regNum
<= UNW_SPARC_I7
)
3694 return _registers
.__regs
[regNum
];
3698 return _registers
.__regs
[UNW_SPARC_O7
];
3700 return _registers
.__regs
[UNW_SPARC_O6
] + 2047;
3702 _LIBUNWIND_ABORT("unsupported sparc64 register");
3705 inline void Registers_sparc64::setRegister(int regNum
, uint64_t value
) {
3706 if (regNum
>= UNW_SPARC_G0
&& regNum
<= UNW_SPARC_I7
) {
3707 _registers
.__regs
[regNum
] = value
;
3713 _registers
.__regs
[UNW_SPARC_O7
] = value
;
3716 _registers
.__regs
[UNW_SPARC_O6
] = value
- 2047;
3719 _LIBUNWIND_ABORT("unsupported sparc64 register");
3722 inline bool Registers_sparc64::validFloatRegister(int) const { return false; }
3724 inline double Registers_sparc64::getFloatRegister(int) const {
3725 _LIBUNWIND_ABORT("no sparc64 float registers");
3728 inline void Registers_sparc64::setFloatRegister(int, double) {
3729 _LIBUNWIND_ABORT("no sparc64 float registers");
3732 inline bool Registers_sparc64::validVectorRegister(int) const { return false; }
3734 inline v128
Registers_sparc64::getVectorRegister(int) const {
3735 _LIBUNWIND_ABORT("no sparc64 vector registers");
3738 inline void Registers_sparc64::setVectorRegister(int, v128
) {
3739 _LIBUNWIND_ABORT("no sparc64 vector registers");
3742 inline const char *Registers_sparc64::getRegisterName(int regNum
) {
3812 return "unknown register";
3815 #endif // _LIBUNWIND_TARGET_SPARC64
3817 #if defined(_LIBUNWIND_TARGET_HEXAGON)
3818 /// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
3820 class _LIBUNWIND_HIDDEN Registers_hexagon
{
3822 Registers_hexagon();
3823 Registers_hexagon(const void *registers
);
3825 bool validRegister(int num
) const;
3826 uint32_t getRegister(int num
) const;
3827 void setRegister(int num
, uint32_t value
);
3828 bool validFloatRegister(int num
) const;
3829 double getFloatRegister(int num
) const;
3830 void setFloatRegister(int num
, double value
);
3831 bool validVectorRegister(int num
) const;
3832 v128
getVectorRegister(int num
) const;
3833 void setVectorRegister(int num
, v128 value
);
3834 const char *getRegisterName(int num
);
3836 static constexpr int lastDwarfRegNum() {
3837 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON
;
3839 static int getArch() { return REGISTERS_HEXAGON
; }
3841 uint32_t getSP() const { return _registers
.__r
[UNW_HEXAGON_R29
]; }
3842 void setSP(uint32_t value
) { _registers
.__r
[UNW_HEXAGON_R29
] = value
; }
3843 uint32_t getIP() const { return _registers
.__r
[UNW_HEXAGON_PC
]; }
3844 void setIP(uint32_t value
) { _registers
.__r
[UNW_HEXAGON_PC
] = value
; }
3847 struct hexagon_thread_state_t
{
3848 unsigned int __r
[35];
3851 hexagon_thread_state_t _registers
;
3854 inline Registers_hexagon::Registers_hexagon(const void *registers
) {
3855 static_assert((check_fit
<Registers_hexagon
, unw_context_t
>::does_fit
),
3856 "hexagon registers do not fit into unw_context_t");
3857 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
3858 sizeof(_registers
));
3861 inline Registers_hexagon::Registers_hexagon() {
3862 memset(&_registers
, 0, sizeof(_registers
));
3865 inline bool Registers_hexagon::validRegister(int regNum
) const {
3866 if (regNum
<= UNW_HEXAGON_R31
)
3871 inline uint32_t Registers_hexagon::getRegister(int regNum
) const {
3872 if (regNum
>= UNW_HEXAGON_R0
&& regNum
<= UNW_HEXAGON_R31
)
3873 return _registers
.__r
[regNum
- UNW_HEXAGON_R0
];
3877 return _registers
.__r
[UNW_HEXAGON_PC
];
3879 return _registers
.__r
[UNW_HEXAGON_R29
];
3881 _LIBUNWIND_ABORT("unsupported hexagon register");
3884 inline void Registers_hexagon::setRegister(int regNum
, uint32_t value
) {
3885 if (regNum
>= UNW_HEXAGON_R0
&& regNum
<= UNW_HEXAGON_R31
) {
3886 _registers
.__r
[regNum
- UNW_HEXAGON_R0
] = value
;
3892 _registers
.__r
[UNW_HEXAGON_PC
] = value
;
3895 _registers
.__r
[UNW_HEXAGON_R29
] = value
;
3898 _LIBUNWIND_ABORT("unsupported hexagon register");
3901 inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {
3905 inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {
3906 _LIBUNWIND_ABORT("hexagon float support not implemented");
3909 inline void Registers_hexagon::setFloatRegister(int /* regNum */,
3910 double /* value */) {
3911 _LIBUNWIND_ABORT("hexagon float support not implemented");
3914 inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {
3918 inline v128
Registers_hexagon::getVectorRegister(int /* regNum */) const {
3919 _LIBUNWIND_ABORT("hexagon vector support not implemented");
3922 inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128
/* value */) {
3923 _LIBUNWIND_ABORT("hexagon vector support not implemented");
3926 inline const char *Registers_hexagon::getRegisterName(int regNum
) {
3928 case UNW_HEXAGON_R0
:
3930 case UNW_HEXAGON_R1
:
3932 case UNW_HEXAGON_R2
:
3934 case UNW_HEXAGON_R3
:
3936 case UNW_HEXAGON_R4
:
3938 case UNW_HEXAGON_R5
:
3940 case UNW_HEXAGON_R6
:
3942 case UNW_HEXAGON_R7
:
3944 case UNW_HEXAGON_R8
:
3946 case UNW_HEXAGON_R9
:
3948 case UNW_HEXAGON_R10
:
3950 case UNW_HEXAGON_R11
:
3952 case UNW_HEXAGON_R12
:
3954 case UNW_HEXAGON_R13
:
3956 case UNW_HEXAGON_R14
:
3958 case UNW_HEXAGON_R15
:
3960 case UNW_HEXAGON_R16
:
3962 case UNW_HEXAGON_R17
:
3964 case UNW_HEXAGON_R18
:
3966 case UNW_HEXAGON_R19
:
3968 case UNW_HEXAGON_R20
:
3970 case UNW_HEXAGON_R21
:
3972 case UNW_HEXAGON_R22
:
3974 case UNW_HEXAGON_R23
:
3976 case UNW_HEXAGON_R24
:
3978 case UNW_HEXAGON_R25
:
3980 case UNW_HEXAGON_R26
:
3982 case UNW_HEXAGON_R27
:
3984 case UNW_HEXAGON_R28
:
3986 case UNW_HEXAGON_R29
:
3988 case UNW_HEXAGON_R30
:
3990 case UNW_HEXAGON_R31
:
3993 return "unknown register";
3997 #endif // _LIBUNWIND_TARGET_HEXAGON
4000 #if defined(_LIBUNWIND_TARGET_RISCV)
4001 /// Registers_riscv holds the register state of a thread in a RISC-V
4004 // This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.
4006 # if __riscv_xlen == 32
4007 typedef uint32_t reg_t
;
4008 # elif __riscv_xlen == 64
4009 typedef uint64_t reg_t
;
4011 # error "Unsupported __riscv_xlen"
4014 # if defined(__riscv_flen)
4015 # if __riscv_flen == 64
4016 typedef double fp_t
;
4017 # elif __riscv_flen == 32
4020 # error "Unsupported __riscv_flen"
4023 // This is just for suppressing undeclared error of fp_t.
4024 typedef double fp_t
;
4027 // Use Max possible width when cross unwinding
4028 typedef uint64_t reg_t
;
4029 typedef double fp_t
;
4030 # define __riscv_xlen 64
4031 # define __riscv_flen 64
4034 /// Registers_riscv holds the register state of a thread.
4035 class _LIBUNWIND_HIDDEN Registers_riscv
{
4038 Registers_riscv(const void *registers
);
4040 bool validRegister(int num
) const;
4041 reg_t
getRegister(int num
) const;
4042 void setRegister(int num
, reg_t value
);
4043 bool validFloatRegister(int num
) const;
4044 fp_t
getFloatRegister(int num
) const;
4045 void setFloatRegister(int num
, fp_t value
);
4046 bool validVectorRegister(int num
) const;
4047 v128
getVectorRegister(int num
) const;
4048 void setVectorRegister(int num
, v128 value
);
4049 static const char *getRegisterName(int num
);
4051 static constexpr int lastDwarfRegNum() {
4052 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV
;
4054 static int getArch() { return REGISTERS_RISCV
; }
4056 reg_t
getSP() const { return _registers
[2]; }
4057 void setSP(reg_t value
) { _registers
[2] = value
; }
4058 reg_t
getIP() const { return _registers
[0]; }
4059 void setIP(reg_t value
) { _registers
[0] = value
; }
4062 // _registers[0] holds the pc
4063 reg_t _registers
[32];
4064 # if defined(__riscv_flen)
4069 inline Registers_riscv::Registers_riscv(const void *registers
) {
4070 static_assert((check_fit
<Registers_riscv
, unw_context_t
>::does_fit
),
4071 "riscv registers do not fit into unw_context_t");
4072 memcpy(&_registers
, registers
, sizeof(_registers
));
4073 # if __riscv_xlen == 32
4074 static_assert(sizeof(_registers
) == 0x80,
4075 "expected float registers to be at offset 128");
4076 # elif __riscv_xlen == 64
4077 static_assert(sizeof(_registers
) == 0x100,
4078 "expected float registers to be at offset 256");
4080 # error "Unexpected float registers."
4083 # if defined(__riscv_flen)
4085 static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
4090 inline Registers_riscv::Registers_riscv() {
4091 memset(&_registers
, 0, sizeof(_registers
));
4092 # if defined(__riscv_flen)
4093 memset(&_floats
, 0, sizeof(_floats
));
4097 inline bool Registers_riscv::validRegister(int regNum
) const {
4098 if (regNum
== UNW_REG_IP
)
4100 if (regNum
== UNW_REG_SP
)
4104 if (regNum
== UNW_RISCV_VLENB
)
4106 if (regNum
> UNW_RISCV_F31
)
4111 inline reg_t
Registers_riscv::getRegister(int regNum
) const {
4112 if (regNum
== UNW_REG_IP
)
4113 return _registers
[0];
4114 if (regNum
== UNW_REG_SP
)
4115 return _registers
[2];
4116 if (regNum
== UNW_RISCV_X0
)
4118 if ((regNum
> 0) && (regNum
< 32))
4119 return _registers
[regNum
];
4120 if (regNum
== UNW_RISCV_VLENB
) {
4122 __asm__("csrr %0, 0xC22" : "=r"(vlenb
));
4125 _LIBUNWIND_ABORT("unsupported riscv register");
4128 inline void Registers_riscv::setRegister(int regNum
, reg_t value
) {
4129 if (regNum
== UNW_REG_IP
)
4130 _registers
[0] = value
;
4131 else if (regNum
== UNW_REG_SP
)
4132 _registers
[2] = value
;
4133 else if (regNum
== UNW_RISCV_X0
)
4134 /* x0 is hardwired to zero */
4136 else if ((regNum
> 0) && (regNum
< 32))
4137 _registers
[regNum
] = value
;
4139 _LIBUNWIND_ABORT("unsupported riscv register");
4142 inline const char *Registers_riscv::getRegisterName(int regNum
) {
4276 case UNW_RISCV_VLENB
:
4279 return "unknown register";
4283 inline bool Registers_riscv::validFloatRegister(int regNum
) const {
4284 # if defined(__riscv_flen)
4285 if (regNum
< UNW_RISCV_F0
)
4287 if (regNum
> UNW_RISCV_F31
)
4296 inline fp_t
Registers_riscv::getFloatRegister(int regNum
) const {
4297 # if defined(__riscv_flen)
4298 assert(validFloatRegister(regNum
));
4299 return _floats
[regNum
- UNW_RISCV_F0
];
4302 _LIBUNWIND_ABORT("libunwind not built with float support");
4306 inline void Registers_riscv::setFloatRegister(int regNum
, fp_t value
) {
4307 # if defined(__riscv_flen)
4308 assert(validFloatRegister(regNum
));
4309 _floats
[regNum
- UNW_RISCV_F0
] = value
;
4313 _LIBUNWIND_ABORT("libunwind not built with float support");
4317 inline bool Registers_riscv::validVectorRegister(int) const {
4321 inline v128
Registers_riscv::getVectorRegister(int) const {
4322 _LIBUNWIND_ABORT("no riscv vector register support yet");
4325 inline void Registers_riscv::setVectorRegister(int, v128
) {
4326 _LIBUNWIND_ABORT("no riscv vector register support yet");
4328 #endif // _LIBUNWIND_TARGET_RISCV
4330 #if defined(_LIBUNWIND_TARGET_VE)
4331 /// Registers_ve holds the register state of a thread in a VE process.
4332 class _LIBUNWIND_HIDDEN Registers_ve
{
4335 Registers_ve(const void *registers
);
4337 bool validRegister(int num
) const;
4338 uint64_t getRegister(int num
) const;
4339 void setRegister(int num
, uint64_t value
);
4340 bool validFloatRegister(int num
) const;
4341 double getFloatRegister(int num
) const;
4342 void setFloatRegister(int num
, double value
);
4343 bool validVectorRegister(int num
) const;
4344 v128
getVectorRegister(int num
) const;
4345 void setVectorRegister(int num
, v128 value
);
4346 static const char *getRegisterName(int num
);
4348 static constexpr int lastDwarfRegNum() {
4349 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE
;
4351 static int getArch() { return REGISTERS_VE
; }
4353 uint64_t getSP() const { return _registers
.__s
[11]; }
4354 void setSP(uint64_t value
) { _registers
.__s
[11] = value
; }
4355 uint64_t getIP() const { return _registers
.__ic
; }
4356 void setIP(uint64_t value
) { _registers
.__ic
= value
; }
4359 // FIXME: Need to store not only scalar registers but also vector and vector
4360 // mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes
4361 // 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for
4362 // SjLj exception support only, so Registers_ve is not implemented completely.
4363 struct ve_thread_state_t
{
4364 uint64_t __s
[64]; // s0-s64
4365 uint64_t __ic
; // Instruction counter (IC)
4366 uint64_t __vixr
; // Vector Index Register
4367 uint64_t __vl
; // Vector Length Register
4370 ve_thread_state_t _registers
; // total 67 registers
4372 // Currently no vector register is preserved.
4375 inline Registers_ve::Registers_ve(const void *registers
) {
4376 static_assert((check_fit
<Registers_ve
, unw_context_t
>::does_fit
),
4377 "ve registers do not fit into unw_context_t");
4378 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
4379 sizeof(_registers
));
4380 static_assert(sizeof(_registers
) == 536,
4381 "expected vector register offset to be 536");
4384 inline Registers_ve::Registers_ve() {
4385 memset(&_registers
, 0, sizeof(_registers
));
4388 inline bool Registers_ve::validRegister(int regNum
) const {
4389 if (regNum
>= UNW_VE_S0
&& regNum
<= UNW_VE_S63
)
4403 inline uint64_t Registers_ve::getRegister(int regNum
) const {
4404 if (regNum
>= UNW_VE_S0
&& regNum
<= UNW_VE_S63
)
4405 return _registers
.__s
[regNum
- UNW_VE_S0
];
4409 return _registers
.__ic
;
4411 return _registers
.__s
[11];
4413 return _registers
.__vixr
;
4415 return _registers
.__vl
;
4417 _LIBUNWIND_ABORT("unsupported ve register");
4420 inline void Registers_ve::setRegister(int regNum
, uint64_t value
) {
4421 if (regNum
>= UNW_VE_S0
&& regNum
<= UNW_VE_S63
) {
4422 _registers
.__s
[regNum
- UNW_VE_S0
] = value
;
4428 _registers
.__ic
= value
;
4431 _registers
.__s
[11] = value
;
4434 _registers
.__vixr
= value
;
4437 _registers
.__vl
= value
;
4440 _LIBUNWIND_ABORT("unsupported ve register");
4443 inline bool Registers_ve::validFloatRegister(int /* regNum */) const {
4447 inline double Registers_ve::getFloatRegister(int /* regNum */) const {
4448 _LIBUNWIND_ABORT("VE doesn't have float registers");
4451 inline void Registers_ve::setFloatRegister(int /* regNum */,
4452 double /* value */) {
4453 _LIBUNWIND_ABORT("VE doesn't have float registers");
4456 inline bool Registers_ve::validVectorRegister(int /* regNum */) const {
4460 inline v128
Registers_ve::getVectorRegister(int /* regNum */) const {
4461 _LIBUNWIND_ABORT("VE vector support not implemented");
4464 inline void Registers_ve::setVectorRegister(int /* regNum */,
4466 _LIBUNWIND_ABORT("VE vector support not implemented");
4469 inline const char *Registers_ve::getRegisterName(int regNum
) {
4768 return "unknown register";
4770 #endif // _LIBUNWIND_TARGET_VE
4772 #if defined(_LIBUNWIND_TARGET_S390X)
4773 /// Registers_s390x holds the register state of a thread in a
4774 /// 64-bit Linux on IBM zSystems process.
4775 class _LIBUNWIND_HIDDEN Registers_s390x
{
4778 Registers_s390x(const void *registers
);
4780 bool validRegister(int num
) const;
4781 uint64_t getRegister(int num
) const;
4782 void setRegister(int num
, uint64_t value
);
4783 bool validFloatRegister(int num
) const;
4784 double getFloatRegister(int num
) const;
4785 void setFloatRegister(int num
, double value
);
4786 bool validVectorRegister(int num
) const;
4787 v128
getVectorRegister(int num
) const;
4788 void setVectorRegister(int num
, v128 value
);
4789 static const char *getRegisterName(int num
);
4791 static constexpr int lastDwarfRegNum() {
4792 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X
;
4794 static int getArch() { return REGISTERS_S390X
; }
4796 uint64_t getSP() const { return _registers
.__gpr
[15]; }
4797 void setSP(uint64_t value
) { _registers
.__gpr
[15] = value
; }
4798 uint64_t getIP() const { return _registers
.__pswa
; }
4799 void setIP(uint64_t value
) { _registers
.__pswa
= value
; }
4802 struct s390x_thread_state_t
{
4803 uint64_t __pswm
; // Problem Status Word: Mask
4804 uint64_t __pswa
; // Problem Status Word: Address (PC)
4805 uint64_t __gpr
[16]; // General Purpose Registers
4806 double __fpr
[16]; // Floating-Point Registers
4809 s390x_thread_state_t _registers
;
4812 inline Registers_s390x::Registers_s390x(const void *registers
) {
4813 static_assert((check_fit
<Registers_s390x
, unw_context_t
>::does_fit
),
4814 "s390x registers do not fit into unw_context_t");
4815 memcpy(&_registers
, static_cast<const uint8_t *>(registers
),
4816 sizeof(_registers
));
4819 inline Registers_s390x::Registers_s390x() {
4820 memset(&_registers
, 0, sizeof(_registers
));
4823 inline bool Registers_s390x::validRegister(int regNum
) const {
4825 case UNW_S390X_PSWM
:
4826 case UNW_S390X_PSWA
:
4832 if (regNum
>= UNW_S390X_R0
&& regNum
<= UNW_S390X_R15
)
4838 inline uint64_t Registers_s390x::getRegister(int regNum
) const {
4839 if (regNum
>= UNW_S390X_R0
&& regNum
<= UNW_S390X_R15
)
4840 return _registers
.__gpr
[regNum
- UNW_S390X_R0
];
4843 case UNW_S390X_PSWM
:
4844 return _registers
.__pswm
;
4845 case UNW_S390X_PSWA
:
4847 return _registers
.__pswa
;
4849 return _registers
.__gpr
[15];
4851 _LIBUNWIND_ABORT("unsupported s390x register");
4854 inline void Registers_s390x::setRegister(int regNum
, uint64_t value
) {
4855 if (regNum
>= UNW_S390X_R0
&& regNum
<= UNW_S390X_R15
) {
4856 _registers
.__gpr
[regNum
- UNW_S390X_R0
] = value
;
4861 case UNW_S390X_PSWM
:
4862 _registers
.__pswm
= value
;
4864 case UNW_S390X_PSWA
:
4866 _registers
.__pswa
= value
;
4869 _registers
.__gpr
[15] = value
;
4872 _LIBUNWIND_ABORT("unsupported s390x register");
4875 inline bool Registers_s390x::validFloatRegister(int regNum
) const {
4876 return regNum
>= UNW_S390X_F0
&& regNum
<= UNW_S390X_F15
;
4879 inline double Registers_s390x::getFloatRegister(int regNum
) const {
4880 // NOTE: FPR DWARF register numbers are not consecutive.
4883 return _registers
.__fpr
[0];
4885 return _registers
.__fpr
[1];
4887 return _registers
.__fpr
[2];
4889 return _registers
.__fpr
[3];
4891 return _registers
.__fpr
[4];
4893 return _registers
.__fpr
[5];
4895 return _registers
.__fpr
[6];
4897 return _registers
.__fpr
[7];
4899 return _registers
.__fpr
[8];
4901 return _registers
.__fpr
[9];
4903 return _registers
.__fpr
[10];
4905 return _registers
.__fpr
[11];
4907 return _registers
.__fpr
[12];
4909 return _registers
.__fpr
[13];
4911 return _registers
.__fpr
[14];
4913 return _registers
.__fpr
[15];
4915 _LIBUNWIND_ABORT("unsupported s390x register");
4918 inline void Registers_s390x::setFloatRegister(int regNum
, double value
) {
4919 // NOTE: FPR DWARF register numbers are not consecutive.
4922 _registers
.__fpr
[0] = value
;
4925 _registers
.__fpr
[1] = value
;
4928 _registers
.__fpr
[2] = value
;
4931 _registers
.__fpr
[3] = value
;
4934 _registers
.__fpr
[4] = value
;
4937 _registers
.__fpr
[5] = value
;
4940 _registers
.__fpr
[6] = value
;
4943 _registers
.__fpr
[7] = value
;
4946 _registers
.__fpr
[8] = value
;
4949 _registers
.__fpr
[9] = value
;
4952 _registers
.__fpr
[10] = value
;
4955 _registers
.__fpr
[11] = value
;
4958 _registers
.__fpr
[12] = value
;
4961 _registers
.__fpr
[13] = value
;
4964 _registers
.__fpr
[14] = value
;
4967 _registers
.__fpr
[15] = value
;
4970 _LIBUNWIND_ABORT("unsupported s390x register");
4973 inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
4977 inline v128
Registers_s390x::getVectorRegister(int /*regNum*/) const {
4978 _LIBUNWIND_ABORT("s390x vector support not implemented");
4981 inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128
/*value*/) {
4982 _LIBUNWIND_ABORT("s390x vector support not implemented");
4985 inline const char *Registers_s390x::getRegisterName(int regNum
) {
5056 return "unknown register";
5058 #endif // _LIBUNWIND_TARGET_S390X
5060 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
5061 /// Registers_loongarch holds the register state of a thread in a 64-bit
5062 /// LoongArch process.
5063 class _LIBUNWIND_HIDDEN Registers_loongarch
{
5065 Registers_loongarch();
5066 Registers_loongarch(const void *registers
);
5068 bool validRegister(int num
) const;
5069 uint64_t getRegister(int num
) const;
5070 void setRegister(int num
, uint64_t value
);
5071 bool validFloatRegister(int num
) const;
5072 double getFloatRegister(int num
) const;
5073 void setFloatRegister(int num
, double value
);
5074 bool validVectorRegister(int num
) const;
5075 v128
getVectorRegister(int num
) const;
5076 void setVectorRegister(int num
, v128 value
);
5077 static const char *getRegisterName(int num
);
5079 static constexpr int lastDwarfRegNum() {
5080 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH
;
5082 static int getArch() { return REGISTERS_LOONGARCH
; }
5084 uint64_t getSP() const { return _registers
.__r
[3]; }
5085 void setSP(uint64_t value
) { _registers
.__r
[3] = value
; }
5086 uint64_t getIP() const { return _registers
.__pc
; }
5087 void setIP(uint64_t value
) { _registers
.__pc
= value
; }
5090 struct loongarch_thread_state_t
{
5095 loongarch_thread_state_t _registers
;
5096 #if __loongarch_frlen == 64
5101 inline Registers_loongarch::Registers_loongarch(const void *registers
) {
5102 static_assert((check_fit
<Registers_loongarch
, unw_context_t
>::does_fit
),
5103 "loongarch registers do not fit into unw_context_t");
5104 memcpy(&_registers
, registers
, sizeof(_registers
));
5105 static_assert(sizeof(_registers
) == 0x108,
5106 "expected float registers to be at offset 264");
5107 #if __loongarch_frlen == 64
5108 memcpy(_floats
, static_cast<const uint8_t *>(registers
) + sizeof(_registers
),
5113 inline Registers_loongarch::Registers_loongarch() {
5114 memset(&_registers
, 0, sizeof(_registers
));
5115 #if __loongarch_frlen == 64
5116 memset(&_floats
, 0, sizeof(_floats
));
5120 inline bool Registers_loongarch::validRegister(int regNum
) const {
5121 if (regNum
== UNW_REG_IP
|| regNum
== UNW_REG_SP
)
5123 if (regNum
< 0 || regNum
> UNW_LOONGARCH_F31
)
5128 inline uint64_t Registers_loongarch::getRegister(int regNum
) const {
5129 if (regNum
>= UNW_LOONGARCH_R0
&& regNum
<= UNW_LOONGARCH_R31
)
5130 return _registers
.__r
[regNum
- UNW_LOONGARCH_R0
];
5132 if (regNum
== UNW_REG_IP
)
5133 return _registers
.__pc
;
5134 if (regNum
== UNW_REG_SP
)
5135 return _registers
.__r
[3];
5136 _LIBUNWIND_ABORT("unsupported loongarch register");
5139 inline void Registers_loongarch::setRegister(int regNum
, uint64_t value
) {
5140 if (regNum
>= UNW_LOONGARCH_R0
&& regNum
<= UNW_LOONGARCH_R31
)
5141 _registers
.__r
[regNum
- UNW_LOONGARCH_R0
] = value
;
5142 else if (regNum
== UNW_REG_IP
)
5143 _registers
.__pc
= value
;
5144 else if (regNum
== UNW_REG_SP
)
5145 _registers
.__r
[3] = value
;
5147 _LIBUNWIND_ABORT("unsupported loongarch register");
5150 inline const char *Registers_loongarch::getRegisterName(int regNum
) {
5156 case UNW_LOONGARCH_R0
:
5158 case UNW_LOONGARCH_R1
:
5160 case UNW_LOONGARCH_R2
:
5162 case UNW_LOONGARCH_R3
:
5164 case UNW_LOONGARCH_R4
:
5166 case UNW_LOONGARCH_R5
:
5168 case UNW_LOONGARCH_R6
:
5170 case UNW_LOONGARCH_R7
:
5172 case UNW_LOONGARCH_R8
:
5174 case UNW_LOONGARCH_R9
:
5176 case UNW_LOONGARCH_R10
:
5178 case UNW_LOONGARCH_R11
:
5180 case UNW_LOONGARCH_R12
:
5182 case UNW_LOONGARCH_R13
:
5184 case UNW_LOONGARCH_R14
:
5186 case UNW_LOONGARCH_R15
:
5188 case UNW_LOONGARCH_R16
:
5190 case UNW_LOONGARCH_R17
:
5192 case UNW_LOONGARCH_R18
:
5194 case UNW_LOONGARCH_R19
:
5196 case UNW_LOONGARCH_R20
:
5198 case UNW_LOONGARCH_R21
:
5200 case UNW_LOONGARCH_R22
:
5202 case UNW_LOONGARCH_R23
:
5204 case UNW_LOONGARCH_R24
:
5206 case UNW_LOONGARCH_R25
:
5208 case UNW_LOONGARCH_R26
:
5210 case UNW_LOONGARCH_R27
:
5212 case UNW_LOONGARCH_R28
:
5214 case UNW_LOONGARCH_R29
:
5216 case UNW_LOONGARCH_R30
:
5218 case UNW_LOONGARCH_R31
:
5220 case UNW_LOONGARCH_F0
:
5222 case UNW_LOONGARCH_F1
:
5224 case UNW_LOONGARCH_F2
:
5226 case UNW_LOONGARCH_F3
:
5228 case UNW_LOONGARCH_F4
:
5230 case UNW_LOONGARCH_F5
:
5232 case UNW_LOONGARCH_F6
:
5234 case UNW_LOONGARCH_F7
:
5236 case UNW_LOONGARCH_F8
:
5238 case UNW_LOONGARCH_F9
:
5240 case UNW_LOONGARCH_F10
:
5242 case UNW_LOONGARCH_F11
:
5244 case UNW_LOONGARCH_F12
:
5246 case UNW_LOONGARCH_F13
:
5248 case UNW_LOONGARCH_F14
:
5250 case UNW_LOONGARCH_F15
:
5252 case UNW_LOONGARCH_F16
:
5254 case UNW_LOONGARCH_F17
:
5256 case UNW_LOONGARCH_F18
:
5258 case UNW_LOONGARCH_F19
:
5260 case UNW_LOONGARCH_F20
:
5262 case UNW_LOONGARCH_F21
:
5264 case UNW_LOONGARCH_F22
:
5266 case UNW_LOONGARCH_F23
:
5268 case UNW_LOONGARCH_F24
:
5270 case UNW_LOONGARCH_F25
:
5272 case UNW_LOONGARCH_F26
:
5274 case UNW_LOONGARCH_F27
:
5276 case UNW_LOONGARCH_F28
:
5278 case UNW_LOONGARCH_F29
:
5280 case UNW_LOONGARCH_F30
:
5282 case UNW_LOONGARCH_F31
:
5285 return "unknown register";
5289 inline bool Registers_loongarch::validFloatRegister(int regNum
) const {
5290 if (regNum
< UNW_LOONGARCH_F0
|| regNum
> UNW_LOONGARCH_F31
)
5295 inline double Registers_loongarch::getFloatRegister(int regNum
) const {
5296 #if __loongarch_frlen == 64
5297 assert(validFloatRegister(regNum
));
5298 return _floats
[regNum
- UNW_LOONGARCH_F0
];
5300 _LIBUNWIND_ABORT("libunwind not built with float support");
5304 inline void Registers_loongarch::setFloatRegister(int regNum
, double value
) {
5305 #if __loongarch_frlen == 64
5306 assert(validFloatRegister(regNum
));
5307 _floats
[regNum
- UNW_LOONGARCH_F0
] = value
;
5309 _LIBUNWIND_ABORT("libunwind not built with float support");
5313 inline bool Registers_loongarch::validVectorRegister(int) const {
5317 inline v128
Registers_loongarch::getVectorRegister(int) const {
5318 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5321 inline void Registers_loongarch::setVectorRegister(int, v128
) {
5322 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5324 #endif //_LIBUNWIND_TARGET_LOONGARCH
5326 } // namespace libunwind
5328 #endif // __REGISTERS_HPP__