[CostModel][X86] Add explicit Silvermont test coverage for bswap costs
[llvm-project.git] / libunwind / src / Registers.hpp
blobd11ddb3426d522ea5ceaf4b0c4d951494b394d78
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //
8 // Models register sets for supported processors.
9 //
10 //===----------------------------------------------------------------------===//
12 #ifndef __REGISTERS_HPP__
13 #define __REGISTERS_HPP__
15 #include <stdint.h>
16 #include <string.h>
18 #include "cet_unwind.h"
19 #include "config.h"
20 #include "libunwind.h"
22 namespace libunwind {
24 // For emulating 128-bit registers
25 struct v128 { uint32_t vec[4]; };
27 enum {
28 REGISTERS_X86,
29 REGISTERS_X86_64,
30 REGISTERS_PPC,
31 REGISTERS_PPC64,
32 REGISTERS_ARM64,
33 REGISTERS_ARM,
34 REGISTERS_OR1K,
35 REGISTERS_MIPS_O32,
36 REGISTERS_MIPS_NEWABI,
37 REGISTERS_SPARC,
38 REGISTERS_SPARC64,
39 REGISTERS_HEXAGON,
40 REGISTERS_RISCV,
41 REGISTERS_VE,
42 REGISTERS_S390X,
43 REGISTERS_LOONGARCH,
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);
54 #endif
56 /// Registers_x86 holds the register state of a thread in a 32-bit intel
57 /// process.
58 class _LIBUNWIND_HIDDEN Registers_x86 {
59 public:
60 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; }
96 private:
97 struct GPRs {
98 unsigned int __eax;
99 unsigned int __ebx;
100 unsigned int __ecx;
101 unsigned int __edx;
102 unsigned int __edi;
103 unsigned int __esi;
104 unsigned int __ebp;
105 unsigned int __esp;
106 unsigned int __ss;
107 unsigned int __eflags;
108 unsigned int __eip;
109 unsigned int __cs;
110 unsigned int __ds;
111 unsigned int __es;
112 unsigned int __fs;
113 unsigned int __gs;
116 GPRs _registers;
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)
131 return true;
132 if (regNum == UNW_REG_SP)
133 return true;
134 if (regNum < 0)
135 return false;
136 if (regNum > 7)
137 return false;
138 return true;
141 inline uint32_t Registers_x86::getRegister(int regNum) const {
142 switch (regNum) {
143 case UNW_REG_IP:
144 return _registers.__eip;
145 case UNW_REG_SP:
146 return _registers.__esp;
147 case UNW_X86_EAX:
148 return _registers.__eax;
149 case UNW_X86_ECX:
150 return _registers.__ecx;
151 case UNW_X86_EDX:
152 return _registers.__edx;
153 case UNW_X86_EBX:
154 return _registers.__ebx;
155 #if !defined(__APPLE__)
156 case UNW_X86_ESP:
157 #else
158 case UNW_X86_EBP:
159 #endif
160 return _registers.__ebp;
161 #if !defined(__APPLE__)
162 case UNW_X86_EBP:
163 #else
164 case UNW_X86_ESP:
165 #endif
166 return _registers.__esp;
167 case UNW_X86_ESI:
168 return _registers.__esi;
169 case UNW_X86_EDI:
170 return _registers.__edi;
172 _LIBUNWIND_ABORT("unsupported x86 register");
175 inline void Registers_x86::setRegister(int regNum, uint32_t value) {
176 switch (regNum) {
177 case UNW_REG_IP:
178 _registers.__eip = value;
179 return;
180 case UNW_REG_SP:
181 _registers.__esp = value;
182 return;
183 case UNW_X86_EAX:
184 _registers.__eax = value;
185 return;
186 case UNW_X86_ECX:
187 _registers.__ecx = value;
188 return;
189 case UNW_X86_EDX:
190 _registers.__edx = value;
191 return;
192 case UNW_X86_EBX:
193 _registers.__ebx = value;
194 return;
195 #if !defined(__APPLE__)
196 case UNW_X86_ESP:
197 #else
198 case UNW_X86_EBP:
199 #endif
200 _registers.__ebp = value;
201 return;
202 #if !defined(__APPLE__)
203 case UNW_X86_EBP:
204 #else
205 case UNW_X86_ESP:
206 #endif
207 _registers.__esp = value;
208 return;
209 case UNW_X86_ESI:
210 _registers.__esi = value;
211 return;
212 case UNW_X86_EDI:
213 _registers.__edi = value;
214 return;
216 _LIBUNWIND_ABORT("unsupported x86 register");
219 inline const char *Registers_x86::getRegisterName(int regNum) {
220 switch (regNum) {
221 case UNW_REG_IP:
222 return "ip";
223 case UNW_REG_SP:
224 return "esp";
225 case UNW_X86_EAX:
226 return "eax";
227 case UNW_X86_ECX:
228 return "ecx";
229 case UNW_X86_EDX:
230 return "edx";
231 case UNW_X86_EBX:
232 return "ebx";
233 case UNW_X86_EBP:
234 return "ebp";
235 case UNW_X86_ESP:
236 return "esp";
237 case UNW_X86_ESI:
238 return "esi";
239 case UNW_X86_EDI:
240 return "edi";
241 default:
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
266 /// process.
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);
274 #endif
276 class _LIBUNWIND_HIDDEN Registers_x86_64 {
277 public:
278 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; }
314 private:
315 struct GPRs {
316 uint64_t __rax;
317 uint64_t __rbx;
318 uint64_t __rcx;
319 uint64_t __rdx;
320 uint64_t __rdi;
321 uint64_t __rsi;
322 uint64_t __rbp;
323 uint64_t __rsp;
324 uint64_t __r8;
325 uint64_t __r9;
326 uint64_t __r10;
327 uint64_t __r11;
328 uint64_t __r12;
329 uint64_t __r13;
330 uint64_t __r14;
331 uint64_t __r15;
332 uint64_t __rip;
333 uint64_t __rflags;
334 uint64_t __cs;
335 uint64_t __fs;
336 uint64_t __gs;
337 #if defined(_WIN64)
338 uint64_t __padding; // 16-byte align
339 #endif
341 GPRs _registers;
342 #if defined(_WIN64)
343 v128 _xmm[16];
344 #endif
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)
359 return true;
360 if (regNum == UNW_REG_SP)
361 return true;
362 if (regNum < 0)
363 return false;
364 if (regNum > 16)
365 return false;
366 return true;
369 inline uint64_t Registers_x86_64::getRegister(int regNum) const {
370 switch (regNum) {
371 case UNW_REG_IP:
372 case UNW_X86_64_RIP:
373 return _registers.__rip;
374 case UNW_REG_SP:
375 return _registers.__rsp;
376 case UNW_X86_64_RAX:
377 return _registers.__rax;
378 case UNW_X86_64_RDX:
379 return _registers.__rdx;
380 case UNW_X86_64_RCX:
381 return _registers.__rcx;
382 case UNW_X86_64_RBX:
383 return _registers.__rbx;
384 case UNW_X86_64_RSI:
385 return _registers.__rsi;
386 case UNW_X86_64_RDI:
387 return _registers.__rdi;
388 case UNW_X86_64_RBP:
389 return _registers.__rbp;
390 case UNW_X86_64_RSP:
391 return _registers.__rsp;
392 case UNW_X86_64_R8:
393 return _registers.__r8;
394 case UNW_X86_64_R9:
395 return _registers.__r9;
396 case UNW_X86_64_R10:
397 return _registers.__r10;
398 case UNW_X86_64_R11:
399 return _registers.__r11;
400 case UNW_X86_64_R12:
401 return _registers.__r12;
402 case UNW_X86_64_R13:
403 return _registers.__r13;
404 case UNW_X86_64_R14:
405 return _registers.__r14;
406 case UNW_X86_64_R15:
407 return _registers.__r15;
409 _LIBUNWIND_ABORT("unsupported x86_64 register");
412 inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
413 switch (regNum) {
414 case UNW_REG_IP:
415 case UNW_X86_64_RIP:
416 _registers.__rip = value;
417 return;
418 case UNW_REG_SP:
419 _registers.__rsp = value;
420 return;
421 case UNW_X86_64_RAX:
422 _registers.__rax = value;
423 return;
424 case UNW_X86_64_RDX:
425 _registers.__rdx = value;
426 return;
427 case UNW_X86_64_RCX:
428 _registers.__rcx = value;
429 return;
430 case UNW_X86_64_RBX:
431 _registers.__rbx = value;
432 return;
433 case UNW_X86_64_RSI:
434 _registers.__rsi = value;
435 return;
436 case UNW_X86_64_RDI:
437 _registers.__rdi = value;
438 return;
439 case UNW_X86_64_RBP:
440 _registers.__rbp = value;
441 return;
442 case UNW_X86_64_RSP:
443 _registers.__rsp = value;
444 return;
445 case UNW_X86_64_R8:
446 _registers.__r8 = value;
447 return;
448 case UNW_X86_64_R9:
449 _registers.__r9 = value;
450 return;
451 case UNW_X86_64_R10:
452 _registers.__r10 = value;
453 return;
454 case UNW_X86_64_R11:
455 _registers.__r11 = value;
456 return;
457 case UNW_X86_64_R12:
458 _registers.__r12 = value;
459 return;
460 case UNW_X86_64_R13:
461 _registers.__r13 = value;
462 return;
463 case UNW_X86_64_R14:
464 _registers.__r14 = value;
465 return;
466 case UNW_X86_64_R15:
467 _registers.__r15 = value;
468 return;
470 _LIBUNWIND_ABORT("unsupported x86_64 register");
473 inline const char *Registers_x86_64::getRegisterName(int regNum) {
474 switch (regNum) {
475 case UNW_REG_IP:
476 case UNW_X86_64_RIP:
477 return "rip";
478 case UNW_REG_SP:
479 return "rsp";
480 case UNW_X86_64_RAX:
481 return "rax";
482 case UNW_X86_64_RDX:
483 return "rdx";
484 case UNW_X86_64_RCX:
485 return "rcx";
486 case UNW_X86_64_RBX:
487 return "rbx";
488 case UNW_X86_64_RSI:
489 return "rsi";
490 case UNW_X86_64_RDI:
491 return "rdi";
492 case UNW_X86_64_RBP:
493 return "rbp";
494 case UNW_X86_64_RSP:
495 return "rsp";
496 case UNW_X86_64_R8:
497 return "r8";
498 case UNW_X86_64_R9:
499 return "r9";
500 case UNW_X86_64_R10:
501 return "r10";
502 case UNW_X86_64_R11:
503 return "r11";
504 case UNW_X86_64_R12:
505 return "r12";
506 case UNW_X86_64_R13:
507 return "r13";
508 case UNW_X86_64_R14:
509 return "r14";
510 case UNW_X86_64_R15:
511 return "r15";
512 case UNW_X86_64_XMM0:
513 return "xmm0";
514 case UNW_X86_64_XMM1:
515 return "xmm1";
516 case UNW_X86_64_XMM2:
517 return "xmm2";
518 case UNW_X86_64_XMM3:
519 return "xmm3";
520 case UNW_X86_64_XMM4:
521 return "xmm4";
522 case UNW_X86_64_XMM5:
523 return "xmm5";
524 case UNW_X86_64_XMM6:
525 return "xmm6";
526 case UNW_X86_64_XMM7:
527 return "xmm7";
528 case UNW_X86_64_XMM8:
529 return "xmm8";
530 case UNW_X86_64_XMM9:
531 return "xmm9";
532 case UNW_X86_64_XMM10:
533 return "xmm10";
534 case UNW_X86_64_XMM11:
535 return "xmm11";
536 case UNW_X86_64_XMM12:
537 return "xmm12";
538 case UNW_X86_64_XMM13:
539 return "xmm13";
540 case UNW_X86_64_XMM14:
541 return "xmm14";
542 case UNW_X86_64_XMM15:
543 return "xmm15";
544 default:
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 {
558 #if defined(_WIN64)
559 if (regNum < UNW_X86_64_XMM0)
560 return false;
561 if (regNum > UNW_X86_64_XMM15)
562 return false;
563 return true;
564 #else
565 (void)regNum; // suppress unused parameter warning
566 return false;
567 #endif
570 inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
571 #if defined(_WIN64)
572 assert(validVectorRegister(regNum));
573 return _xmm[regNum - UNW_X86_64_XMM0];
574 #else
575 (void)regNum; // suppress unused parameter warning
576 _LIBUNWIND_ABORT("no x86_64 vector registers");
577 #endif
580 inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
581 #if defined(_WIN64)
582 assert(validVectorRegister(regNum));
583 _xmm[regNum - UNW_X86_64_XMM0] = value;
584 #else
585 (void)regNum; (void)value; // suppress unused parameter warnings
586 _LIBUNWIND_ABORT("no x86_64 vector registers");
587 #endif
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
594 /// process.
595 class _LIBUNWIND_HIDDEN Registers_ppc {
596 public:
597 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);
610 void jumpto();
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; }
625 private:
626 struct ppc_thread_state_t {
627 unsigned int __srr0; /* Instruction address register (PC) */
628 unsigned int __srr1; /* Machine state register (supervisor) */
629 unsigned int __r0;
630 unsigned int __r1;
631 unsigned int __r2;
632 unsigned int __r3;
633 unsigned int __r4;
634 unsigned int __r5;
635 unsigned int __r6;
636 unsigned int __r7;
637 unsigned int __r8;
638 unsigned int __r9;
639 unsigned int __r10;
640 unsigned int __r11;
641 unsigned int __r12;
642 unsigned int __r13;
643 unsigned int __r14;
644 unsigned int __r15;
645 unsigned int __r16;
646 unsigned int __r17;
647 unsigned int __r18;
648 unsigned int __r19;
649 unsigned int __r20;
650 unsigned int __r21;
651 unsigned int __r22;
652 unsigned int __r23;
653 unsigned int __r24;
654 unsigned int __r25;
655 unsigned int __r26;
656 unsigned int __r27;
657 unsigned int __r28;
658 unsigned int __r29;
659 unsigned int __r30;
660 unsigned int __r31;
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 {
670 double __fpregs[32];
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),
685 sizeof(_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)
707 return true;
708 if (regNum == UNW_REG_SP)
709 return true;
710 if (regNum == UNW_PPC_VRSAVE)
711 return true;
712 if (regNum < 0)
713 return false;
714 if (regNum <= UNW_PPC_R31)
715 return true;
716 if (regNum == UNW_PPC_MQ)
717 return true;
718 if (regNum == UNW_PPC_LR)
719 return true;
720 if (regNum == UNW_PPC_CTR)
721 return true;
722 if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
723 return true;
724 return false;
727 inline uint32_t Registers_ppc::getRegister(int regNum) const {
728 switch (regNum) {
729 case UNW_REG_IP:
730 return _registers.__srr0;
731 case UNW_REG_SP:
732 return _registers.__r1;
733 case UNW_PPC_R0:
734 return _registers.__r0;
735 case UNW_PPC_R1:
736 return _registers.__r1;
737 case UNW_PPC_R2:
738 return _registers.__r2;
739 case UNW_PPC_R3:
740 return _registers.__r3;
741 case UNW_PPC_R4:
742 return _registers.__r4;
743 case UNW_PPC_R5:
744 return _registers.__r5;
745 case UNW_PPC_R6:
746 return _registers.__r6;
747 case UNW_PPC_R7:
748 return _registers.__r7;
749 case UNW_PPC_R8:
750 return _registers.__r8;
751 case UNW_PPC_R9:
752 return _registers.__r9;
753 case UNW_PPC_R10:
754 return _registers.__r10;
755 case UNW_PPC_R11:
756 return _registers.__r11;
757 case UNW_PPC_R12:
758 return _registers.__r12;
759 case UNW_PPC_R13:
760 return _registers.__r13;
761 case UNW_PPC_R14:
762 return _registers.__r14;
763 case UNW_PPC_R15:
764 return _registers.__r15;
765 case UNW_PPC_R16:
766 return _registers.__r16;
767 case UNW_PPC_R17:
768 return _registers.__r17;
769 case UNW_PPC_R18:
770 return _registers.__r18;
771 case UNW_PPC_R19:
772 return _registers.__r19;
773 case UNW_PPC_R20:
774 return _registers.__r20;
775 case UNW_PPC_R21:
776 return _registers.__r21;
777 case UNW_PPC_R22:
778 return _registers.__r22;
779 case UNW_PPC_R23:
780 return _registers.__r23;
781 case UNW_PPC_R24:
782 return _registers.__r24;
783 case UNW_PPC_R25:
784 return _registers.__r25;
785 case UNW_PPC_R26:
786 return _registers.__r26;
787 case UNW_PPC_R27:
788 return _registers.__r27;
789 case UNW_PPC_R28:
790 return _registers.__r28;
791 case UNW_PPC_R29:
792 return _registers.__r29;
793 case UNW_PPC_R30:
794 return _registers.__r30;
795 case UNW_PPC_R31:
796 return _registers.__r31;
797 case UNW_PPC_LR:
798 return _registers.__lr;
799 case UNW_PPC_CR0:
800 return (_registers.__cr & 0xF0000000);
801 case UNW_PPC_CR1:
802 return (_registers.__cr & 0x0F000000);
803 case UNW_PPC_CR2:
804 return (_registers.__cr & 0x00F00000);
805 case UNW_PPC_CR3:
806 return (_registers.__cr & 0x000F0000);
807 case UNW_PPC_CR4:
808 return (_registers.__cr & 0x0000F000);
809 case UNW_PPC_CR5:
810 return (_registers.__cr & 0x00000F00);
811 case UNW_PPC_CR6:
812 return (_registers.__cr & 0x000000F0);
813 case UNW_PPC_CR7:
814 return (_registers.__cr & 0x0000000F);
815 case UNW_PPC_VRSAVE:
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);
823 switch (regNum) {
824 case UNW_REG_IP:
825 _registers.__srr0 = value;
826 return;
827 case UNW_REG_SP:
828 _registers.__r1 = value;
829 return;
830 case UNW_PPC_R0:
831 _registers.__r0 = value;
832 return;
833 case UNW_PPC_R1:
834 _registers.__r1 = value;
835 return;
836 case UNW_PPC_R2:
837 _registers.__r2 = value;
838 return;
839 case UNW_PPC_R3:
840 _registers.__r3 = value;
841 return;
842 case UNW_PPC_R4:
843 _registers.__r4 = value;
844 return;
845 case UNW_PPC_R5:
846 _registers.__r5 = value;
847 return;
848 case UNW_PPC_R6:
849 _registers.__r6 = value;
850 return;
851 case UNW_PPC_R7:
852 _registers.__r7 = value;
853 return;
854 case UNW_PPC_R8:
855 _registers.__r8 = value;
856 return;
857 case UNW_PPC_R9:
858 _registers.__r9 = value;
859 return;
860 case UNW_PPC_R10:
861 _registers.__r10 = value;
862 return;
863 case UNW_PPC_R11:
864 _registers.__r11 = value;
865 return;
866 case UNW_PPC_R12:
867 _registers.__r12 = value;
868 return;
869 case UNW_PPC_R13:
870 _registers.__r13 = value;
871 return;
872 case UNW_PPC_R14:
873 _registers.__r14 = value;
874 return;
875 case UNW_PPC_R15:
876 _registers.__r15 = value;
877 return;
878 case UNW_PPC_R16:
879 _registers.__r16 = value;
880 return;
881 case UNW_PPC_R17:
882 _registers.__r17 = value;
883 return;
884 case UNW_PPC_R18:
885 _registers.__r18 = value;
886 return;
887 case UNW_PPC_R19:
888 _registers.__r19 = value;
889 return;
890 case UNW_PPC_R20:
891 _registers.__r20 = value;
892 return;
893 case UNW_PPC_R21:
894 _registers.__r21 = value;
895 return;
896 case UNW_PPC_R22:
897 _registers.__r22 = value;
898 return;
899 case UNW_PPC_R23:
900 _registers.__r23 = value;
901 return;
902 case UNW_PPC_R24:
903 _registers.__r24 = value;
904 return;
905 case UNW_PPC_R25:
906 _registers.__r25 = value;
907 return;
908 case UNW_PPC_R26:
909 _registers.__r26 = value;
910 return;
911 case UNW_PPC_R27:
912 _registers.__r27 = value;
913 return;
914 case UNW_PPC_R28:
915 _registers.__r28 = value;
916 return;
917 case UNW_PPC_R29:
918 _registers.__r29 = value;
919 return;
920 case UNW_PPC_R30:
921 _registers.__r30 = value;
922 return;
923 case UNW_PPC_R31:
924 _registers.__r31 = value;
925 return;
926 case UNW_PPC_MQ:
927 _registers.__mq = value;
928 return;
929 case UNW_PPC_LR:
930 _registers.__lr = value;
931 return;
932 case UNW_PPC_CTR:
933 _registers.__ctr = value;
934 return;
935 case UNW_PPC_CR0:
936 _registers.__cr &= 0x0FFFFFFF;
937 _registers.__cr |= (value & 0xF0000000);
938 return;
939 case UNW_PPC_CR1:
940 _registers.__cr &= 0xF0FFFFFF;
941 _registers.__cr |= (value & 0x0F000000);
942 return;
943 case UNW_PPC_CR2:
944 _registers.__cr &= 0xFF0FFFFF;
945 _registers.__cr |= (value & 0x00F00000);
946 return;
947 case UNW_PPC_CR3:
948 _registers.__cr &= 0xFFF0FFFF;
949 _registers.__cr |= (value & 0x000F0000);
950 return;
951 case UNW_PPC_CR4:
952 _registers.__cr &= 0xFFFF0FFF;
953 _registers.__cr |= (value & 0x0000F000);
954 return;
955 case UNW_PPC_CR5:
956 _registers.__cr &= 0xFFFFF0FF;
957 _registers.__cr |= (value & 0x00000F00);
958 return;
959 case UNW_PPC_CR6:
960 _registers.__cr &= 0xFFFFFF0F;
961 _registers.__cr |= (value & 0x000000F0);
962 return;
963 case UNW_PPC_CR7:
964 _registers.__cr &= 0xFFFFFFF0;
965 _registers.__cr |= (value & 0x0000000F);
966 return;
967 case UNW_PPC_VRSAVE:
968 _registers.__vrsave = value;
969 return;
970 // not saved
971 return;
972 case UNW_PPC_XER:
973 _registers.__xer = value;
974 return;
975 case UNW_PPC_AP:
976 case UNW_PPC_VSCR:
977 case UNW_PPC_SPEFSCR:
978 // not saved
979 return;
981 _LIBUNWIND_ABORT("unsupported ppc register");
984 inline bool Registers_ppc::validFloatRegister(int regNum) const {
985 if (regNum < UNW_PPC_F0)
986 return false;
987 if (regNum > UNW_PPC_F31)
988 return false;
989 return true;
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)
1004 return false;
1005 if (regNum > UNW_PPC_V31)
1006 return false;
1007 return true;
1010 inline v128 Registers_ppc::getVectorRegister(int regNum) const {
1011 assert(validVectorRegister(regNum));
1012 v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
1013 return result;
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) {
1022 switch (regNum) {
1023 case UNW_REG_IP:
1024 return "ip";
1025 case UNW_REG_SP:
1026 return "sp";
1027 case UNW_PPC_R0:
1028 return "r0";
1029 case UNW_PPC_R1:
1030 return "r1";
1031 case UNW_PPC_R2:
1032 return "r2";
1033 case UNW_PPC_R3:
1034 return "r3";
1035 case UNW_PPC_R4:
1036 return "r4";
1037 case UNW_PPC_R5:
1038 return "r5";
1039 case UNW_PPC_R6:
1040 return "r6";
1041 case UNW_PPC_R7:
1042 return "r7";
1043 case UNW_PPC_R8:
1044 return "r8";
1045 case UNW_PPC_R9:
1046 return "r9";
1047 case UNW_PPC_R10:
1048 return "r10";
1049 case UNW_PPC_R11:
1050 return "r11";
1051 case UNW_PPC_R12:
1052 return "r12";
1053 case UNW_PPC_R13:
1054 return "r13";
1055 case UNW_PPC_R14:
1056 return "r14";
1057 case UNW_PPC_R15:
1058 return "r15";
1059 case UNW_PPC_R16:
1060 return "r16";
1061 case UNW_PPC_R17:
1062 return "r17";
1063 case UNW_PPC_R18:
1064 return "r18";
1065 case UNW_PPC_R19:
1066 return "r19";
1067 case UNW_PPC_R20:
1068 return "r20";
1069 case UNW_PPC_R21:
1070 return "r21";
1071 case UNW_PPC_R22:
1072 return "r22";
1073 case UNW_PPC_R23:
1074 return "r23";
1075 case UNW_PPC_R24:
1076 return "r24";
1077 case UNW_PPC_R25:
1078 return "r25";
1079 case UNW_PPC_R26:
1080 return "r26";
1081 case UNW_PPC_R27:
1082 return "r27";
1083 case UNW_PPC_R28:
1084 return "r28";
1085 case UNW_PPC_R29:
1086 return "r29";
1087 case UNW_PPC_R30:
1088 return "r30";
1089 case UNW_PPC_R31:
1090 return "r31";
1091 case UNW_PPC_F0:
1092 return "fp0";
1093 case UNW_PPC_F1:
1094 return "fp1";
1095 case UNW_PPC_F2:
1096 return "fp2";
1097 case UNW_PPC_F3:
1098 return "fp3";
1099 case UNW_PPC_F4:
1100 return "fp4";
1101 case UNW_PPC_F5:
1102 return "fp5";
1103 case UNW_PPC_F6:
1104 return "fp6";
1105 case UNW_PPC_F7:
1106 return "fp7";
1107 case UNW_PPC_F8:
1108 return "fp8";
1109 case UNW_PPC_F9:
1110 return "fp9";
1111 case UNW_PPC_F10:
1112 return "fp10";
1113 case UNW_PPC_F11:
1114 return "fp11";
1115 case UNW_PPC_F12:
1116 return "fp12";
1117 case UNW_PPC_F13:
1118 return "fp13";
1119 case UNW_PPC_F14:
1120 return "fp14";
1121 case UNW_PPC_F15:
1122 return "fp15";
1123 case UNW_PPC_F16:
1124 return "fp16";
1125 case UNW_PPC_F17:
1126 return "fp17";
1127 case UNW_PPC_F18:
1128 return "fp18";
1129 case UNW_PPC_F19:
1130 return "fp19";
1131 case UNW_PPC_F20:
1132 return "fp20";
1133 case UNW_PPC_F21:
1134 return "fp21";
1135 case UNW_PPC_F22:
1136 return "fp22";
1137 case UNW_PPC_F23:
1138 return "fp23";
1139 case UNW_PPC_F24:
1140 return "fp24";
1141 case UNW_PPC_F25:
1142 return "fp25";
1143 case UNW_PPC_F26:
1144 return "fp26";
1145 case UNW_PPC_F27:
1146 return "fp27";
1147 case UNW_PPC_F28:
1148 return "fp28";
1149 case UNW_PPC_F29:
1150 return "fp29";
1151 case UNW_PPC_F30:
1152 return "fp30";
1153 case UNW_PPC_F31:
1154 return "fp31";
1155 case UNW_PPC_LR:
1156 return "lr";
1157 default:
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
1166 /// process.
1167 class _LIBUNWIND_HIDDEN Registers_ppc64 {
1168 public:
1169 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);
1182 void jumpto();
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; }
1197 private:
1198 struct ppc64_thread_state_t {
1199 uint64_t __srr0; // Instruction address register (PC)
1200 uint64_t __srr1; // Machine state register (supervisor)
1201 uint64_t __r0;
1202 uint64_t __r1;
1203 uint64_t __r2;
1204 uint64_t __r3;
1205 uint64_t __r4;
1206 uint64_t __r5;
1207 uint64_t __r6;
1208 uint64_t __r7;
1209 uint64_t __r8;
1210 uint64_t __r9;
1211 uint64_t __r10;
1212 uint64_t __r11;
1213 uint64_t __r12;
1214 uint64_t __r13;
1215 uint64_t __r14;
1216 uint64_t __r15;
1217 uint64_t __r16;
1218 uint64_t __r17;
1219 uint64_t __r18;
1220 uint64_t __r19;
1221 uint64_t __r20;
1222 uint64_t __r21;
1223 uint64_t __r22;
1224 uint64_t __r23;
1225 uint64_t __r24;
1226 uint64_t __r25;
1227 uint64_t __r26;
1228 uint64_t __r27;
1229 uint64_t __r28;
1230 uint64_t __r29;
1231 uint64_t __r30;
1232 uint64_t __r31;
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
1240 union ppc64_vsr_t {
1241 struct asfloat_s {
1242 double f;
1243 uint64_t v2;
1244 } asfloat;
1245 v128 v;
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 {
1275 switch (regNum) {
1276 case UNW_REG_IP:
1277 case UNW_REG_SP:
1278 case UNW_PPC64_XER:
1279 case UNW_PPC64_LR:
1280 case UNW_PPC64_CTR:
1281 case UNW_PPC64_VRSAVE:
1282 return true;
1285 if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
1286 return true;
1287 if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
1288 return true;
1290 return false;
1293 inline uint64_t Registers_ppc64::getRegister(int regNum) const {
1294 switch (regNum) {
1295 case UNW_REG_IP:
1296 return _registers.__srr0;
1297 case UNW_PPC64_R0:
1298 return _registers.__r0;
1299 case UNW_PPC64_R1:
1300 case UNW_REG_SP:
1301 return _registers.__r1;
1302 case UNW_PPC64_R2:
1303 return _registers.__r2;
1304 case UNW_PPC64_R3:
1305 return _registers.__r3;
1306 case UNW_PPC64_R4:
1307 return _registers.__r4;
1308 case UNW_PPC64_R5:
1309 return _registers.__r5;
1310 case UNW_PPC64_R6:
1311 return _registers.__r6;
1312 case UNW_PPC64_R7:
1313 return _registers.__r7;
1314 case UNW_PPC64_R8:
1315 return _registers.__r8;
1316 case UNW_PPC64_R9:
1317 return _registers.__r9;
1318 case UNW_PPC64_R10:
1319 return _registers.__r10;
1320 case UNW_PPC64_R11:
1321 return _registers.__r11;
1322 case UNW_PPC64_R12:
1323 return _registers.__r12;
1324 case UNW_PPC64_R13:
1325 return _registers.__r13;
1326 case UNW_PPC64_R14:
1327 return _registers.__r14;
1328 case UNW_PPC64_R15:
1329 return _registers.__r15;
1330 case UNW_PPC64_R16:
1331 return _registers.__r16;
1332 case UNW_PPC64_R17:
1333 return _registers.__r17;
1334 case UNW_PPC64_R18:
1335 return _registers.__r18;
1336 case UNW_PPC64_R19:
1337 return _registers.__r19;
1338 case UNW_PPC64_R20:
1339 return _registers.__r20;
1340 case UNW_PPC64_R21:
1341 return _registers.__r21;
1342 case UNW_PPC64_R22:
1343 return _registers.__r22;
1344 case UNW_PPC64_R23:
1345 return _registers.__r23;
1346 case UNW_PPC64_R24:
1347 return _registers.__r24;
1348 case UNW_PPC64_R25:
1349 return _registers.__r25;
1350 case UNW_PPC64_R26:
1351 return _registers.__r26;
1352 case UNW_PPC64_R27:
1353 return _registers.__r27;
1354 case UNW_PPC64_R28:
1355 return _registers.__r28;
1356 case UNW_PPC64_R29:
1357 return _registers.__r29;
1358 case UNW_PPC64_R30:
1359 return _registers.__r30;
1360 case UNW_PPC64_R31:
1361 return _registers.__r31;
1362 case UNW_PPC64_CR0:
1363 return (_registers.__cr & 0xF0000000);
1364 case UNW_PPC64_CR1:
1365 return (_registers.__cr & 0x0F000000);
1366 case UNW_PPC64_CR2:
1367 return (_registers.__cr & 0x00F00000);
1368 case UNW_PPC64_CR3:
1369 return (_registers.__cr & 0x000F0000);
1370 case UNW_PPC64_CR4:
1371 return (_registers.__cr & 0x0000F000);
1372 case UNW_PPC64_CR5:
1373 return (_registers.__cr & 0x00000F00);
1374 case UNW_PPC64_CR6:
1375 return (_registers.__cr & 0x000000F0);
1376 case UNW_PPC64_CR7:
1377 return (_registers.__cr & 0x0000000F);
1378 case UNW_PPC64_XER:
1379 return _registers.__xer;
1380 case UNW_PPC64_LR:
1381 return _registers.__lr;
1382 case UNW_PPC64_CTR:
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) {
1391 switch (regNum) {
1392 case UNW_REG_IP:
1393 _registers.__srr0 = value;
1394 return;
1395 case UNW_PPC64_R0:
1396 _registers.__r0 = value;
1397 return;
1398 case UNW_PPC64_R1:
1399 case UNW_REG_SP:
1400 _registers.__r1 = value;
1401 return;
1402 case UNW_PPC64_R2:
1403 _registers.__r2 = value;
1404 return;
1405 case UNW_PPC64_R3:
1406 _registers.__r3 = value;
1407 return;
1408 case UNW_PPC64_R4:
1409 _registers.__r4 = value;
1410 return;
1411 case UNW_PPC64_R5:
1412 _registers.__r5 = value;
1413 return;
1414 case UNW_PPC64_R6:
1415 _registers.__r6 = value;
1416 return;
1417 case UNW_PPC64_R7:
1418 _registers.__r7 = value;
1419 return;
1420 case UNW_PPC64_R8:
1421 _registers.__r8 = value;
1422 return;
1423 case UNW_PPC64_R9:
1424 _registers.__r9 = value;
1425 return;
1426 case UNW_PPC64_R10:
1427 _registers.__r10 = value;
1428 return;
1429 case UNW_PPC64_R11:
1430 _registers.__r11 = value;
1431 return;
1432 case UNW_PPC64_R12:
1433 _registers.__r12 = value;
1434 return;
1435 case UNW_PPC64_R13:
1436 _registers.__r13 = value;
1437 return;
1438 case UNW_PPC64_R14:
1439 _registers.__r14 = value;
1440 return;
1441 case UNW_PPC64_R15:
1442 _registers.__r15 = value;
1443 return;
1444 case UNW_PPC64_R16:
1445 _registers.__r16 = value;
1446 return;
1447 case UNW_PPC64_R17:
1448 _registers.__r17 = value;
1449 return;
1450 case UNW_PPC64_R18:
1451 _registers.__r18 = value;
1452 return;
1453 case UNW_PPC64_R19:
1454 _registers.__r19 = value;
1455 return;
1456 case UNW_PPC64_R20:
1457 _registers.__r20 = value;
1458 return;
1459 case UNW_PPC64_R21:
1460 _registers.__r21 = value;
1461 return;
1462 case UNW_PPC64_R22:
1463 _registers.__r22 = value;
1464 return;
1465 case UNW_PPC64_R23:
1466 _registers.__r23 = value;
1467 return;
1468 case UNW_PPC64_R24:
1469 _registers.__r24 = value;
1470 return;
1471 case UNW_PPC64_R25:
1472 _registers.__r25 = value;
1473 return;
1474 case UNW_PPC64_R26:
1475 _registers.__r26 = value;
1476 return;
1477 case UNW_PPC64_R27:
1478 _registers.__r27 = value;
1479 return;
1480 case UNW_PPC64_R28:
1481 _registers.__r28 = value;
1482 return;
1483 case UNW_PPC64_R29:
1484 _registers.__r29 = value;
1485 return;
1486 case UNW_PPC64_R30:
1487 _registers.__r30 = value;
1488 return;
1489 case UNW_PPC64_R31:
1490 _registers.__r31 = value;
1491 return;
1492 case UNW_PPC64_CR0:
1493 _registers.__cr &= 0x0FFFFFFF;
1494 _registers.__cr |= (value & 0xF0000000);
1495 return;
1496 case UNW_PPC64_CR1:
1497 _registers.__cr &= 0xF0FFFFFF;
1498 _registers.__cr |= (value & 0x0F000000);
1499 return;
1500 case UNW_PPC64_CR2:
1501 _registers.__cr &= 0xFF0FFFFF;
1502 _registers.__cr |= (value & 0x00F00000);
1503 return;
1504 case UNW_PPC64_CR3:
1505 _registers.__cr &= 0xFFF0FFFF;
1506 _registers.__cr |= (value & 0x000F0000);
1507 return;
1508 case UNW_PPC64_CR4:
1509 _registers.__cr &= 0xFFFF0FFF;
1510 _registers.__cr |= (value & 0x0000F000);
1511 return;
1512 case UNW_PPC64_CR5:
1513 _registers.__cr &= 0xFFFFF0FF;
1514 _registers.__cr |= (value & 0x00000F00);
1515 return;
1516 case UNW_PPC64_CR6:
1517 _registers.__cr &= 0xFFFFFF0F;
1518 _registers.__cr |= (value & 0x000000F0);
1519 return;
1520 case UNW_PPC64_CR7:
1521 _registers.__cr &= 0xFFFFFFF0;
1522 _registers.__cr |= (value & 0x0000000F);
1523 return;
1524 case UNW_PPC64_XER:
1525 _registers.__xer = value;
1526 return;
1527 case UNW_PPC64_LR:
1528 _registers.__lr = value;
1529 return;
1530 case UNW_PPC64_CTR:
1531 _registers.__ctr = value;
1532 return;
1533 case UNW_PPC64_VRSAVE:
1534 _registers.__vrsave = value;
1535 return;
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)
1557 return true;
1558 if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
1559 return true;
1560 #elif defined(__ALTIVEC__)
1561 if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
1562 return true;
1563 #endif
1564 return false;
1567 inline int Registers_ppc64::getVectorRegNum(int num)
1569 if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
1570 return num - UNW_PPC64_VS0;
1571 else
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) {
1586 switch (regNum) {
1587 case UNW_REG_IP:
1588 return "ip";
1589 case UNW_REG_SP:
1590 return "sp";
1591 case UNW_PPC64_R0:
1592 return "r0";
1593 case UNW_PPC64_R1:
1594 return "r1";
1595 case UNW_PPC64_R2:
1596 return "r2";
1597 case UNW_PPC64_R3:
1598 return "r3";
1599 case UNW_PPC64_R4:
1600 return "r4";
1601 case UNW_PPC64_R5:
1602 return "r5";
1603 case UNW_PPC64_R6:
1604 return "r6";
1605 case UNW_PPC64_R7:
1606 return "r7";
1607 case UNW_PPC64_R8:
1608 return "r8";
1609 case UNW_PPC64_R9:
1610 return "r9";
1611 case UNW_PPC64_R10:
1612 return "r10";
1613 case UNW_PPC64_R11:
1614 return "r11";
1615 case UNW_PPC64_R12:
1616 return "r12";
1617 case UNW_PPC64_R13:
1618 return "r13";
1619 case UNW_PPC64_R14:
1620 return "r14";
1621 case UNW_PPC64_R15:
1622 return "r15";
1623 case UNW_PPC64_R16:
1624 return "r16";
1625 case UNW_PPC64_R17:
1626 return "r17";
1627 case UNW_PPC64_R18:
1628 return "r18";
1629 case UNW_PPC64_R19:
1630 return "r19";
1631 case UNW_PPC64_R20:
1632 return "r20";
1633 case UNW_PPC64_R21:
1634 return "r21";
1635 case UNW_PPC64_R22:
1636 return "r22";
1637 case UNW_PPC64_R23:
1638 return "r23";
1639 case UNW_PPC64_R24:
1640 return "r24";
1641 case UNW_PPC64_R25:
1642 return "r25";
1643 case UNW_PPC64_R26:
1644 return "r26";
1645 case UNW_PPC64_R27:
1646 return "r27";
1647 case UNW_PPC64_R28:
1648 return "r28";
1649 case UNW_PPC64_R29:
1650 return "r29";
1651 case UNW_PPC64_R30:
1652 return "r30";
1653 case UNW_PPC64_R31:
1654 return "r31";
1655 case UNW_PPC64_CR0:
1656 return "cr0";
1657 case UNW_PPC64_CR1:
1658 return "cr1";
1659 case UNW_PPC64_CR2:
1660 return "cr2";
1661 case UNW_PPC64_CR3:
1662 return "cr3";
1663 case UNW_PPC64_CR4:
1664 return "cr4";
1665 case UNW_PPC64_CR5:
1666 return "cr5";
1667 case UNW_PPC64_CR6:
1668 return "cr6";
1669 case UNW_PPC64_CR7:
1670 return "cr7";
1671 case UNW_PPC64_XER:
1672 return "xer";
1673 case UNW_PPC64_LR:
1674 return "lr";
1675 case UNW_PPC64_CTR:
1676 return "ctr";
1677 case UNW_PPC64_VRSAVE:
1678 return "vrsave";
1679 case UNW_PPC64_F0:
1680 return "fp0";
1681 case UNW_PPC64_F1:
1682 return "fp1";
1683 case UNW_PPC64_F2:
1684 return "fp2";
1685 case UNW_PPC64_F3:
1686 return "fp3";
1687 case UNW_PPC64_F4:
1688 return "fp4";
1689 case UNW_PPC64_F5:
1690 return "fp5";
1691 case UNW_PPC64_F6:
1692 return "fp6";
1693 case UNW_PPC64_F7:
1694 return "fp7";
1695 case UNW_PPC64_F8:
1696 return "fp8";
1697 case UNW_PPC64_F9:
1698 return "fp9";
1699 case UNW_PPC64_F10:
1700 return "fp10";
1701 case UNW_PPC64_F11:
1702 return "fp11";
1703 case UNW_PPC64_F12:
1704 return "fp12";
1705 case UNW_PPC64_F13:
1706 return "fp13";
1707 case UNW_PPC64_F14:
1708 return "fp14";
1709 case UNW_PPC64_F15:
1710 return "fp15";
1711 case UNW_PPC64_F16:
1712 return "fp16";
1713 case UNW_PPC64_F17:
1714 return "fp17";
1715 case UNW_PPC64_F18:
1716 return "fp18";
1717 case UNW_PPC64_F19:
1718 return "fp19";
1719 case UNW_PPC64_F20:
1720 return "fp20";
1721 case UNW_PPC64_F21:
1722 return "fp21";
1723 case UNW_PPC64_F22:
1724 return "fp22";
1725 case UNW_PPC64_F23:
1726 return "fp23";
1727 case UNW_PPC64_F24:
1728 return "fp24";
1729 case UNW_PPC64_F25:
1730 return "fp25";
1731 case UNW_PPC64_F26:
1732 return "fp26";
1733 case UNW_PPC64_F27:
1734 return "fp27";
1735 case UNW_PPC64_F28:
1736 return "fp28";
1737 case UNW_PPC64_F29:
1738 return "fp29";
1739 case UNW_PPC64_F30:
1740 return "fp30";
1741 case UNW_PPC64_F31:
1742 return "fp31";
1743 case UNW_PPC64_V0:
1744 return "v0";
1745 case UNW_PPC64_V1:
1746 return "v1";
1747 case UNW_PPC64_V2:
1748 return "v2";
1749 case UNW_PPC64_V3:
1750 return "v3";
1751 case UNW_PPC64_V4:
1752 return "v4";
1753 case UNW_PPC64_V5:
1754 return "v5";
1755 case UNW_PPC64_V6:
1756 return "v6";
1757 case UNW_PPC64_V7:
1758 return "v7";
1759 case UNW_PPC64_V8:
1760 return "v8";
1761 case UNW_PPC64_V9:
1762 return "v9";
1763 case UNW_PPC64_V10:
1764 return "v10";
1765 case UNW_PPC64_V11:
1766 return "v11";
1767 case UNW_PPC64_V12:
1768 return "v12";
1769 case UNW_PPC64_V13:
1770 return "v13";
1771 case UNW_PPC64_V14:
1772 return "v14";
1773 case UNW_PPC64_V15:
1774 return "v15";
1775 case UNW_PPC64_V16:
1776 return "v16";
1777 case UNW_PPC64_V17:
1778 return "v17";
1779 case UNW_PPC64_V18:
1780 return "v18";
1781 case UNW_PPC64_V19:
1782 return "v19";
1783 case UNW_PPC64_V20:
1784 return "v20";
1785 case UNW_PPC64_V21:
1786 return "v21";
1787 case UNW_PPC64_V22:
1788 return "v22";
1789 case UNW_PPC64_V23:
1790 return "v23";
1791 case UNW_PPC64_V24:
1792 return "v24";
1793 case UNW_PPC64_V25:
1794 return "v25";
1795 case UNW_PPC64_V26:
1796 return "v26";
1797 case UNW_PPC64_V27:
1798 return "v27";
1799 case UNW_PPC64_V28:
1800 return "v28";
1801 case UNW_PPC64_V29:
1802 return "v29";
1803 case UNW_PPC64_V30:
1804 return "v30";
1805 case UNW_PPC64_V31:
1806 return "v31";
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
1815 /// process.
1816 class _LIBUNWIND_HIDDEN Registers_arm64;
1817 extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
1818 class _LIBUNWIND_HIDDEN Registers_arm64 {
1819 public:
1820 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; }
1846 private:
1847 struct GPRs {
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
1856 GPRs _registers;
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)
1882 return true;
1883 if (regNum == UNW_REG_SP)
1884 return true;
1885 if (regNum < 0)
1886 return false;
1887 if (regNum > 95)
1888 return false;
1889 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
1890 return true;
1891 if ((regNum > 32) && (regNum < 64))
1892 return false;
1893 return true;
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;
1925 else
1926 _LIBUNWIND_ABORT("unsupported arm64 register");
1929 inline const char *Registers_arm64::getRegisterName(int regNum) {
1930 switch (regNum) {
1931 case UNW_REG_IP:
1932 return "pc";
1933 case UNW_REG_SP:
1934 return "sp";
1935 case UNW_AARCH64_X0:
1936 return "x0";
1937 case UNW_AARCH64_X1:
1938 return "x1";
1939 case UNW_AARCH64_X2:
1940 return "x2";
1941 case UNW_AARCH64_X3:
1942 return "x3";
1943 case UNW_AARCH64_X4:
1944 return "x4";
1945 case UNW_AARCH64_X5:
1946 return "x5";
1947 case UNW_AARCH64_X6:
1948 return "x6";
1949 case UNW_AARCH64_X7:
1950 return "x7";
1951 case UNW_AARCH64_X8:
1952 return "x8";
1953 case UNW_AARCH64_X9:
1954 return "x9";
1955 case UNW_AARCH64_X10:
1956 return "x10";
1957 case UNW_AARCH64_X11:
1958 return "x11";
1959 case UNW_AARCH64_X12:
1960 return "x12";
1961 case UNW_AARCH64_X13:
1962 return "x13";
1963 case UNW_AARCH64_X14:
1964 return "x14";
1965 case UNW_AARCH64_X15:
1966 return "x15";
1967 case UNW_AARCH64_X16:
1968 return "x16";
1969 case UNW_AARCH64_X17:
1970 return "x17";
1971 case UNW_AARCH64_X18:
1972 return "x18";
1973 case UNW_AARCH64_X19:
1974 return "x19";
1975 case UNW_AARCH64_X20:
1976 return "x20";
1977 case UNW_AARCH64_X21:
1978 return "x21";
1979 case UNW_AARCH64_X22:
1980 return "x22";
1981 case UNW_AARCH64_X23:
1982 return "x23";
1983 case UNW_AARCH64_X24:
1984 return "x24";
1985 case UNW_AARCH64_X25:
1986 return "x25";
1987 case UNW_AARCH64_X26:
1988 return "x26";
1989 case UNW_AARCH64_X27:
1990 return "x27";
1991 case UNW_AARCH64_X28:
1992 return "x28";
1993 case UNW_AARCH64_FP:
1994 return "fp";
1995 case UNW_AARCH64_LR:
1996 return "lr";
1997 case UNW_AARCH64_SP:
1998 return "sp";
1999 case UNW_AARCH64_PC:
2000 return "pc";
2001 case UNW_AARCH64_V0:
2002 return "d0";
2003 case UNW_AARCH64_V1:
2004 return "d1";
2005 case UNW_AARCH64_V2:
2006 return "d2";
2007 case UNW_AARCH64_V3:
2008 return "d3";
2009 case UNW_AARCH64_V4:
2010 return "d4";
2011 case UNW_AARCH64_V5:
2012 return "d5";
2013 case UNW_AARCH64_V6:
2014 return "d6";
2015 case UNW_AARCH64_V7:
2016 return "d7";
2017 case UNW_AARCH64_V8:
2018 return "d8";
2019 case UNW_AARCH64_V9:
2020 return "d9";
2021 case UNW_AARCH64_V10:
2022 return "d10";
2023 case UNW_AARCH64_V11:
2024 return "d11";
2025 case UNW_AARCH64_V12:
2026 return "d12";
2027 case UNW_AARCH64_V13:
2028 return "d13";
2029 case UNW_AARCH64_V14:
2030 return "d14";
2031 case UNW_AARCH64_V15:
2032 return "d15";
2033 case UNW_AARCH64_V16:
2034 return "d16";
2035 case UNW_AARCH64_V17:
2036 return "d17";
2037 case UNW_AARCH64_V18:
2038 return "d18";
2039 case UNW_AARCH64_V19:
2040 return "d19";
2041 case UNW_AARCH64_V20:
2042 return "d20";
2043 case UNW_AARCH64_V21:
2044 return "d21";
2045 case UNW_AARCH64_V22:
2046 return "d22";
2047 case UNW_AARCH64_V23:
2048 return "d23";
2049 case UNW_AARCH64_V24:
2050 return "d24";
2051 case UNW_AARCH64_V25:
2052 return "d25";
2053 case UNW_AARCH64_V26:
2054 return "d26";
2055 case UNW_AARCH64_V27:
2056 return "d27";
2057 case UNW_AARCH64_V28:
2058 return "d28";
2059 case UNW_AARCH64_V29:
2060 return "d29";
2061 case UNW_AARCH64_V30:
2062 return "d30";
2063 case UNW_AARCH64_V31:
2064 return "d31";
2065 default:
2066 return "unknown register";
2070 inline bool Registers_arm64::validFloatRegister(int regNum) const {
2071 if (regNum < UNW_AARCH64_V0)
2072 return false;
2073 if (regNum > UNW_AARCH64_V31)
2074 return false;
2075 return true;
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 {
2089 return false;
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
2103 /// process.
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 {
2108 public:
2109 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);
2122 void jumpto() {
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; }
2136 void saveVFPAsX() {
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);
2145 else
2146 restoreVFPWithFLDMD(_vfp_d0_d15_pad);
2148 if (_saved_vfp_d16_d31)
2149 restoreVFPv3(_vfp_d16_d31);
2150 #if defined(__ARM_WMMX)
2151 if (_saved_iwmmx)
2152 restoreiWMMX(_iwmmx);
2153 if (_saved_iwmmx_control)
2154 restoreiWMMXControl(_iwmmx_control);
2155 #endif
2158 private:
2159 struct GPRs {
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*);
2181 #endif
2182 void restoreCoreAndJumpTo();
2184 // ARM registers
2185 GPRs _registers;
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.
2206 bool _saved_iwmmx;
2207 // Whether iWMMX control registers are saved.
2208 mutable bool _saved_iwmmx_control;
2209 // iWMMX registers
2210 unw_fpreg_t _iwmmx[16];
2211 // iWMMX control registers
2212 mutable uint32_t _iwmmx_control[4];
2213 #endif
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));
2232 #endif
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));
2248 #endif
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)
2255 return true;
2257 if (regNum == UNW_REG_SP)
2258 return true;
2260 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
2261 return true;
2263 #if defined(__ARM_WMMX)
2264 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
2265 return true;
2266 #endif
2268 #ifdef __ARM_FEATURE_PAUTH
2269 if (regNum == UNW_ARM_RA_AUTH_CODE)
2270 return true;
2271 #endif
2273 return false;
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];
2297 #endif
2299 #ifdef __ARM_FEATURE_PAUTH
2300 if (regNum == UNW_ARM_RA_AUTH_CODE)
2301 return _pseudo_registers.__pac;
2302 #endif
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;
2310 return;
2313 if (regNum == UNW_ARM_LR) {
2314 _registers.__lr = value;
2315 return;
2318 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
2319 _registers.__pc = value;
2320 return;
2323 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
2324 _registers.__r[regNum] = value;
2325 return;
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;
2335 return;
2337 #endif
2339 if (regNum == UNW_ARM_RA_AUTH_CODE) {
2340 _pseudo_registers.__pac = value;
2341 return;
2344 _LIBUNWIND_ABORT("unsupported arm register");
2347 inline const char *Registers_arm::getRegisterName(int regNum) {
2348 switch (regNum) {
2349 case UNW_REG_IP:
2350 case UNW_ARM_IP: // UNW_ARM_R15 is alias
2351 return "pc";
2352 case UNW_ARM_LR: // UNW_ARM_R14 is alias
2353 return "lr";
2354 case UNW_REG_SP:
2355 case UNW_ARM_SP: // UNW_ARM_R13 is alias
2356 return "sp";
2357 case UNW_ARM_R0:
2358 return "r0";
2359 case UNW_ARM_R1:
2360 return "r1";
2361 case UNW_ARM_R2:
2362 return "r2";
2363 case UNW_ARM_R3:
2364 return "r3";
2365 case UNW_ARM_R4:
2366 return "r4";
2367 case UNW_ARM_R5:
2368 return "r5";
2369 case UNW_ARM_R6:
2370 return "r6";
2371 case UNW_ARM_R7:
2372 return "r7";
2373 case UNW_ARM_R8:
2374 return "r8";
2375 case UNW_ARM_R9:
2376 return "r9";
2377 case UNW_ARM_R10:
2378 return "r10";
2379 case UNW_ARM_R11:
2380 return "r11";
2381 case UNW_ARM_R12:
2382 return "r12";
2383 case UNW_ARM_S0:
2384 return "s0";
2385 case UNW_ARM_S1:
2386 return "s1";
2387 case UNW_ARM_S2:
2388 return "s2";
2389 case UNW_ARM_S3:
2390 return "s3";
2391 case UNW_ARM_S4:
2392 return "s4";
2393 case UNW_ARM_S5:
2394 return "s5";
2395 case UNW_ARM_S6:
2396 return "s6";
2397 case UNW_ARM_S7:
2398 return "s7";
2399 case UNW_ARM_S8:
2400 return "s8";
2401 case UNW_ARM_S9:
2402 return "s9";
2403 case UNW_ARM_S10:
2404 return "s10";
2405 case UNW_ARM_S11:
2406 return "s11";
2407 case UNW_ARM_S12:
2408 return "s12";
2409 case UNW_ARM_S13:
2410 return "s13";
2411 case UNW_ARM_S14:
2412 return "s14";
2413 case UNW_ARM_S15:
2414 return "s15";
2415 case UNW_ARM_S16:
2416 return "s16";
2417 case UNW_ARM_S17:
2418 return "s17";
2419 case UNW_ARM_S18:
2420 return "s18";
2421 case UNW_ARM_S19:
2422 return "s19";
2423 case UNW_ARM_S20:
2424 return "s20";
2425 case UNW_ARM_S21:
2426 return "s21";
2427 case UNW_ARM_S22:
2428 return "s22";
2429 case UNW_ARM_S23:
2430 return "s23";
2431 case UNW_ARM_S24:
2432 return "s24";
2433 case UNW_ARM_S25:
2434 return "s25";
2435 case UNW_ARM_S26:
2436 return "s26";
2437 case UNW_ARM_S27:
2438 return "s27";
2439 case UNW_ARM_S28:
2440 return "s28";
2441 case UNW_ARM_S29:
2442 return "s29";
2443 case UNW_ARM_S30:
2444 return "s30";
2445 case UNW_ARM_S31:
2446 return "s31";
2447 case UNW_ARM_D0:
2448 return "d0";
2449 case UNW_ARM_D1:
2450 return "d1";
2451 case UNW_ARM_D2:
2452 return "d2";
2453 case UNW_ARM_D3:
2454 return "d3";
2455 case UNW_ARM_D4:
2456 return "d4";
2457 case UNW_ARM_D5:
2458 return "d5";
2459 case UNW_ARM_D6:
2460 return "d6";
2461 case UNW_ARM_D7:
2462 return "d7";
2463 case UNW_ARM_D8:
2464 return "d8";
2465 case UNW_ARM_D9:
2466 return "d9";
2467 case UNW_ARM_D10:
2468 return "d10";
2469 case UNW_ARM_D11:
2470 return "d11";
2471 case UNW_ARM_D12:
2472 return "d12";
2473 case UNW_ARM_D13:
2474 return "d13";
2475 case UNW_ARM_D14:
2476 return "d14";
2477 case UNW_ARM_D15:
2478 return "d15";
2479 case UNW_ARM_D16:
2480 return "d16";
2481 case UNW_ARM_D17:
2482 return "d17";
2483 case UNW_ARM_D18:
2484 return "d18";
2485 case UNW_ARM_D19:
2486 return "d19";
2487 case UNW_ARM_D20:
2488 return "d20";
2489 case UNW_ARM_D21:
2490 return "d21";
2491 case UNW_ARM_D22:
2492 return "d22";
2493 case UNW_ARM_D23:
2494 return "d23";
2495 case UNW_ARM_D24:
2496 return "d24";
2497 case UNW_ARM_D25:
2498 return "d25";
2499 case UNW_ARM_D26:
2500 return "d26";
2501 case UNW_ARM_D27:
2502 return "d27";
2503 case UNW_ARM_D28:
2504 return "d28";
2505 case UNW_ARM_D29:
2506 return "d29";
2507 case UNW_ARM_D30:
2508 return "d30";
2509 case UNW_ARM_D31:
2510 return "d31";
2511 default:
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))
2522 #endif
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);
2532 else
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;
2550 saveiWMMX(_iwmmx);
2552 return _iwmmx[regNum - UNW_ARM_WR0];
2554 #endif
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);
2565 else
2566 saveVFPWithFSTMD(_vfp_d0_d15_pad);
2568 _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
2569 return;
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;
2578 return;
2581 #if defined(__ARM_WMMX)
2582 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2583 if (!_saved_iwmmx) {
2584 _saved_iwmmx = true;
2585 saveiWMMX(_iwmmx);
2587 _iwmmx[regNum - UNW_ARM_WR0] = value;
2588 return;
2590 #endif
2592 _LIBUNWIND_ABORT("Unknown ARM float register");
2595 inline bool Registers_arm::validVectorRegister(int) const {
2596 return false;
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
2611 /// process.
2612 class _LIBUNWIND_HIDDEN Registers_or1k {
2613 public:
2614 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);
2627 void jumpto();
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; }
2638 private:
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)
2661 return true;
2662 if (regNum == UNW_REG_SP)
2663 return true;
2664 if (regNum < 0)
2665 return false;
2666 if (regNum <= UNW_OR1K_R31)
2667 return true;
2668 if (regNum == UNW_OR1K_EPCR)
2669 return true;
2670 return false;
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];
2677 switch (regNum) {
2678 case UNW_REG_IP:
2679 return _registers.__pc;
2680 case UNW_REG_SP:
2681 return _registers.__r[1];
2682 case UNW_OR1K_EPCR:
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;
2691 return;
2694 switch (regNum) {
2695 case UNW_REG_IP:
2696 _registers.__pc = value;
2697 return;
2698 case UNW_REG_SP:
2699 _registers.__r[1] = value;
2700 return;
2701 case UNW_OR1K_EPCR:
2702 _registers.__epcr = value;
2703 return;
2705 _LIBUNWIND_ABORT("unsupported or1k register");
2708 inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2709 return false;
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 {
2722 return false;
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) {
2734 switch (regNum) {
2735 case UNW_OR1K_R0:
2736 return "r0";
2737 case UNW_OR1K_R1:
2738 return "r1";
2739 case UNW_OR1K_R2:
2740 return "r2";
2741 case UNW_OR1K_R3:
2742 return "r3";
2743 case UNW_OR1K_R4:
2744 return "r4";
2745 case UNW_OR1K_R5:
2746 return "r5";
2747 case UNW_OR1K_R6:
2748 return "r6";
2749 case UNW_OR1K_R7:
2750 return "r7";
2751 case UNW_OR1K_R8:
2752 return "r8";
2753 case UNW_OR1K_R9:
2754 return "r9";
2755 case UNW_OR1K_R10:
2756 return "r10";
2757 case UNW_OR1K_R11:
2758 return "r11";
2759 case UNW_OR1K_R12:
2760 return "r12";
2761 case UNW_OR1K_R13:
2762 return "r13";
2763 case UNW_OR1K_R14:
2764 return "r14";
2765 case UNW_OR1K_R15:
2766 return "r15";
2767 case UNW_OR1K_R16:
2768 return "r16";
2769 case UNW_OR1K_R17:
2770 return "r17";
2771 case UNW_OR1K_R18:
2772 return "r18";
2773 case UNW_OR1K_R19:
2774 return "r19";
2775 case UNW_OR1K_R20:
2776 return "r20";
2777 case UNW_OR1K_R21:
2778 return "r21";
2779 case UNW_OR1K_R22:
2780 return "r22";
2781 case UNW_OR1K_R23:
2782 return "r23";
2783 case UNW_OR1K_R24:
2784 return "r24";
2785 case UNW_OR1K_R25:
2786 return "r25";
2787 case UNW_OR1K_R26:
2788 return "r26";
2789 case UNW_OR1K_R27:
2790 return "r27";
2791 case UNW_OR1K_R28:
2792 return "r28";
2793 case UNW_OR1K_R29:
2794 return "r29";
2795 case UNW_OR1K_R30:
2796 return "r30";
2797 case UNW_OR1K_R31:
2798 return "r31";
2799 case UNW_OR1K_EPCR:
2800 return "EPCR";
2801 default:
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
2810 /// process.
2811 class _LIBUNWIND_HIDDEN Registers_mips_o32 {
2812 public:
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);
2826 void jumpto();
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; }
2837 private:
2838 struct mips_o32_thread_state_t {
2839 uint32_t __r[32];
2840 uint32_t __pc;
2841 uint32_t __hi;
2842 uint32_t __lo;
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.
2851 uint32_t _padding;
2852 double _floats[32];
2853 #endif
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)
2869 return true;
2870 if (regNum == UNW_REG_SP)
2871 return true;
2872 if (regNum < 0)
2873 return false;
2874 if (regNum <= UNW_MIPS_R31)
2875 return true;
2876 #if __mips_isa_rev < 6
2877 if (regNum == UNW_MIPS_HI)
2878 return true;
2879 if (regNum == UNW_MIPS_LO)
2880 return true;
2881 #endif
2882 #if defined(__mips_hard_float) && __mips_fpr == 32
2883 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2884 return true;
2885 #endif
2886 // FIXME: DSP accumulator registers, MSA registers
2887 return false;
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) {
2895 uint32_t *p;
2897 if (regNum % 2 == 0)
2898 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2899 else
2900 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2901 return *p;
2903 #endif
2905 switch (regNum) {
2906 case UNW_REG_IP:
2907 return _registers.__pc;
2908 case UNW_REG_SP:
2909 return _registers.__r[29];
2910 #if __mips_isa_rev < 6
2911 case UNW_MIPS_HI:
2912 return _registers.__hi;
2913 case UNW_MIPS_LO:
2914 return _registers.__lo;
2915 #endif
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;
2923 return;
2925 #if defined(__mips_hard_float) && __mips_fpr == 32
2926 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2927 uint32_t *p;
2929 if (regNum % 2 == 0)
2930 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2931 else
2932 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2933 *p = value;
2934 return;
2936 #endif
2938 switch (regNum) {
2939 case UNW_REG_IP:
2940 _registers.__pc = value;
2941 return;
2942 case UNW_REG_SP:
2943 _registers.__r[29] = value;
2944 return;
2945 #if __mips_isa_rev < 6
2946 case UNW_MIPS_HI:
2947 _registers.__hi = value;
2948 return;
2949 case UNW_MIPS_LO:
2950 _registers.__lo = value;
2951 #endif
2952 return;
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)
2960 return true;
2961 #else
2962 (void)regNum;
2963 #endif
2964 return false;
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];
2971 #else
2972 (void)regNum;
2973 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2974 #endif
2977 inline void Registers_mips_o32::setFloatRegister(int regNum,
2978 double value) {
2979 #if defined(__mips_hard_float) && __mips_fpr == 64
2980 assert(validFloatRegister(regNum));
2981 _floats[regNum - UNW_MIPS_F0] = value;
2982 #else
2983 (void)regNum;
2984 (void)value;
2985 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2986 #endif
2989 inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
2990 return false;
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) {
3002 switch (regNum) {
3003 case UNW_MIPS_R0:
3004 return "$0";
3005 case UNW_MIPS_R1:
3006 return "$1";
3007 case UNW_MIPS_R2:
3008 return "$2";
3009 case UNW_MIPS_R3:
3010 return "$3";
3011 case UNW_MIPS_R4:
3012 return "$4";
3013 case UNW_MIPS_R5:
3014 return "$5";
3015 case UNW_MIPS_R6:
3016 return "$6";
3017 case UNW_MIPS_R7:
3018 return "$7";
3019 case UNW_MIPS_R8:
3020 return "$8";
3021 case UNW_MIPS_R9:
3022 return "$9";
3023 case UNW_MIPS_R10:
3024 return "$10";
3025 case UNW_MIPS_R11:
3026 return "$11";
3027 case UNW_MIPS_R12:
3028 return "$12";
3029 case UNW_MIPS_R13:
3030 return "$13";
3031 case UNW_MIPS_R14:
3032 return "$14";
3033 case UNW_MIPS_R15:
3034 return "$15";
3035 case UNW_MIPS_R16:
3036 return "$16";
3037 case UNW_MIPS_R17:
3038 return "$17";
3039 case UNW_MIPS_R18:
3040 return "$18";
3041 case UNW_MIPS_R19:
3042 return "$19";
3043 case UNW_MIPS_R20:
3044 return "$20";
3045 case UNW_MIPS_R21:
3046 return "$21";
3047 case UNW_MIPS_R22:
3048 return "$22";
3049 case UNW_MIPS_R23:
3050 return "$23";
3051 case UNW_MIPS_R24:
3052 return "$24";
3053 case UNW_MIPS_R25:
3054 return "$25";
3055 case UNW_MIPS_R26:
3056 return "$26";
3057 case UNW_MIPS_R27:
3058 return "$27";
3059 case UNW_MIPS_R28:
3060 return "$28";
3061 case UNW_MIPS_R29:
3062 return "$29";
3063 case UNW_MIPS_R30:
3064 return "$30";
3065 case UNW_MIPS_R31:
3066 return "$31";
3067 case UNW_MIPS_F0:
3068 return "$f0";
3069 case UNW_MIPS_F1:
3070 return "$f1";
3071 case UNW_MIPS_F2:
3072 return "$f2";
3073 case UNW_MIPS_F3:
3074 return "$f3";
3075 case UNW_MIPS_F4:
3076 return "$f4";
3077 case UNW_MIPS_F5:
3078 return "$f5";
3079 case UNW_MIPS_F6:
3080 return "$f6";
3081 case UNW_MIPS_F7:
3082 return "$f7";
3083 case UNW_MIPS_F8:
3084 return "$f8";
3085 case UNW_MIPS_F9:
3086 return "$f9";
3087 case UNW_MIPS_F10:
3088 return "$f10";
3089 case UNW_MIPS_F11:
3090 return "$f11";
3091 case UNW_MIPS_F12:
3092 return "$f12";
3093 case UNW_MIPS_F13:
3094 return "$f13";
3095 case UNW_MIPS_F14:
3096 return "$f14";
3097 case UNW_MIPS_F15:
3098 return "$f15";
3099 case UNW_MIPS_F16:
3100 return "$f16";
3101 case UNW_MIPS_F17:
3102 return "$f17";
3103 case UNW_MIPS_F18:
3104 return "$f18";
3105 case UNW_MIPS_F19:
3106 return "$f19";
3107 case UNW_MIPS_F20:
3108 return "$f20";
3109 case UNW_MIPS_F21:
3110 return "$f21";
3111 case UNW_MIPS_F22:
3112 return "$f22";
3113 case UNW_MIPS_F23:
3114 return "$f23";
3115 case UNW_MIPS_F24:
3116 return "$f24";
3117 case UNW_MIPS_F25:
3118 return "$f25";
3119 case UNW_MIPS_F26:
3120 return "$f26";
3121 case UNW_MIPS_F27:
3122 return "$f27";
3123 case UNW_MIPS_F28:
3124 return "$f28";
3125 case UNW_MIPS_F29:
3126 return "$f29";
3127 case UNW_MIPS_F30:
3128 return "$f30";
3129 case UNW_MIPS_F31:
3130 return "$f31";
3131 #if __mips_isa_rev < 6
3132 case UNW_MIPS_HI:
3133 return "$hi";
3134 case UNW_MIPS_LO:
3135 return "$lo";
3136 #endif
3137 default:
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 {
3147 public:
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);
3161 void jumpto();
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; }
3172 private:
3173 struct mips_newabi_thread_state_t {
3174 uint64_t __r[32];
3175 uint64_t __pc;
3176 uint64_t __hi;
3177 uint64_t __lo;
3180 mips_newabi_thread_state_t _registers;
3181 #ifdef __mips_hard_float
3182 double _floats[32];
3183 #endif
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)
3199 return true;
3200 if (regNum == UNW_REG_SP)
3201 return true;
3202 if (regNum < 0)
3203 return false;
3204 if (regNum <= UNW_MIPS_R31)
3205 return true;
3206 #if __mips_isa_rev < 6
3207 if (regNum == UNW_MIPS_HI)
3208 return true;
3209 if (regNum == UNW_MIPS_LO)
3210 return true;
3211 #endif
3212 // FIXME: Hard float, DSP accumulator registers, MSA registers
3213 return false;
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];
3220 switch (regNum) {
3221 case UNW_REG_IP:
3222 return _registers.__pc;
3223 case UNW_REG_SP:
3224 return _registers.__r[29];
3225 #if __mips_isa_rev < 6
3226 case UNW_MIPS_HI:
3227 return _registers.__hi;
3228 case UNW_MIPS_LO:
3229 return _registers.__lo;
3230 #endif
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;
3238 return;
3241 switch (regNum) {
3242 case UNW_REG_IP:
3243 _registers.__pc = value;
3244 return;
3245 case UNW_REG_SP:
3246 _registers.__r[29] = value;
3247 return;
3248 #if __mips_isa_rev < 6
3249 case UNW_MIPS_HI:
3250 _registers.__hi = value;
3251 return;
3252 case UNW_MIPS_LO:
3253 _registers.__lo = value;
3254 return;
3255 #endif
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)
3263 return true;
3264 #else
3265 (void)regNum;
3266 #endif
3267 return false;
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];
3274 #else
3275 (void)regNum;
3276 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3277 #endif
3280 inline void Registers_mips_newabi::setFloatRegister(int regNum,
3281 double value) {
3282 #ifdef __mips_hard_float
3283 assert(validFloatRegister(regNum));
3284 _floats[regNum - UNW_MIPS_F0] = value;
3285 #else
3286 (void)regNum;
3287 (void)value;
3288 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3289 #endif
3292 inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3293 return false;
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) {
3305 switch (regNum) {
3306 case UNW_MIPS_R0:
3307 return "$0";
3308 case UNW_MIPS_R1:
3309 return "$1";
3310 case UNW_MIPS_R2:
3311 return "$2";
3312 case UNW_MIPS_R3:
3313 return "$3";
3314 case UNW_MIPS_R4:
3315 return "$4";
3316 case UNW_MIPS_R5:
3317 return "$5";
3318 case UNW_MIPS_R6:
3319 return "$6";
3320 case UNW_MIPS_R7:
3321 return "$7";
3322 case UNW_MIPS_R8:
3323 return "$8";
3324 case UNW_MIPS_R9:
3325 return "$9";
3326 case UNW_MIPS_R10:
3327 return "$10";
3328 case UNW_MIPS_R11:
3329 return "$11";
3330 case UNW_MIPS_R12:
3331 return "$12";
3332 case UNW_MIPS_R13:
3333 return "$13";
3334 case UNW_MIPS_R14:
3335 return "$14";
3336 case UNW_MIPS_R15:
3337 return "$15";
3338 case UNW_MIPS_R16:
3339 return "$16";
3340 case UNW_MIPS_R17:
3341 return "$17";
3342 case UNW_MIPS_R18:
3343 return "$18";
3344 case UNW_MIPS_R19:
3345 return "$19";
3346 case UNW_MIPS_R20:
3347 return "$20";
3348 case UNW_MIPS_R21:
3349 return "$21";
3350 case UNW_MIPS_R22:
3351 return "$22";
3352 case UNW_MIPS_R23:
3353 return "$23";
3354 case UNW_MIPS_R24:
3355 return "$24";
3356 case UNW_MIPS_R25:
3357 return "$25";
3358 case UNW_MIPS_R26:
3359 return "$26";
3360 case UNW_MIPS_R27:
3361 return "$27";
3362 case UNW_MIPS_R28:
3363 return "$28";
3364 case UNW_MIPS_R29:
3365 return "$29";
3366 case UNW_MIPS_R30:
3367 return "$30";
3368 case UNW_MIPS_R31:
3369 return "$31";
3370 case UNW_MIPS_F0:
3371 return "$f0";
3372 case UNW_MIPS_F1:
3373 return "$f1";
3374 case UNW_MIPS_F2:
3375 return "$f2";
3376 case UNW_MIPS_F3:
3377 return "$f3";
3378 case UNW_MIPS_F4:
3379 return "$f4";
3380 case UNW_MIPS_F5:
3381 return "$f5";
3382 case UNW_MIPS_F6:
3383 return "$f6";
3384 case UNW_MIPS_F7:
3385 return "$f7";
3386 case UNW_MIPS_F8:
3387 return "$f8";
3388 case UNW_MIPS_F9:
3389 return "$f9";
3390 case UNW_MIPS_F10:
3391 return "$f10";
3392 case UNW_MIPS_F11:
3393 return "$f11";
3394 case UNW_MIPS_F12:
3395 return "$f12";
3396 case UNW_MIPS_F13:
3397 return "$f13";
3398 case UNW_MIPS_F14:
3399 return "$f14";
3400 case UNW_MIPS_F15:
3401 return "$f15";
3402 case UNW_MIPS_F16:
3403 return "$f16";
3404 case UNW_MIPS_F17:
3405 return "$f17";
3406 case UNW_MIPS_F18:
3407 return "$f18";
3408 case UNW_MIPS_F19:
3409 return "$f19";
3410 case UNW_MIPS_F20:
3411 return "$f20";
3412 case UNW_MIPS_F21:
3413 return "$f21";
3414 case UNW_MIPS_F22:
3415 return "$f22";
3416 case UNW_MIPS_F23:
3417 return "$f23";
3418 case UNW_MIPS_F24:
3419 return "$f24";
3420 case UNW_MIPS_F25:
3421 return "$f25";
3422 case UNW_MIPS_F26:
3423 return "$f26";
3424 case UNW_MIPS_F27:
3425 return "$f27";
3426 case UNW_MIPS_F28:
3427 return "$f28";
3428 case UNW_MIPS_F29:
3429 return "$f29";
3430 case UNW_MIPS_F30:
3431 return "$f30";
3432 case UNW_MIPS_F31:
3433 return "$f31";
3434 #if __mips_isa_rev < 6
3435 case UNW_MIPS_HI:
3436 return "$hi";
3437 case UNW_MIPS_LO:
3438 return "$lo";
3439 #endif
3440 default:
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
3448 /// process.
3449 class _LIBUNWIND_HIDDEN Registers_sparc {
3450 public:
3451 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);
3464 void jumpto();
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; }
3475 private:
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)
3496 return true;
3497 if (regNum == UNW_REG_SP)
3498 return true;
3499 if (regNum < 0)
3500 return false;
3501 if (regNum <= UNW_SPARC_I7)
3502 return true;
3503 return false;
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];
3511 switch (regNum) {
3512 case UNW_REG_IP:
3513 return _registers.__regs[UNW_SPARC_O7];
3514 case UNW_REG_SP:
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;
3523 return;
3526 switch (regNum) {
3527 case UNW_REG_IP:
3528 _registers.__regs[UNW_SPARC_O7] = value;
3529 return;
3530 case UNW_REG_SP:
3531 _registers.__regs[UNW_SPARC_O6] = value;
3532 return;
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) {
3558 switch (regNum) {
3559 case UNW_REG_IP:
3560 return "pc";
3561 case UNW_SPARC_G0:
3562 return "g0";
3563 case UNW_SPARC_G1:
3564 return "g1";
3565 case UNW_SPARC_G2:
3566 return "g2";
3567 case UNW_SPARC_G3:
3568 return "g3";
3569 case UNW_SPARC_G4:
3570 return "g4";
3571 case UNW_SPARC_G5:
3572 return "g5";
3573 case UNW_SPARC_G6:
3574 return "g6";
3575 case UNW_SPARC_G7:
3576 return "g7";
3577 case UNW_SPARC_O0:
3578 return "o0";
3579 case UNW_SPARC_O1:
3580 return "o1";
3581 case UNW_SPARC_O2:
3582 return "o2";
3583 case UNW_SPARC_O3:
3584 return "o3";
3585 case UNW_SPARC_O4:
3586 return "o4";
3587 case UNW_SPARC_O5:
3588 return "o5";
3589 case UNW_REG_SP:
3590 case UNW_SPARC_O6:
3591 return "sp";
3592 case UNW_SPARC_O7:
3593 return "o7";
3594 case UNW_SPARC_L0:
3595 return "l0";
3596 case UNW_SPARC_L1:
3597 return "l1";
3598 case UNW_SPARC_L2:
3599 return "l2";
3600 case UNW_SPARC_L3:
3601 return "l3";
3602 case UNW_SPARC_L4:
3603 return "l4";
3604 case UNW_SPARC_L5:
3605 return "l5";
3606 case UNW_SPARC_L6:
3607 return "l6";
3608 case UNW_SPARC_L7:
3609 return "l7";
3610 case UNW_SPARC_I0:
3611 return "i0";
3612 case UNW_SPARC_I1:
3613 return "i1";
3614 case UNW_SPARC_I2:
3615 return "i2";
3616 case UNW_SPARC_I3:
3617 return "i3";
3618 case UNW_SPARC_I4:
3619 return "i4";
3620 case UNW_SPARC_I5:
3621 return "i5";
3622 case UNW_SPARC_I6:
3623 return "fp";
3624 case UNW_SPARC_I7:
3625 return "i7";
3626 default:
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
3634 /// sparc process.
3635 class _LIBUNWIND_HIDDEN Registers_sparc64 {
3636 public:
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);
3650 void jumpto();
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; }
3662 private:
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));
3675 memcpy(&_wcookie,
3676 static_cast<const uint8_t *>(registers) + sizeof(_registers),
3677 sizeof(_wcookie));
3680 inline bool Registers_sparc64::validRegister(int regNum) const {
3681 if (regNum == UNW_REG_IP)
3682 return true;
3683 if (regNum == UNW_REG_SP)
3684 return true;
3685 if (regNum < 0)
3686 return false;
3687 if (regNum <= UNW_SPARC_I7)
3688 return true;
3689 return false;
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];
3696 switch (regNum) {
3697 case UNW_REG_IP:
3698 return _registers.__regs[UNW_SPARC_O7];
3699 case UNW_REG_SP:
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;
3708 return;
3711 switch (regNum) {
3712 case UNW_REG_IP:
3713 _registers.__regs[UNW_SPARC_O7] = value;
3714 return;
3715 case UNW_REG_SP:
3716 _registers.__regs[UNW_SPARC_O6] = value - 2047;
3717 return;
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) {
3743 switch (regNum) {
3744 case UNW_REG_IP:
3745 return "pc";
3746 case UNW_SPARC_G0:
3747 return "g0";
3748 case UNW_SPARC_G1:
3749 return "g1";
3750 case UNW_SPARC_G2:
3751 return "g2";
3752 case UNW_SPARC_G3:
3753 return "g3";
3754 case UNW_SPARC_G4:
3755 return "g4";
3756 case UNW_SPARC_G5:
3757 return "g5";
3758 case UNW_SPARC_G6:
3759 return "g6";
3760 case UNW_SPARC_G7:
3761 return "g7";
3762 case UNW_SPARC_O0:
3763 return "o0";
3764 case UNW_SPARC_O1:
3765 return "o1";
3766 case UNW_SPARC_O2:
3767 return "o2";
3768 case UNW_SPARC_O3:
3769 return "o3";
3770 case UNW_SPARC_O4:
3771 return "o4";
3772 case UNW_SPARC_O5:
3773 return "o5";
3774 case UNW_REG_SP:
3775 case UNW_SPARC_O6:
3776 return "o6";
3777 case UNW_SPARC_O7:
3778 return "o7";
3779 case UNW_SPARC_L0:
3780 return "l0";
3781 case UNW_SPARC_L1:
3782 return "l1";
3783 case UNW_SPARC_L2:
3784 return "l2";
3785 case UNW_SPARC_L3:
3786 return "l3";
3787 case UNW_SPARC_L4:
3788 return "l4";
3789 case UNW_SPARC_L5:
3790 return "l5";
3791 case UNW_SPARC_L6:
3792 return "l6";
3793 case UNW_SPARC_L7:
3794 return "l7";
3795 case UNW_SPARC_I0:
3796 return "i0";
3797 case UNW_SPARC_I1:
3798 return "i1";
3799 case UNW_SPARC_I2:
3800 return "i2";
3801 case UNW_SPARC_I3:
3802 return "i3";
3803 case UNW_SPARC_I4:
3804 return "i4";
3805 case UNW_SPARC_I5:
3806 return "i5";
3807 case UNW_SPARC_I6:
3808 return "i6";
3809 case UNW_SPARC_I7:
3810 return "i7";
3811 default:
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
3819 /// process.
3820 class _LIBUNWIND_HIDDEN Registers_hexagon {
3821 public:
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);
3835 void jumpto();
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; }
3846 private:
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)
3867 return true;
3868 return false;
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];
3875 switch (regNum) {
3876 case UNW_REG_IP:
3877 return _registers.__r[UNW_HEXAGON_PC];
3878 case UNW_REG_SP:
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;
3887 return;
3890 switch (regNum) {
3891 case UNW_REG_IP:
3892 _registers.__r[UNW_HEXAGON_PC] = value;
3893 return;
3894 case UNW_REG_SP:
3895 _registers.__r[UNW_HEXAGON_R29] = value;
3896 return;
3898 _LIBUNWIND_ABORT("unsupported hexagon register");
3901 inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {
3902 return false;
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 {
3915 return false;
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) {
3927 switch (regNum) {
3928 case UNW_HEXAGON_R0:
3929 return "r0";
3930 case UNW_HEXAGON_R1:
3931 return "r1";
3932 case UNW_HEXAGON_R2:
3933 return "r2";
3934 case UNW_HEXAGON_R3:
3935 return "r3";
3936 case UNW_HEXAGON_R4:
3937 return "r4";
3938 case UNW_HEXAGON_R5:
3939 return "r5";
3940 case UNW_HEXAGON_R6:
3941 return "r6";
3942 case UNW_HEXAGON_R7:
3943 return "r7";
3944 case UNW_HEXAGON_R8:
3945 return "r8";
3946 case UNW_HEXAGON_R9:
3947 return "r9";
3948 case UNW_HEXAGON_R10:
3949 return "r10";
3950 case UNW_HEXAGON_R11:
3951 return "r11";
3952 case UNW_HEXAGON_R12:
3953 return "r12";
3954 case UNW_HEXAGON_R13:
3955 return "r13";
3956 case UNW_HEXAGON_R14:
3957 return "r14";
3958 case UNW_HEXAGON_R15:
3959 return "r15";
3960 case UNW_HEXAGON_R16:
3961 return "r16";
3962 case UNW_HEXAGON_R17:
3963 return "r17";
3964 case UNW_HEXAGON_R18:
3965 return "r18";
3966 case UNW_HEXAGON_R19:
3967 return "r19";
3968 case UNW_HEXAGON_R20:
3969 return "r20";
3970 case UNW_HEXAGON_R21:
3971 return "r21";
3972 case UNW_HEXAGON_R22:
3973 return "r22";
3974 case UNW_HEXAGON_R23:
3975 return "r23";
3976 case UNW_HEXAGON_R24:
3977 return "r24";
3978 case UNW_HEXAGON_R25:
3979 return "r25";
3980 case UNW_HEXAGON_R26:
3981 return "r26";
3982 case UNW_HEXAGON_R27:
3983 return "r27";
3984 case UNW_HEXAGON_R28:
3985 return "r28";
3986 case UNW_HEXAGON_R29:
3987 return "r29";
3988 case UNW_HEXAGON_R30:
3989 return "r30";
3990 case UNW_HEXAGON_R31:
3991 return "r31";
3992 default:
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
4002 /// process.
4004 // This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.
4005 # ifdef __riscv
4006 # if __riscv_xlen == 32
4007 typedef uint32_t reg_t;
4008 # elif __riscv_xlen == 64
4009 typedef uint64_t reg_t;
4010 # else
4011 # error "Unsupported __riscv_xlen"
4012 # endif
4014 # if defined(__riscv_flen)
4015 # if __riscv_flen == 64
4016 typedef double fp_t;
4017 # elif __riscv_flen == 32
4018 typedef float fp_t;
4019 # else
4020 # error "Unsupported __riscv_flen"
4021 # endif
4022 # else
4023 // This is just for suppressing undeclared error of fp_t.
4024 typedef double fp_t;
4025 # endif
4026 # else
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
4032 #endif
4034 /// Registers_riscv holds the register state of a thread.
4035 class _LIBUNWIND_HIDDEN Registers_riscv {
4036 public:
4037 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);
4050 void jumpto();
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; }
4061 private:
4062 // _registers[0] holds the pc
4063 reg_t _registers[32];
4064 # if defined(__riscv_flen)
4065 fp_t _floats[32];
4066 # endif
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");
4079 # else
4080 # error "Unexpected float registers."
4081 # endif
4083 # if defined(__riscv_flen)
4084 memcpy(_floats,
4085 static_cast<const uint8_t *>(registers) + sizeof(_registers),
4086 sizeof(_floats));
4087 # endif
4090 inline Registers_riscv::Registers_riscv() {
4091 memset(&_registers, 0, sizeof(_registers));
4092 # if defined(__riscv_flen)
4093 memset(&_floats, 0, sizeof(_floats));
4094 # endif
4097 inline bool Registers_riscv::validRegister(int regNum) const {
4098 if (regNum == UNW_REG_IP)
4099 return true;
4100 if (regNum == UNW_REG_SP)
4101 return true;
4102 if (regNum < 0)
4103 return false;
4104 if (regNum == UNW_RISCV_VLENB)
4105 return true;
4106 if (regNum > UNW_RISCV_F31)
4107 return false;
4108 return true;
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)
4117 return 0;
4118 if ((regNum > 0) && (regNum < 32))
4119 return _registers[regNum];
4120 if (regNum == UNW_RISCV_VLENB) {
4121 reg_t vlenb;
4122 __asm__("csrr %0, 0xC22" : "=r"(vlenb));
4123 return 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 */
4135 return;
4136 else if ((regNum > 0) && (regNum < 32))
4137 _registers[regNum] = value;
4138 else
4139 _LIBUNWIND_ABORT("unsupported riscv register");
4142 inline const char *Registers_riscv::getRegisterName(int regNum) {
4143 switch (regNum) {
4144 case UNW_REG_IP:
4145 return "pc";
4146 case UNW_REG_SP:
4147 return "sp";
4148 case UNW_RISCV_X0:
4149 return "zero";
4150 case UNW_RISCV_X1:
4151 return "ra";
4152 case UNW_RISCV_X2:
4153 return "sp";
4154 case UNW_RISCV_X3:
4155 return "gp";
4156 case UNW_RISCV_X4:
4157 return "tp";
4158 case UNW_RISCV_X5:
4159 return "t0";
4160 case UNW_RISCV_X6:
4161 return "t1";
4162 case UNW_RISCV_X7:
4163 return "t2";
4164 case UNW_RISCV_X8:
4165 return "s0";
4166 case UNW_RISCV_X9:
4167 return "s1";
4168 case UNW_RISCV_X10:
4169 return "a0";
4170 case UNW_RISCV_X11:
4171 return "a1";
4172 case UNW_RISCV_X12:
4173 return "a2";
4174 case UNW_RISCV_X13:
4175 return "a3";
4176 case UNW_RISCV_X14:
4177 return "a4";
4178 case UNW_RISCV_X15:
4179 return "a5";
4180 case UNW_RISCV_X16:
4181 return "a6";
4182 case UNW_RISCV_X17:
4183 return "a7";
4184 case UNW_RISCV_X18:
4185 return "s2";
4186 case UNW_RISCV_X19:
4187 return "s3";
4188 case UNW_RISCV_X20:
4189 return "s4";
4190 case UNW_RISCV_X21:
4191 return "s5";
4192 case UNW_RISCV_X22:
4193 return "s6";
4194 case UNW_RISCV_X23:
4195 return "s7";
4196 case UNW_RISCV_X24:
4197 return "s8";
4198 case UNW_RISCV_X25:
4199 return "s9";
4200 case UNW_RISCV_X26:
4201 return "s10";
4202 case UNW_RISCV_X27:
4203 return "s11";
4204 case UNW_RISCV_X28:
4205 return "t3";
4206 case UNW_RISCV_X29:
4207 return "t4";
4208 case UNW_RISCV_X30:
4209 return "t5";
4210 case UNW_RISCV_X31:
4211 return "t6";
4212 case UNW_RISCV_F0:
4213 return "ft0";
4214 case UNW_RISCV_F1:
4215 return "ft1";
4216 case UNW_RISCV_F2:
4217 return "ft2";
4218 case UNW_RISCV_F3:
4219 return "ft3";
4220 case UNW_RISCV_F4:
4221 return "ft4";
4222 case UNW_RISCV_F5:
4223 return "ft5";
4224 case UNW_RISCV_F6:
4225 return "ft6";
4226 case UNW_RISCV_F7:
4227 return "ft7";
4228 case UNW_RISCV_F8:
4229 return "fs0";
4230 case UNW_RISCV_F9:
4231 return "fs1";
4232 case UNW_RISCV_F10:
4233 return "fa0";
4234 case UNW_RISCV_F11:
4235 return "fa1";
4236 case UNW_RISCV_F12:
4237 return "fa2";
4238 case UNW_RISCV_F13:
4239 return "fa3";
4240 case UNW_RISCV_F14:
4241 return "fa4";
4242 case UNW_RISCV_F15:
4243 return "fa5";
4244 case UNW_RISCV_F16:
4245 return "fa6";
4246 case UNW_RISCV_F17:
4247 return "fa7";
4248 case UNW_RISCV_F18:
4249 return "fs2";
4250 case UNW_RISCV_F19:
4251 return "fs3";
4252 case UNW_RISCV_F20:
4253 return "fs4";
4254 case UNW_RISCV_F21:
4255 return "fs5";
4256 case UNW_RISCV_F22:
4257 return "fs6";
4258 case UNW_RISCV_F23:
4259 return "fs7";
4260 case UNW_RISCV_F24:
4261 return "fs8";
4262 case UNW_RISCV_F25:
4263 return "fs9";
4264 case UNW_RISCV_F26:
4265 return "fs10";
4266 case UNW_RISCV_F27:
4267 return "fs11";
4268 case UNW_RISCV_F28:
4269 return "ft8";
4270 case UNW_RISCV_F29:
4271 return "ft9";
4272 case UNW_RISCV_F30:
4273 return "ft10";
4274 case UNW_RISCV_F31:
4275 return "ft11";
4276 case UNW_RISCV_VLENB:
4277 return "vlenb";
4278 default:
4279 return "unknown register";
4283 inline bool Registers_riscv::validFloatRegister(int regNum) const {
4284 # if defined(__riscv_flen)
4285 if (regNum < UNW_RISCV_F0)
4286 return false;
4287 if (regNum > UNW_RISCV_F31)
4288 return false;
4289 return true;
4290 # else
4291 (void)regNum;
4292 return false;
4293 # endif
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];
4300 # else
4301 (void)regNum;
4302 _LIBUNWIND_ABORT("libunwind not built with float support");
4303 # endif
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;
4310 # else
4311 (void)regNum;
4312 (void)value;
4313 _LIBUNWIND_ABORT("libunwind not built with float support");
4314 # endif
4317 inline bool Registers_riscv::validVectorRegister(int) const {
4318 return false;
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 {
4333 public:
4334 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);
4347 void jumpto();
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; }
4358 private:
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)
4390 return true;
4392 switch (regNum) {
4393 case UNW_REG_IP:
4394 case UNW_REG_SP:
4395 case UNW_VE_VIXR:
4396 case UNW_VE_VL:
4397 return true;
4398 default:
4399 return false;
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];
4407 switch (regNum) {
4408 case UNW_REG_IP:
4409 return _registers.__ic;
4410 case UNW_REG_SP:
4411 return _registers.__s[11];
4412 case UNW_VE_VIXR:
4413 return _registers.__vixr;
4414 case UNW_VE_VL:
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;
4423 return;
4426 switch (regNum) {
4427 case UNW_REG_IP:
4428 _registers.__ic = value;
4429 return;
4430 case UNW_REG_SP:
4431 _registers.__s[11] = value;
4432 return;
4433 case UNW_VE_VIXR:
4434 _registers.__vixr = value;
4435 return;
4436 case UNW_VE_VL:
4437 _registers.__vl = value;
4438 return;
4440 _LIBUNWIND_ABORT("unsupported ve register");
4443 inline bool Registers_ve::validFloatRegister(int /* regNum */) const {
4444 return false;
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 {
4457 return false;
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 */,
4465 v128 /* value */) {
4466 _LIBUNWIND_ABORT("VE vector support not implemented");
4469 inline const char *Registers_ve::getRegisterName(int regNum) {
4470 switch (regNum) {
4471 case UNW_REG_IP:
4472 return "ip";
4473 case UNW_REG_SP:
4474 return "sp";
4475 case UNW_VE_VIXR:
4476 return "vixr";
4477 case UNW_VE_VL:
4478 return "vl";
4479 case UNW_VE_S0:
4480 return "s0";
4481 case UNW_VE_S1:
4482 return "s1";
4483 case UNW_VE_S2:
4484 return "s2";
4485 case UNW_VE_S3:
4486 return "s3";
4487 case UNW_VE_S4:
4488 return "s4";
4489 case UNW_VE_S5:
4490 return "s5";
4491 case UNW_VE_S6:
4492 return "s6";
4493 case UNW_VE_S7:
4494 return "s7";
4495 case UNW_VE_S8:
4496 return "s8";
4497 case UNW_VE_S9:
4498 return "s9";
4499 case UNW_VE_S10:
4500 return "s10";
4501 case UNW_VE_S11:
4502 return "s11";
4503 case UNW_VE_S12:
4504 return "s12";
4505 case UNW_VE_S13:
4506 return "s13";
4507 case UNW_VE_S14:
4508 return "s14";
4509 case UNW_VE_S15:
4510 return "s15";
4511 case UNW_VE_S16:
4512 return "s16";
4513 case UNW_VE_S17:
4514 return "s17";
4515 case UNW_VE_S18:
4516 return "s18";
4517 case UNW_VE_S19:
4518 return "s19";
4519 case UNW_VE_S20:
4520 return "s20";
4521 case UNW_VE_S21:
4522 return "s21";
4523 case UNW_VE_S22:
4524 return "s22";
4525 case UNW_VE_S23:
4526 return "s23";
4527 case UNW_VE_S24:
4528 return "s24";
4529 case UNW_VE_S25:
4530 return "s25";
4531 case UNW_VE_S26:
4532 return "s26";
4533 case UNW_VE_S27:
4534 return "s27";
4535 case UNW_VE_S28:
4536 return "s28";
4537 case UNW_VE_S29:
4538 return "s29";
4539 case UNW_VE_S30:
4540 return "s30";
4541 case UNW_VE_S31:
4542 return "s31";
4543 case UNW_VE_S32:
4544 return "s32";
4545 case UNW_VE_S33:
4546 return "s33";
4547 case UNW_VE_S34:
4548 return "s34";
4549 case UNW_VE_S35:
4550 return "s35";
4551 case UNW_VE_S36:
4552 return "s36";
4553 case UNW_VE_S37:
4554 return "s37";
4555 case UNW_VE_S38:
4556 return "s38";
4557 case UNW_VE_S39:
4558 return "s39";
4559 case UNW_VE_S40:
4560 return "s40";
4561 case UNW_VE_S41:
4562 return "s41";
4563 case UNW_VE_S42:
4564 return "s42";
4565 case UNW_VE_S43:
4566 return "s43";
4567 case UNW_VE_S44:
4568 return "s44";
4569 case UNW_VE_S45:
4570 return "s45";
4571 case UNW_VE_S46:
4572 return "s46";
4573 case UNW_VE_S47:
4574 return "s47";
4575 case UNW_VE_S48:
4576 return "s48";
4577 case UNW_VE_S49:
4578 return "s49";
4579 case UNW_VE_S50:
4580 return "s50";
4581 case UNW_VE_S51:
4582 return "s51";
4583 case UNW_VE_S52:
4584 return "s52";
4585 case UNW_VE_S53:
4586 return "s53";
4587 case UNW_VE_S54:
4588 return "s54";
4589 case UNW_VE_S55:
4590 return "s55";
4591 case UNW_VE_S56:
4592 return "s56";
4593 case UNW_VE_S57:
4594 return "s57";
4595 case UNW_VE_S58:
4596 return "s58";
4597 case UNW_VE_S59:
4598 return "s59";
4599 case UNW_VE_S60:
4600 return "s60";
4601 case UNW_VE_S61:
4602 return "s61";
4603 case UNW_VE_S62:
4604 return "s62";
4605 case UNW_VE_S63:
4606 return "s63";
4607 case UNW_VE_V0:
4608 return "v0";
4609 case UNW_VE_V1:
4610 return "v1";
4611 case UNW_VE_V2:
4612 return "v2";
4613 case UNW_VE_V3:
4614 return "v3";
4615 case UNW_VE_V4:
4616 return "v4";
4617 case UNW_VE_V5:
4618 return "v5";
4619 case UNW_VE_V6:
4620 return "v6";
4621 case UNW_VE_V7:
4622 return "v7";
4623 case UNW_VE_V8:
4624 return "v8";
4625 case UNW_VE_V9:
4626 return "v9";
4627 case UNW_VE_V10:
4628 return "v10";
4629 case UNW_VE_V11:
4630 return "v11";
4631 case UNW_VE_V12:
4632 return "v12";
4633 case UNW_VE_V13:
4634 return "v13";
4635 case UNW_VE_V14:
4636 return "v14";
4637 case UNW_VE_V15:
4638 return "v15";
4639 case UNW_VE_V16:
4640 return "v16";
4641 case UNW_VE_V17:
4642 return "v17";
4643 case UNW_VE_V18:
4644 return "v18";
4645 case UNW_VE_V19:
4646 return "v19";
4647 case UNW_VE_V20:
4648 return "v20";
4649 case UNW_VE_V21:
4650 return "v21";
4651 case UNW_VE_V22:
4652 return "v22";
4653 case UNW_VE_V23:
4654 return "v23";
4655 case UNW_VE_V24:
4656 return "v24";
4657 case UNW_VE_V25:
4658 return "v25";
4659 case UNW_VE_V26:
4660 return "v26";
4661 case UNW_VE_V27:
4662 return "v27";
4663 case UNW_VE_V28:
4664 return "v28";
4665 case UNW_VE_V29:
4666 return "v29";
4667 case UNW_VE_V30:
4668 return "v30";
4669 case UNW_VE_V31:
4670 return "v31";
4671 case UNW_VE_V32:
4672 return "v32";
4673 case UNW_VE_V33:
4674 return "v33";
4675 case UNW_VE_V34:
4676 return "v34";
4677 case UNW_VE_V35:
4678 return "v35";
4679 case UNW_VE_V36:
4680 return "v36";
4681 case UNW_VE_V37:
4682 return "v37";
4683 case UNW_VE_V38:
4684 return "v38";
4685 case UNW_VE_V39:
4686 return "v39";
4687 case UNW_VE_V40:
4688 return "v40";
4689 case UNW_VE_V41:
4690 return "v41";
4691 case UNW_VE_V42:
4692 return "v42";
4693 case UNW_VE_V43:
4694 return "v43";
4695 case UNW_VE_V44:
4696 return "v44";
4697 case UNW_VE_V45:
4698 return "v45";
4699 case UNW_VE_V46:
4700 return "v46";
4701 case UNW_VE_V47:
4702 return "v47";
4703 case UNW_VE_V48:
4704 return "v48";
4705 case UNW_VE_V49:
4706 return "v49";
4707 case UNW_VE_V50:
4708 return "v50";
4709 case UNW_VE_V51:
4710 return "v51";
4711 case UNW_VE_V52:
4712 return "v52";
4713 case UNW_VE_V53:
4714 return "v53";
4715 case UNW_VE_V54:
4716 return "v54";
4717 case UNW_VE_V55:
4718 return "v55";
4719 case UNW_VE_V56:
4720 return "v56";
4721 case UNW_VE_V57:
4722 return "v57";
4723 case UNW_VE_V58:
4724 return "v58";
4725 case UNW_VE_V59:
4726 return "v59";
4727 case UNW_VE_V60:
4728 return "v60";
4729 case UNW_VE_V61:
4730 return "v61";
4731 case UNW_VE_V62:
4732 return "v62";
4733 case UNW_VE_V63:
4734 return "v63";
4735 case UNW_VE_VM0:
4736 return "vm0";
4737 case UNW_VE_VM1:
4738 return "vm1";
4739 case UNW_VE_VM2:
4740 return "vm2";
4741 case UNW_VE_VM3:
4742 return "vm3";
4743 case UNW_VE_VM4:
4744 return "vm4";
4745 case UNW_VE_VM5:
4746 return "vm5";
4747 case UNW_VE_VM6:
4748 return "vm6";
4749 case UNW_VE_VM7:
4750 return "vm7";
4751 case UNW_VE_VM8:
4752 return "vm8";
4753 case UNW_VE_VM9:
4754 return "vm9";
4755 case UNW_VE_VM10:
4756 return "vm10";
4757 case UNW_VE_VM11:
4758 return "vm11";
4759 case UNW_VE_VM12:
4760 return "vm12";
4761 case UNW_VE_VM13:
4762 return "vm13";
4763 case UNW_VE_VM14:
4764 return "vm14";
4765 case UNW_VE_VM15:
4766 return "vm15";
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 {
4776 public:
4777 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);
4790 void jumpto();
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; }
4801 private:
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 {
4824 switch (regNum) {
4825 case UNW_S390X_PSWM:
4826 case UNW_S390X_PSWA:
4827 case UNW_REG_IP:
4828 case UNW_REG_SP:
4829 return true;
4832 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
4833 return true;
4835 return false;
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];
4842 switch (regNum) {
4843 case UNW_S390X_PSWM:
4844 return _registers.__pswm;
4845 case UNW_S390X_PSWA:
4846 case UNW_REG_IP:
4847 return _registers.__pswa;
4848 case UNW_REG_SP:
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;
4857 return;
4860 switch (regNum) {
4861 case UNW_S390X_PSWM:
4862 _registers.__pswm = value;
4863 return;
4864 case UNW_S390X_PSWA:
4865 case UNW_REG_IP:
4866 _registers.__pswa = value;
4867 return;
4868 case UNW_REG_SP:
4869 _registers.__gpr[15] = value;
4870 return;
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.
4881 switch (regNum) {
4882 case UNW_S390X_F0:
4883 return _registers.__fpr[0];
4884 case UNW_S390X_F1:
4885 return _registers.__fpr[1];
4886 case UNW_S390X_F2:
4887 return _registers.__fpr[2];
4888 case UNW_S390X_F3:
4889 return _registers.__fpr[3];
4890 case UNW_S390X_F4:
4891 return _registers.__fpr[4];
4892 case UNW_S390X_F5:
4893 return _registers.__fpr[5];
4894 case UNW_S390X_F6:
4895 return _registers.__fpr[6];
4896 case UNW_S390X_F7:
4897 return _registers.__fpr[7];
4898 case UNW_S390X_F8:
4899 return _registers.__fpr[8];
4900 case UNW_S390X_F9:
4901 return _registers.__fpr[9];
4902 case UNW_S390X_F10:
4903 return _registers.__fpr[10];
4904 case UNW_S390X_F11:
4905 return _registers.__fpr[11];
4906 case UNW_S390X_F12:
4907 return _registers.__fpr[12];
4908 case UNW_S390X_F13:
4909 return _registers.__fpr[13];
4910 case UNW_S390X_F14:
4911 return _registers.__fpr[14];
4912 case UNW_S390X_F15:
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.
4920 switch (regNum) {
4921 case UNW_S390X_F0:
4922 _registers.__fpr[0] = value;
4923 return;
4924 case UNW_S390X_F1:
4925 _registers.__fpr[1] = value;
4926 return;
4927 case UNW_S390X_F2:
4928 _registers.__fpr[2] = value;
4929 return;
4930 case UNW_S390X_F3:
4931 _registers.__fpr[3] = value;
4932 return;
4933 case UNW_S390X_F4:
4934 _registers.__fpr[4] = value;
4935 return;
4936 case UNW_S390X_F5:
4937 _registers.__fpr[5] = value;
4938 return;
4939 case UNW_S390X_F6:
4940 _registers.__fpr[6] = value;
4941 return;
4942 case UNW_S390X_F7:
4943 _registers.__fpr[7] = value;
4944 return;
4945 case UNW_S390X_F8:
4946 _registers.__fpr[8] = value;
4947 return;
4948 case UNW_S390X_F9:
4949 _registers.__fpr[9] = value;
4950 return;
4951 case UNW_S390X_F10:
4952 _registers.__fpr[10] = value;
4953 return;
4954 case UNW_S390X_F11:
4955 _registers.__fpr[11] = value;
4956 return;
4957 case UNW_S390X_F12:
4958 _registers.__fpr[12] = value;
4959 return;
4960 case UNW_S390X_F13:
4961 _registers.__fpr[13] = value;
4962 return;
4963 case UNW_S390X_F14:
4964 _registers.__fpr[14] = value;
4965 return;
4966 case UNW_S390X_F15:
4967 _registers.__fpr[15] = value;
4968 return;
4970 _LIBUNWIND_ABORT("unsupported s390x register");
4973 inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
4974 return false;
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) {
4986 switch (regNum) {
4987 case UNW_REG_IP:
4988 return "ip";
4989 case UNW_REG_SP:
4990 return "sp";
4991 case UNW_S390X_R0:
4992 return "r0";
4993 case UNW_S390X_R1:
4994 return "r1";
4995 case UNW_S390X_R2:
4996 return "r2";
4997 case UNW_S390X_R3:
4998 return "r3";
4999 case UNW_S390X_R4:
5000 return "r4";
5001 case UNW_S390X_R5:
5002 return "r5";
5003 case UNW_S390X_R6:
5004 return "r6";
5005 case UNW_S390X_R7:
5006 return "r7";
5007 case UNW_S390X_R8:
5008 return "r8";
5009 case UNW_S390X_R9:
5010 return "r9";
5011 case UNW_S390X_R10:
5012 return "r10";
5013 case UNW_S390X_R11:
5014 return "r11";
5015 case UNW_S390X_R12:
5016 return "r12";
5017 case UNW_S390X_R13:
5018 return "r13";
5019 case UNW_S390X_R14:
5020 return "r14";
5021 case UNW_S390X_R15:
5022 return "r15";
5023 case UNW_S390X_F0:
5024 return "f0";
5025 case UNW_S390X_F1:
5026 return "f1";
5027 case UNW_S390X_F2:
5028 return "f2";
5029 case UNW_S390X_F3:
5030 return "f3";
5031 case UNW_S390X_F4:
5032 return "f4";
5033 case UNW_S390X_F5:
5034 return "f5";
5035 case UNW_S390X_F6:
5036 return "f6";
5037 case UNW_S390X_F7:
5038 return "f7";
5039 case UNW_S390X_F8:
5040 return "f8";
5041 case UNW_S390X_F9:
5042 return "f9";
5043 case UNW_S390X_F10:
5044 return "f10";
5045 case UNW_S390X_F11:
5046 return "f11";
5047 case UNW_S390X_F12:
5048 return "f12";
5049 case UNW_S390X_F13:
5050 return "f13";
5051 case UNW_S390X_F14:
5052 return "f14";
5053 case UNW_S390X_F15:
5054 return "f15";
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 {
5064 public:
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);
5078 void jumpto();
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; }
5089 private:
5090 struct loongarch_thread_state_t {
5091 uint64_t __r[32];
5092 uint64_t __pc;
5095 loongarch_thread_state_t _registers;
5096 #if __loongarch_frlen == 64
5097 double _floats[32];
5098 #endif
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),
5109 sizeof(_floats));
5110 #endif
5113 inline Registers_loongarch::Registers_loongarch() {
5114 memset(&_registers, 0, sizeof(_registers));
5115 #if __loongarch_frlen == 64
5116 memset(&_floats, 0, sizeof(_floats));
5117 #endif
5120 inline bool Registers_loongarch::validRegister(int regNum) const {
5121 if (regNum == UNW_REG_IP || regNum == UNW_REG_SP)
5122 return true;
5123 if (regNum < 0 || regNum > UNW_LOONGARCH_F31)
5124 return false;
5125 return true;
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;
5146 else
5147 _LIBUNWIND_ABORT("unsupported loongarch register");
5150 inline const char *Registers_loongarch::getRegisterName(int regNum) {
5151 switch (regNum) {
5152 case UNW_REG_IP:
5153 return "$pc";
5154 case UNW_REG_SP:
5155 return "$sp";
5156 case UNW_LOONGARCH_R0:
5157 return "$r0";
5158 case UNW_LOONGARCH_R1:
5159 return "$r1";
5160 case UNW_LOONGARCH_R2:
5161 return "$r2";
5162 case UNW_LOONGARCH_R3:
5163 return "$r3";
5164 case UNW_LOONGARCH_R4:
5165 return "$r4";
5166 case UNW_LOONGARCH_R5:
5167 return "$r5";
5168 case UNW_LOONGARCH_R6:
5169 return "$r6";
5170 case UNW_LOONGARCH_R7:
5171 return "$r7";
5172 case UNW_LOONGARCH_R8:
5173 return "$r8";
5174 case UNW_LOONGARCH_R9:
5175 return "$r9";
5176 case UNW_LOONGARCH_R10:
5177 return "$r10";
5178 case UNW_LOONGARCH_R11:
5179 return "$r11";
5180 case UNW_LOONGARCH_R12:
5181 return "$r12";
5182 case UNW_LOONGARCH_R13:
5183 return "$r13";
5184 case UNW_LOONGARCH_R14:
5185 return "$r14";
5186 case UNW_LOONGARCH_R15:
5187 return "$r15";
5188 case UNW_LOONGARCH_R16:
5189 return "$r16";
5190 case UNW_LOONGARCH_R17:
5191 return "$r17";
5192 case UNW_LOONGARCH_R18:
5193 return "$r18";
5194 case UNW_LOONGARCH_R19:
5195 return "$r19";
5196 case UNW_LOONGARCH_R20:
5197 return "$r20";
5198 case UNW_LOONGARCH_R21:
5199 return "$r21";
5200 case UNW_LOONGARCH_R22:
5201 return "$r22";
5202 case UNW_LOONGARCH_R23:
5203 return "$r23";
5204 case UNW_LOONGARCH_R24:
5205 return "$r24";
5206 case UNW_LOONGARCH_R25:
5207 return "$r25";
5208 case UNW_LOONGARCH_R26:
5209 return "$r26";
5210 case UNW_LOONGARCH_R27:
5211 return "$r27";
5212 case UNW_LOONGARCH_R28:
5213 return "$r28";
5214 case UNW_LOONGARCH_R29:
5215 return "$r29";
5216 case UNW_LOONGARCH_R30:
5217 return "$r30";
5218 case UNW_LOONGARCH_R31:
5219 return "$r31";
5220 case UNW_LOONGARCH_F0:
5221 return "$f0";
5222 case UNW_LOONGARCH_F1:
5223 return "$f1";
5224 case UNW_LOONGARCH_F2:
5225 return "$f2";
5226 case UNW_LOONGARCH_F3:
5227 return "$f3";
5228 case UNW_LOONGARCH_F4:
5229 return "$f4";
5230 case UNW_LOONGARCH_F5:
5231 return "$f5";
5232 case UNW_LOONGARCH_F6:
5233 return "$f6";
5234 case UNW_LOONGARCH_F7:
5235 return "$f7";
5236 case UNW_LOONGARCH_F8:
5237 return "$f8";
5238 case UNW_LOONGARCH_F9:
5239 return "$f9";
5240 case UNW_LOONGARCH_F10:
5241 return "$f10";
5242 case UNW_LOONGARCH_F11:
5243 return "$f11";
5244 case UNW_LOONGARCH_F12:
5245 return "$f12";
5246 case UNW_LOONGARCH_F13:
5247 return "$f13";
5248 case UNW_LOONGARCH_F14:
5249 return "$f14";
5250 case UNW_LOONGARCH_F15:
5251 return "$f15";
5252 case UNW_LOONGARCH_F16:
5253 return "$f16";
5254 case UNW_LOONGARCH_F17:
5255 return "$f17";
5256 case UNW_LOONGARCH_F18:
5257 return "$f18";
5258 case UNW_LOONGARCH_F19:
5259 return "$f19";
5260 case UNW_LOONGARCH_F20:
5261 return "$f20";
5262 case UNW_LOONGARCH_F21:
5263 return "$f21";
5264 case UNW_LOONGARCH_F22:
5265 return "$f22";
5266 case UNW_LOONGARCH_F23:
5267 return "$f23";
5268 case UNW_LOONGARCH_F24:
5269 return "$f24";
5270 case UNW_LOONGARCH_F25:
5271 return "$f25";
5272 case UNW_LOONGARCH_F26:
5273 return "$f26";
5274 case UNW_LOONGARCH_F27:
5275 return "$f27";
5276 case UNW_LOONGARCH_F28:
5277 return "$f28";
5278 case UNW_LOONGARCH_F29:
5279 return "$f29";
5280 case UNW_LOONGARCH_F30:
5281 return "$f30";
5282 case UNW_LOONGARCH_F31:
5283 return "$f31";
5284 default:
5285 return "unknown register";
5289 inline bool Registers_loongarch::validFloatRegister(int regNum) const {
5290 if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31)
5291 return false;
5292 return true;
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];
5299 #else
5300 _LIBUNWIND_ABORT("libunwind not built with float support");
5301 #endif
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;
5308 #else
5309 _LIBUNWIND_ABORT("libunwind not built with float support");
5310 #endif
5313 inline bool Registers_loongarch::validVectorRegister(int) const {
5314 return false;
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__