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//===----------------------------------------------------------------------===//
11
12#ifndef __REGISTERS_HPP__
13#define __REGISTERS_HPP__
14
15#include <stdint.h>
16#include <string.h>
17
18#include "config.h"
19#include "libunwind.h"
20#include "libunwind_ext.h"
21#include "shadow_stack_unwind.h"
22
23#if __has_include(<sys/auxv.h>)
24#include <sys/auxv.h>
25#define HAVE_SYS_AUXV_H
26#endif
27
28namespace libunwind {
29
30// For emulating 128-bit registers
31struct v128 { uint32_t vec[4]; };
32
33enum {
34 REGISTERS_X86,
35 REGISTERS_X86_64,
36 REGISTERS_PPC,
37 REGISTERS_PPC64,
38 REGISTERS_ARM64,
39 REGISTERS_ARM,
40 REGISTERS_OR1K,
41 REGISTERS_MIPS_O32,
42 REGISTERS_MIPS_NEWABI,
43 REGISTERS_SPARC,
44 REGISTERS_SPARC64,
45 REGISTERS_HEXAGON,
46 REGISTERS_RISCV,
47 REGISTERS_VE,
48 REGISTERS_S390X,
49 REGISTERS_LOONGARCH,
50};
51
52#if defined(_LIBUNWIND_TARGET_I386)
53class _LIBUNWIND_HIDDEN Registers_x86;
54extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
55
56#if defined(_LIBUNWIND_USE_CET)
57extern "C" void *__libunwind_shstk_get_jump_target() {
58 return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto);
59}
60#endif
61
62/// Registers_x86 holds the register state of a thread in a 32-bit intel
63/// process.
64class _LIBUNWIND_HIDDEN Registers_x86 {
65public:
66 Registers_x86();
67 Registers_x86(const void *registers);
68
69 typedef uint32_t reg_t;
70 typedef uint32_t link_reg_t;
71 typedef const link_reg_t &link_hardened_reg_arg_t;
72
73 bool validRegister(int num) const;
74 uint32_t getRegister(int num) const;
75 void setRegister(int num, uint32_t value);
76 bool validFloatRegister(int) const { return false; }
77 double getFloatRegister(int num) const;
78 void setFloatRegister(int num, double value);
79 bool validVectorRegister(int) const { return false; }
80 v128 getVectorRegister(int num) const;
81 void setVectorRegister(int num, v128 value);
82 static const char *getRegisterName(int num);
83 void jumpto() { __libunwind_Registers_x86_jumpto(this); }
84 static constexpr int lastDwarfRegNum() {
85 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86;
86 }
87 static int getArch() { return REGISTERS_X86; }
88
89 uint32_t getSP() const { return _registers.__esp; }
90 void setSP(uint32_t value) { _registers.__esp = value; }
91 uint32_t getIP() const { return _registers.__eip; }
92 void setIP(uint32_t value) { _registers.__eip = value; }
93 uint32_t getEBP() const { return _registers.__ebp; }
94 void setEBP(uint32_t value) { _registers.__ebp = value; }
95 uint32_t getEBX() const { return _registers.__ebx; }
96 void setEBX(uint32_t value) { _registers.__ebx = value; }
97 uint32_t getECX() const { return _registers.__ecx; }
98 void setECX(uint32_t value) { _registers.__ecx = value; }
99 uint32_t getEDX() const { return _registers.__edx; }
100 void setEDX(uint32_t value) { _registers.__edx = value; }
101 uint32_t getESI() const { return _registers.__esi; }
102 void setESI(uint32_t value) { _registers.__esi = value; }
103 uint32_t getEDI() const { return _registers.__edi; }
104 void setEDI(uint32_t value) { _registers.__edi = value; }
105
106private:
107 struct GPRs {
108 unsigned int __eax;
109 unsigned int __ebx;
110 unsigned int __ecx;
111 unsigned int __edx;
112 unsigned int __edi;
113 unsigned int __esi;
114 unsigned int __ebp;
115 unsigned int __esp;
116 unsigned int __ss;
117 unsigned int __eflags;
118 unsigned int __eip;
119 unsigned int __cs;
120 unsigned int __ds;
121 unsigned int __es;
122 unsigned int __fs;
123 unsigned int __gs;
124 };
125
126 GPRs _registers;
127};
128
129inline Registers_x86::Registers_x86(const void *registers) {
130 static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
131 "x86 registers do not fit into unw_context_t");
132 memcpy(&_registers, registers, sizeof(_registers));
133}
134
135inline Registers_x86::Registers_x86() {
136 memset(&_registers, 0, sizeof(_registers));
137}
138
139inline bool Registers_x86::validRegister(int regNum) const {
140 if (regNum == UNW_REG_IP)
141 return true;
142 if (regNum == UNW_REG_SP)
143 return true;
144 if (regNum < 0)
145 return false;
146 if (regNum > 7)
147 return false;
148 return true;
149}
150
151inline uint32_t Registers_x86::getRegister(int regNum) const {
152 switch (regNum) {
153 case UNW_REG_IP:
154 return _registers.__eip;
155 case UNW_REG_SP:
156 return _registers.__esp;
157 case UNW_X86_EAX:
158 return _registers.__eax;
159 case UNW_X86_ECX:
160 return _registers.__ecx;
161 case UNW_X86_EDX:
162 return _registers.__edx;
163 case UNW_X86_EBX:
164 return _registers.__ebx;
165#if !defined(__APPLE__)
166 case UNW_X86_ESP:
167#else
168 case UNW_X86_EBP:
169#endif
170 return _registers.__ebp;
171#if !defined(__APPLE__)
172 case UNW_X86_EBP:
173#else
174 case UNW_X86_ESP:
175#endif
176 return _registers.__esp;
177 case UNW_X86_ESI:
178 return _registers.__esi;
179 case UNW_X86_EDI:
180 return _registers.__edi;
181 }
182 _LIBUNWIND_ABORT("unsupported x86 register");
183}
184
185inline void Registers_x86::setRegister(int regNum, uint32_t value) {
186 switch (regNum) {
187 case UNW_REG_IP:
188 _registers.__eip = value;
189 return;
190 case UNW_REG_SP:
191 _registers.__esp = value;
192 return;
193 case UNW_X86_EAX:
194 _registers.__eax = value;
195 return;
196 case UNW_X86_ECX:
197 _registers.__ecx = value;
198 return;
199 case UNW_X86_EDX:
200 _registers.__edx = value;
201 return;
202 case UNW_X86_EBX:
203 _registers.__ebx = value;
204 return;
205#if !defined(__APPLE__)
206 case UNW_X86_ESP:
207#else
208 case UNW_X86_EBP:
209#endif
210 _registers.__ebp = value;
211 return;
212#if !defined(__APPLE__)
213 case UNW_X86_EBP:
214#else
215 case UNW_X86_ESP:
216#endif
217 _registers.__esp = value;
218 return;
219 case UNW_X86_ESI:
220 _registers.__esi = value;
221 return;
222 case UNW_X86_EDI:
223 _registers.__edi = value;
224 return;
225 }
226 _LIBUNWIND_ABORT("unsupported x86 register");
227}
228
229inline const char *Registers_x86::getRegisterName(int regNum) {
230 switch (regNum) {
231 case UNW_REG_IP:
232 return "ip";
233 case UNW_REG_SP:
234 return "esp";
235 case UNW_X86_EAX:
236 return "eax";
237 case UNW_X86_ECX:
238 return "ecx";
239 case UNW_X86_EDX:
240 return "edx";
241 case UNW_X86_EBX:
242 return "ebx";
243 case UNW_X86_EBP:
244 return "ebp";
245 case UNW_X86_ESP:
246 return "esp";
247 case UNW_X86_ESI:
248 return "esi";
249 case UNW_X86_EDI:
250 return "edi";
251 default:
252 return "unknown register";
253 }
254}
255
256inline double Registers_x86::getFloatRegister(int) const {
257 _LIBUNWIND_ABORT("no x86 float registers");
258}
259
260inline void Registers_x86::setFloatRegister(int, double) {
261 _LIBUNWIND_ABORT("no x86 float registers");
262}
263
264inline v128 Registers_x86::getVectorRegister(int) const {
265 _LIBUNWIND_ABORT("no x86 vector registers");
266}
267
268inline void Registers_x86::setVectorRegister(int, v128) {
269 _LIBUNWIND_ABORT("no x86 vector registers");
270}
271#endif // _LIBUNWIND_TARGET_I386
272
273
274#if defined(_LIBUNWIND_TARGET_X86_64)
275/// Registers_x86_64 holds the register state of a thread in a 64-bit intel
276/// process.
277class _LIBUNWIND_HIDDEN Registers_x86_64;
278extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
279
280#if defined(_LIBUNWIND_USE_CET)
281extern "C" void *__libunwind_shstk_get_jump_target() {
282 return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto);
283}
284#endif
285
286class _LIBUNWIND_HIDDEN Registers_x86_64 {
287public:
288 Registers_x86_64();
289 Registers_x86_64(const void *registers);
290
291 typedef uint64_t reg_t;
292 typedef uint64_t link_reg_t;
293 typedef const link_reg_t &link_hardened_reg_arg_t;
294
295 bool validRegister(int num) const;
296 uint64_t getRegister(int num) const;
297 void setRegister(int num, uint64_t value);
298 bool validFloatRegister(int) const { return false; }
299 double getFloatRegister(int num) const;
300 void setFloatRegister(int num, double value);
301 bool validVectorRegister(int) const;
302 v128 getVectorRegister(int num) const;
303 void setVectorRegister(int num, v128 value);
304 static const char *getRegisterName(int num);
305 void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }
306 static constexpr int lastDwarfRegNum() {
307 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64;
308 }
309 static int getArch() { return REGISTERS_X86_64; }
310
311 uint64_t getSP() const { return _registers.__rsp; }
312 void setSP(uint64_t value) { _registers.__rsp = value; }
313 uint64_t getIP() const { return _registers.__rip; }
314 void setIP(uint64_t value) { _registers.__rip = value; }
315 uint64_t getRBP() const { return _registers.__rbp; }
316 void setRBP(uint64_t value) { _registers.__rbp = value; }
317 uint64_t getRBX() const { return _registers.__rbx; }
318 void setRBX(uint64_t value) { _registers.__rbx = value; }
319 uint64_t getR12() const { return _registers.__r12; }
320 void setR12(uint64_t value) { _registers.__r12 = value; }
321 uint64_t getR13() const { return _registers.__r13; }
322 void setR13(uint64_t value) { _registers.__r13 = value; }
323 uint64_t getR14() const { return _registers.__r14; }
324 void setR14(uint64_t value) { _registers.__r14 = value; }
325 uint64_t getR15() const { return _registers.__r15; }
326 void setR15(uint64_t value) { _registers.__r15 = value; }
327
328private:
329 struct GPRs {
330 uint64_t __rax;
331 uint64_t __rbx;
332 uint64_t __rcx;
333 uint64_t __rdx;
334 uint64_t __rdi;
335 uint64_t __rsi;
336 uint64_t __rbp;
337 uint64_t __rsp;
338 uint64_t __r8;
339 uint64_t __r9;
340 uint64_t __r10;
341 uint64_t __r11;
342 uint64_t __r12;
343 uint64_t __r13;
344 uint64_t __r14;
345 uint64_t __r15;
346 uint64_t __rip;
347 uint64_t __rflags;
348 uint64_t __cs;
349 uint64_t __fs;
350 uint64_t __gs;
351#if defined(_WIN64)
352 uint64_t __padding; // 16-byte align
353#endif
354 };
355 GPRs _registers;
356#if defined(_WIN64)
357 v128 _xmm[16];
358#endif
359};
360
361inline Registers_x86_64::Registers_x86_64(const void *registers) {
362 static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
363 "x86_64 registers do not fit into unw_context_t");
364 memcpy(dest: &_registers, src: registers, n: sizeof(_registers));
365}
366
367inline Registers_x86_64::Registers_x86_64() {
368 memset(s: &_registers, c: 0, n: sizeof(_registers));
369}
370
371inline bool Registers_x86_64::validRegister(int regNum) const {
372 if (regNum == UNW_REG_IP)
373 return true;
374 if (regNum == UNW_REG_SP)
375 return true;
376 if (regNum < 0)
377 return false;
378 if (regNum > 16)
379 return false;
380 return true;
381}
382
383inline uint64_t Registers_x86_64::getRegister(int regNum) const {
384 switch (regNum) {
385 case UNW_REG_IP:
386 case UNW_X86_64_RIP:
387 return _registers.__rip;
388 case UNW_REG_SP:
389 return _registers.__rsp;
390 case UNW_X86_64_RAX:
391 return _registers.__rax;
392 case UNW_X86_64_RDX:
393 return _registers.__rdx;
394 case UNW_X86_64_RCX:
395 return _registers.__rcx;
396 case UNW_X86_64_RBX:
397 return _registers.__rbx;
398 case UNW_X86_64_RSI:
399 return _registers.__rsi;
400 case UNW_X86_64_RDI:
401 return _registers.__rdi;
402 case UNW_X86_64_RBP:
403 return _registers.__rbp;
404 case UNW_X86_64_RSP:
405 return _registers.__rsp;
406 case UNW_X86_64_R8:
407 return _registers.__r8;
408 case UNW_X86_64_R9:
409 return _registers.__r9;
410 case UNW_X86_64_R10:
411 return _registers.__r10;
412 case UNW_X86_64_R11:
413 return _registers.__r11;
414 case UNW_X86_64_R12:
415 return _registers.__r12;
416 case UNW_X86_64_R13:
417 return _registers.__r13;
418 case UNW_X86_64_R14:
419 return _registers.__r14;
420 case UNW_X86_64_R15:
421 return _registers.__r15;
422 }
423 _LIBUNWIND_ABORT("unsupported x86_64 register");
424}
425
426inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
427 switch (regNum) {
428 case UNW_REG_IP:
429 case UNW_X86_64_RIP:
430 _registers.__rip = value;
431 return;
432 case UNW_REG_SP:
433 _registers.__rsp = value;
434 return;
435 case UNW_X86_64_RAX:
436 _registers.__rax = value;
437 return;
438 case UNW_X86_64_RDX:
439 _registers.__rdx = value;
440 return;
441 case UNW_X86_64_RCX:
442 _registers.__rcx = value;
443 return;
444 case UNW_X86_64_RBX:
445 _registers.__rbx = value;
446 return;
447 case UNW_X86_64_RSI:
448 _registers.__rsi = value;
449 return;
450 case UNW_X86_64_RDI:
451 _registers.__rdi = value;
452 return;
453 case UNW_X86_64_RBP:
454 _registers.__rbp = value;
455 return;
456 case UNW_X86_64_RSP:
457 _registers.__rsp = value;
458 return;
459 case UNW_X86_64_R8:
460 _registers.__r8 = value;
461 return;
462 case UNW_X86_64_R9:
463 _registers.__r9 = value;
464 return;
465 case UNW_X86_64_R10:
466 _registers.__r10 = value;
467 return;
468 case UNW_X86_64_R11:
469 _registers.__r11 = value;
470 return;
471 case UNW_X86_64_R12:
472 _registers.__r12 = value;
473 return;
474 case UNW_X86_64_R13:
475 _registers.__r13 = value;
476 return;
477 case UNW_X86_64_R14:
478 _registers.__r14 = value;
479 return;
480 case UNW_X86_64_R15:
481 _registers.__r15 = value;
482 return;
483 }
484 _LIBUNWIND_ABORT("unsupported x86_64 register");
485}
486
487inline const char *Registers_x86_64::getRegisterName(int regNum) {
488 switch (regNum) {
489 case UNW_REG_IP:
490 case UNW_X86_64_RIP:
491 return "rip";
492 case UNW_REG_SP:
493 return "rsp";
494 case UNW_X86_64_RAX:
495 return "rax";
496 case UNW_X86_64_RDX:
497 return "rdx";
498 case UNW_X86_64_RCX:
499 return "rcx";
500 case UNW_X86_64_RBX:
501 return "rbx";
502 case UNW_X86_64_RSI:
503 return "rsi";
504 case UNW_X86_64_RDI:
505 return "rdi";
506 case UNW_X86_64_RBP:
507 return "rbp";
508 case UNW_X86_64_RSP:
509 return "rsp";
510 case UNW_X86_64_R8:
511 return "r8";
512 case UNW_X86_64_R9:
513 return "r9";
514 case UNW_X86_64_R10:
515 return "r10";
516 case UNW_X86_64_R11:
517 return "r11";
518 case UNW_X86_64_R12:
519 return "r12";
520 case UNW_X86_64_R13:
521 return "r13";
522 case UNW_X86_64_R14:
523 return "r14";
524 case UNW_X86_64_R15:
525 return "r15";
526 case UNW_X86_64_XMM0:
527 return "xmm0";
528 case UNW_X86_64_XMM1:
529 return "xmm1";
530 case UNW_X86_64_XMM2:
531 return "xmm2";
532 case UNW_X86_64_XMM3:
533 return "xmm3";
534 case UNW_X86_64_XMM4:
535 return "xmm4";
536 case UNW_X86_64_XMM5:
537 return "xmm5";
538 case UNW_X86_64_XMM6:
539 return "xmm6";
540 case UNW_X86_64_XMM7:
541 return "xmm7";
542 case UNW_X86_64_XMM8:
543 return "xmm8";
544 case UNW_X86_64_XMM9:
545 return "xmm9";
546 case UNW_X86_64_XMM10:
547 return "xmm10";
548 case UNW_X86_64_XMM11:
549 return "xmm11";
550 case UNW_X86_64_XMM12:
551 return "xmm12";
552 case UNW_X86_64_XMM13:
553 return "xmm13";
554 case UNW_X86_64_XMM14:
555 return "xmm14";
556 case UNW_X86_64_XMM15:
557 return "xmm15";
558 default:
559 return "unknown register";
560 }
561}
562
563inline double Registers_x86_64::getFloatRegister(int) const {
564 _LIBUNWIND_ABORT("no x86_64 float registers");
565}
566
567inline void Registers_x86_64::setFloatRegister(int, double) {
568 _LIBUNWIND_ABORT("no x86_64 float registers");
569}
570
571inline bool Registers_x86_64::validVectorRegister(int regNum) const {
572#if defined(_WIN64)
573 if (regNum < UNW_X86_64_XMM0)
574 return false;
575 if (regNum > UNW_X86_64_XMM15)
576 return false;
577 return true;
578#else
579 (void)regNum; // suppress unused parameter warning
580 return false;
581#endif
582}
583
584inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
585#if defined(_WIN64)
586 assert(validVectorRegister(regNum));
587 return _xmm[regNum - UNW_X86_64_XMM0];
588#else
589 (void)regNum; // suppress unused parameter warning
590 _LIBUNWIND_ABORT("no x86_64 vector registers");
591#endif
592}
593
594inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
595#if defined(_WIN64)
596 assert(validVectorRegister(regNum));
597 _xmm[regNum - UNW_X86_64_XMM0] = value;
598#else
599 (void)regNum; (void)value; // suppress unused parameter warnings
600 _LIBUNWIND_ABORT("no x86_64 vector registers");
601#endif
602}
603#endif // _LIBUNWIND_TARGET_X86_64
604
605
606#if defined(_LIBUNWIND_TARGET_PPC)
607/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
608/// process.
609class _LIBUNWIND_HIDDEN Registers_ppc {
610public:
611 Registers_ppc();
612 Registers_ppc(const void *registers);
613
614 typedef uint32_t reg_t;
615 typedef uint32_t link_reg_t;
616 typedef const link_reg_t &link_hardened_reg_arg_t;
617
618 bool validRegister(int num) const;
619 uint32_t getRegister(int num) const;
620 void setRegister(int num, uint32_t value);
621 bool validFloatRegister(int num) const;
622 double getFloatRegister(int num) const;
623 void setFloatRegister(int num, double value);
624 bool validVectorRegister(int num) const;
625 v128 getVectorRegister(int num) const;
626 void setVectorRegister(int num, v128 value);
627 static const char *getRegisterName(int num);
628 void jumpto();
629 static constexpr int lastDwarfRegNum() {
630 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC;
631 }
632 static int getArch() { return REGISTERS_PPC; }
633
634 uint64_t getSP() const { return _registers.__r1; }
635 void setSP(uint32_t value) { _registers.__r1 = value; }
636 uint64_t getIP() const { return _registers.__srr0; }
637 void setIP(uint32_t value) { _registers.__srr0 = value; }
638 uint64_t getCR() const { return _registers.__cr; }
639 void setCR(uint32_t value) { _registers.__cr = value; }
640 uint64_t getLR() const { return _registers.__lr; }
641 void setLR(uint32_t value) { _registers.__lr = value; }
642
643private:
644 struct ppc_thread_state_t {
645 unsigned int __srr0; /* Instruction address register (PC) */
646 unsigned int __srr1; /* Machine state register (supervisor) */
647 unsigned int __r0;
648 unsigned int __r1;
649 unsigned int __r2;
650 unsigned int __r3;
651 unsigned int __r4;
652 unsigned int __r5;
653 unsigned int __r6;
654 unsigned int __r7;
655 unsigned int __r8;
656 unsigned int __r9;
657 unsigned int __r10;
658 unsigned int __r11;
659 unsigned int __r12;
660 unsigned int __r13;
661 unsigned int __r14;
662 unsigned int __r15;
663 unsigned int __r16;
664 unsigned int __r17;
665 unsigned int __r18;
666 unsigned int __r19;
667 unsigned int __r20;
668 unsigned int __r21;
669 unsigned int __r22;
670 unsigned int __r23;
671 unsigned int __r24;
672 unsigned int __r25;
673 unsigned int __r26;
674 unsigned int __r27;
675 unsigned int __r28;
676 unsigned int __r29;
677 unsigned int __r30;
678 unsigned int __r31;
679 unsigned int __cr; /* Condition register */
680 unsigned int __xer; /* User's integer exception register */
681 unsigned int __lr; /* Link register */
682 unsigned int __ctr; /* Count register */
683 unsigned int __mq; /* MQ register (601 only) */
684 unsigned int __vrsave; /* Vector Save Register */
685 };
686
687 struct ppc_float_state_t {
688 double __fpregs[32];
689
690 unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
691 unsigned int __fpscr; /* floating point status register */
692 };
693
694 ppc_thread_state_t _registers;
695 ppc_float_state_t _floatRegisters;
696 v128 _vectorRegisters[32]; // offset 424
697};
698
699inline Registers_ppc::Registers_ppc(const void *registers) {
700 static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
701 "ppc registers do not fit into unw_context_t");
702 memcpy(&_registers, static_cast<const uint8_t *>(registers),
703 sizeof(_registers));
704 static_assert(sizeof(ppc_thread_state_t) == 160,
705 "expected float register offset to be 160");
706 memcpy(&_floatRegisters,
707 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
708 sizeof(_floatRegisters));
709 static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
710 "expected vector register offset to be 424 bytes");
711 memcpy(_vectorRegisters,
712 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
713 sizeof(ppc_float_state_t),
714 sizeof(_vectorRegisters));
715}
716
717inline Registers_ppc::Registers_ppc() {
718 memset(&_registers, 0, sizeof(_registers));
719 memset(&_floatRegisters, 0, sizeof(_floatRegisters));
720 memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
721}
722
723inline bool Registers_ppc::validRegister(int regNum) const {
724 if (regNum == UNW_REG_IP)
725 return true;
726 if (regNum == UNW_REG_SP)
727 return true;
728 if (regNum == UNW_PPC_VRSAVE)
729 return true;
730 if (regNum < 0)
731 return false;
732 if (regNum <= UNW_PPC_R31)
733 return true;
734 if (regNum == UNW_PPC_MQ)
735 return true;
736 if (regNum == UNW_PPC_LR)
737 return true;
738 if (regNum == UNW_PPC_CTR)
739 return true;
740 if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
741 return true;
742 return false;
743}
744
745inline uint32_t Registers_ppc::getRegister(int regNum) const {
746 switch (regNum) {
747 case UNW_REG_IP:
748 return _registers.__srr0;
749 case UNW_REG_SP:
750 return _registers.__r1;
751 case UNW_PPC_R0:
752 return _registers.__r0;
753 case UNW_PPC_R1:
754 return _registers.__r1;
755 case UNW_PPC_R2:
756 return _registers.__r2;
757 case UNW_PPC_R3:
758 return _registers.__r3;
759 case UNW_PPC_R4:
760 return _registers.__r4;
761 case UNW_PPC_R5:
762 return _registers.__r5;
763 case UNW_PPC_R6:
764 return _registers.__r6;
765 case UNW_PPC_R7:
766 return _registers.__r7;
767 case UNW_PPC_R8:
768 return _registers.__r8;
769 case UNW_PPC_R9:
770 return _registers.__r9;
771 case UNW_PPC_R10:
772 return _registers.__r10;
773 case UNW_PPC_R11:
774 return _registers.__r11;
775 case UNW_PPC_R12:
776 return _registers.__r12;
777 case UNW_PPC_R13:
778 return _registers.__r13;
779 case UNW_PPC_R14:
780 return _registers.__r14;
781 case UNW_PPC_R15:
782 return _registers.__r15;
783 case UNW_PPC_R16:
784 return _registers.__r16;
785 case UNW_PPC_R17:
786 return _registers.__r17;
787 case UNW_PPC_R18:
788 return _registers.__r18;
789 case UNW_PPC_R19:
790 return _registers.__r19;
791 case UNW_PPC_R20:
792 return _registers.__r20;
793 case UNW_PPC_R21:
794 return _registers.__r21;
795 case UNW_PPC_R22:
796 return _registers.__r22;
797 case UNW_PPC_R23:
798 return _registers.__r23;
799 case UNW_PPC_R24:
800 return _registers.__r24;
801 case UNW_PPC_R25:
802 return _registers.__r25;
803 case UNW_PPC_R26:
804 return _registers.__r26;
805 case UNW_PPC_R27:
806 return _registers.__r27;
807 case UNW_PPC_R28:
808 return _registers.__r28;
809 case UNW_PPC_R29:
810 return _registers.__r29;
811 case UNW_PPC_R30:
812 return _registers.__r30;
813 case UNW_PPC_R31:
814 return _registers.__r31;
815 case UNW_PPC_LR:
816 return _registers.__lr;
817 case UNW_PPC_CR0:
818 return (_registers.__cr & 0xF0000000);
819 case UNW_PPC_CR1:
820 return (_registers.__cr & 0x0F000000);
821 case UNW_PPC_CR2:
822 return (_registers.__cr & 0x00F00000);
823 case UNW_PPC_CR3:
824 return (_registers.__cr & 0x000F0000);
825 case UNW_PPC_CR4:
826 return (_registers.__cr & 0x0000F000);
827 case UNW_PPC_CR5:
828 return (_registers.__cr & 0x00000F00);
829 case UNW_PPC_CR6:
830 return (_registers.__cr & 0x000000F0);
831 case UNW_PPC_CR7:
832 return (_registers.__cr & 0x0000000F);
833 case UNW_PPC_VRSAVE:
834 return _registers.__vrsave;
835 }
836 _LIBUNWIND_ABORT("unsupported ppc register");
837}
838
839inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
840 //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
841 switch (regNum) {
842 case UNW_REG_IP:
843 _registers.__srr0 = value;
844 return;
845 case UNW_REG_SP:
846 _registers.__r1 = value;
847 return;
848 case UNW_PPC_R0:
849 _registers.__r0 = value;
850 return;
851 case UNW_PPC_R1:
852 _registers.__r1 = value;
853 return;
854 case UNW_PPC_R2:
855 _registers.__r2 = value;
856 return;
857 case UNW_PPC_R3:
858 _registers.__r3 = value;
859 return;
860 case UNW_PPC_R4:
861 _registers.__r4 = value;
862 return;
863 case UNW_PPC_R5:
864 _registers.__r5 = value;
865 return;
866 case UNW_PPC_R6:
867 _registers.__r6 = value;
868 return;
869 case UNW_PPC_R7:
870 _registers.__r7 = value;
871 return;
872 case UNW_PPC_R8:
873 _registers.__r8 = value;
874 return;
875 case UNW_PPC_R9:
876 _registers.__r9 = value;
877 return;
878 case UNW_PPC_R10:
879 _registers.__r10 = value;
880 return;
881 case UNW_PPC_R11:
882 _registers.__r11 = value;
883 return;
884 case UNW_PPC_R12:
885 _registers.__r12 = value;
886 return;
887 case UNW_PPC_R13:
888 _registers.__r13 = value;
889 return;
890 case UNW_PPC_R14:
891 _registers.__r14 = value;
892 return;
893 case UNW_PPC_R15:
894 _registers.__r15 = value;
895 return;
896 case UNW_PPC_R16:
897 _registers.__r16 = value;
898 return;
899 case UNW_PPC_R17:
900 _registers.__r17 = value;
901 return;
902 case UNW_PPC_R18:
903 _registers.__r18 = value;
904 return;
905 case UNW_PPC_R19:
906 _registers.__r19 = value;
907 return;
908 case UNW_PPC_R20:
909 _registers.__r20 = value;
910 return;
911 case UNW_PPC_R21:
912 _registers.__r21 = value;
913 return;
914 case UNW_PPC_R22:
915 _registers.__r22 = value;
916 return;
917 case UNW_PPC_R23:
918 _registers.__r23 = value;
919 return;
920 case UNW_PPC_R24:
921 _registers.__r24 = value;
922 return;
923 case UNW_PPC_R25:
924 _registers.__r25 = value;
925 return;
926 case UNW_PPC_R26:
927 _registers.__r26 = value;
928 return;
929 case UNW_PPC_R27:
930 _registers.__r27 = value;
931 return;
932 case UNW_PPC_R28:
933 _registers.__r28 = value;
934 return;
935 case UNW_PPC_R29:
936 _registers.__r29 = value;
937 return;
938 case UNW_PPC_R30:
939 _registers.__r30 = value;
940 return;
941 case UNW_PPC_R31:
942 _registers.__r31 = value;
943 return;
944 case UNW_PPC_MQ:
945 _registers.__mq = value;
946 return;
947 case UNW_PPC_LR:
948 _registers.__lr = value;
949 return;
950 case UNW_PPC_CTR:
951 _registers.__ctr = value;
952 return;
953 case UNW_PPC_CR0:
954 _registers.__cr &= 0x0FFFFFFF;
955 _registers.__cr |= (value & 0xF0000000);
956 return;
957 case UNW_PPC_CR1:
958 _registers.__cr &= 0xF0FFFFFF;
959 _registers.__cr |= (value & 0x0F000000);
960 return;
961 case UNW_PPC_CR2:
962 _registers.__cr &= 0xFF0FFFFF;
963 _registers.__cr |= (value & 0x00F00000);
964 return;
965 case UNW_PPC_CR3:
966 _registers.__cr &= 0xFFF0FFFF;
967 _registers.__cr |= (value & 0x000F0000);
968 return;
969 case UNW_PPC_CR4:
970 _registers.__cr &= 0xFFFF0FFF;
971 _registers.__cr |= (value & 0x0000F000);
972 return;
973 case UNW_PPC_CR5:
974 _registers.__cr &= 0xFFFFF0FF;
975 _registers.__cr |= (value & 0x00000F00);
976 return;
977 case UNW_PPC_CR6:
978 _registers.__cr &= 0xFFFFFF0F;
979 _registers.__cr |= (value & 0x000000F0);
980 return;
981 case UNW_PPC_CR7:
982 _registers.__cr &= 0xFFFFFFF0;
983 _registers.__cr |= (value & 0x0000000F);
984 return;
985 case UNW_PPC_VRSAVE:
986 _registers.__vrsave = value;
987 return;
988 // not saved
989 return;
990 case UNW_PPC_XER:
991 _registers.__xer = value;
992 return;
993 case UNW_PPC_AP:
994 case UNW_PPC_VSCR:
995 case UNW_PPC_SPEFSCR:
996 // not saved
997 return;
998 }
999 _LIBUNWIND_ABORT("unsupported ppc register");
1000}
1001
1002inline bool Registers_ppc::validFloatRegister(int regNum) const {
1003 if (regNum < UNW_PPC_F0)
1004 return false;
1005 if (regNum > UNW_PPC_F31)
1006 return false;
1007 return true;
1008}
1009
1010inline double Registers_ppc::getFloatRegister(int regNum) const {
1011 assert(validFloatRegister(regNum));
1012 return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
1013}
1014
1015inline void Registers_ppc::setFloatRegister(int regNum, double value) {
1016 assert(validFloatRegister(regNum));
1017 _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
1018}
1019
1020inline bool Registers_ppc::validVectorRegister(int regNum) const {
1021 if (regNum < UNW_PPC_V0)
1022 return false;
1023 if (regNum > UNW_PPC_V31)
1024 return false;
1025 return true;
1026}
1027
1028inline v128 Registers_ppc::getVectorRegister(int regNum) const {
1029 assert(validVectorRegister(regNum));
1030 v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
1031 return result;
1032}
1033
1034inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
1035 assert(validVectorRegister(regNum));
1036 _vectorRegisters[regNum - UNW_PPC_V0] = value;
1037}
1038
1039inline const char *Registers_ppc::getRegisterName(int regNum) {
1040 switch (regNum) {
1041 case UNW_REG_IP:
1042 return "ip";
1043 case UNW_REG_SP:
1044 return "sp";
1045 case UNW_PPC_R0:
1046 return "r0";
1047 case UNW_PPC_R1:
1048 return "r1";
1049 case UNW_PPC_R2:
1050 return "r2";
1051 case UNW_PPC_R3:
1052 return "r3";
1053 case UNW_PPC_R4:
1054 return "r4";
1055 case UNW_PPC_R5:
1056 return "r5";
1057 case UNW_PPC_R6:
1058 return "r6";
1059 case UNW_PPC_R7:
1060 return "r7";
1061 case UNW_PPC_R8:
1062 return "r8";
1063 case UNW_PPC_R9:
1064 return "r9";
1065 case UNW_PPC_R10:
1066 return "r10";
1067 case UNW_PPC_R11:
1068 return "r11";
1069 case UNW_PPC_R12:
1070 return "r12";
1071 case UNW_PPC_R13:
1072 return "r13";
1073 case UNW_PPC_R14:
1074 return "r14";
1075 case UNW_PPC_R15:
1076 return "r15";
1077 case UNW_PPC_R16:
1078 return "r16";
1079 case UNW_PPC_R17:
1080 return "r17";
1081 case UNW_PPC_R18:
1082 return "r18";
1083 case UNW_PPC_R19:
1084 return "r19";
1085 case UNW_PPC_R20:
1086 return "r20";
1087 case UNW_PPC_R21:
1088 return "r21";
1089 case UNW_PPC_R22:
1090 return "r22";
1091 case UNW_PPC_R23:
1092 return "r23";
1093 case UNW_PPC_R24:
1094 return "r24";
1095 case UNW_PPC_R25:
1096 return "r25";
1097 case UNW_PPC_R26:
1098 return "r26";
1099 case UNW_PPC_R27:
1100 return "r27";
1101 case UNW_PPC_R28:
1102 return "r28";
1103 case UNW_PPC_R29:
1104 return "r29";
1105 case UNW_PPC_R30:
1106 return "r30";
1107 case UNW_PPC_R31:
1108 return "r31";
1109 case UNW_PPC_F0:
1110 return "fp0";
1111 case UNW_PPC_F1:
1112 return "fp1";
1113 case UNW_PPC_F2:
1114 return "fp2";
1115 case UNW_PPC_F3:
1116 return "fp3";
1117 case UNW_PPC_F4:
1118 return "fp4";
1119 case UNW_PPC_F5:
1120 return "fp5";
1121 case UNW_PPC_F6:
1122 return "fp6";
1123 case UNW_PPC_F7:
1124 return "fp7";
1125 case UNW_PPC_F8:
1126 return "fp8";
1127 case UNW_PPC_F9:
1128 return "fp9";
1129 case UNW_PPC_F10:
1130 return "fp10";
1131 case UNW_PPC_F11:
1132 return "fp11";
1133 case UNW_PPC_F12:
1134 return "fp12";
1135 case UNW_PPC_F13:
1136 return "fp13";
1137 case UNW_PPC_F14:
1138 return "fp14";
1139 case UNW_PPC_F15:
1140 return "fp15";
1141 case UNW_PPC_F16:
1142 return "fp16";
1143 case UNW_PPC_F17:
1144 return "fp17";
1145 case UNW_PPC_F18:
1146 return "fp18";
1147 case UNW_PPC_F19:
1148 return "fp19";
1149 case UNW_PPC_F20:
1150 return "fp20";
1151 case UNW_PPC_F21:
1152 return "fp21";
1153 case UNW_PPC_F22:
1154 return "fp22";
1155 case UNW_PPC_F23:
1156 return "fp23";
1157 case UNW_PPC_F24:
1158 return "fp24";
1159 case UNW_PPC_F25:
1160 return "fp25";
1161 case UNW_PPC_F26:
1162 return "fp26";
1163 case UNW_PPC_F27:
1164 return "fp27";
1165 case UNW_PPC_F28:
1166 return "fp28";
1167 case UNW_PPC_F29:
1168 return "fp29";
1169 case UNW_PPC_F30:
1170 return "fp30";
1171 case UNW_PPC_F31:
1172 return "fp31";
1173 case UNW_PPC_LR:
1174 return "lr";
1175 default:
1176 return "unknown register";
1177 }
1178
1179}
1180#endif // _LIBUNWIND_TARGET_PPC
1181
1182#if defined(_LIBUNWIND_TARGET_PPC64)
1183/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
1184/// process.
1185class _LIBUNWIND_HIDDEN Registers_ppc64 {
1186public:
1187 Registers_ppc64();
1188 Registers_ppc64(const void *registers);
1189
1190 typedef uint64_t reg_t;
1191 typedef uint64_t link_reg_t;
1192 typedef const link_reg_t &link_hardened_reg_arg_t;
1193
1194 bool validRegister(int num) const;
1195 uint64_t getRegister(int num) const;
1196 void setRegister(int num, uint64_t value);
1197 bool validFloatRegister(int num) const;
1198 double getFloatRegister(int num) const;
1199 void setFloatRegister(int num, double value);
1200 bool validVectorRegister(int num) const;
1201 v128 getVectorRegister(int num) const;
1202 void setVectorRegister(int num, v128 value);
1203 static const char *getRegisterName(int num);
1204 void jumpto();
1205 static constexpr int lastDwarfRegNum() {
1206 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64;
1207 }
1208 static int getArch() { return REGISTERS_PPC64; }
1209
1210 uint64_t getSP() const { return _registers.__r1; }
1211 void setSP(uint64_t value) { _registers.__r1 = value; }
1212 uint64_t getIP() const { return _registers.__srr0; }
1213 void setIP(uint64_t value) { _registers.__srr0 = value; }
1214 uint64_t getCR() const { return _registers.__cr; }
1215 void setCR(uint64_t value) { _registers.__cr = value; }
1216 uint64_t getLR() const { return _registers.__lr; }
1217 void setLR(uint64_t value) { _registers.__lr = value; }
1218
1219private:
1220 struct ppc64_thread_state_t {
1221 uint64_t __srr0; // Instruction address register (PC)
1222 uint64_t __srr1; // Machine state register (supervisor)
1223 uint64_t __r0;
1224 uint64_t __r1;
1225 uint64_t __r2;
1226 uint64_t __r3;
1227 uint64_t __r4;
1228 uint64_t __r5;
1229 uint64_t __r6;
1230 uint64_t __r7;
1231 uint64_t __r8;
1232 uint64_t __r9;
1233 uint64_t __r10;
1234 uint64_t __r11;
1235 uint64_t __r12;
1236 uint64_t __r13;
1237 uint64_t __r14;
1238 uint64_t __r15;
1239 uint64_t __r16;
1240 uint64_t __r17;
1241 uint64_t __r18;
1242 uint64_t __r19;
1243 uint64_t __r20;
1244 uint64_t __r21;
1245 uint64_t __r22;
1246 uint64_t __r23;
1247 uint64_t __r24;
1248 uint64_t __r25;
1249 uint64_t __r26;
1250 uint64_t __r27;
1251 uint64_t __r28;
1252 uint64_t __r29;
1253 uint64_t __r30;
1254 uint64_t __r31;
1255 uint64_t __cr; // Condition register
1256 uint64_t __xer; // User's integer exception register
1257 uint64_t __lr; // Link register
1258 uint64_t __ctr; // Count register
1259 uint64_t __vrsave; // Vector Save Register
1260 };
1261
1262 union ppc64_vsr_t {
1263 struct asfloat_s {
1264 double f;
1265 uint64_t v2;
1266 } asfloat;
1267 v128 v;
1268 };
1269
1270 ppc64_thread_state_t _registers;
1271 ppc64_vsr_t _vectorScalarRegisters[64];
1272
1273 static int getVectorRegNum(int num);
1274};
1275
1276inline Registers_ppc64::Registers_ppc64(const void *registers) {
1277 static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),
1278 "ppc64 registers do not fit into unw_context_t");
1279 memcpy(&_registers, static_cast<const uint8_t *>(registers),
1280 sizeof(_registers));
1281 static_assert(sizeof(_registers) == 312,
1282 "expected vector scalar register offset to be 312");
1283 memcpy(&_vectorScalarRegisters,
1284 static_cast<const uint8_t *>(registers) + sizeof(_registers),
1285 sizeof(_vectorScalarRegisters));
1286 static_assert(sizeof(_registers) +
1287 sizeof(_vectorScalarRegisters) == 1336,
1288 "expected vector register offset to be 1336 bytes");
1289}
1290
1291inline Registers_ppc64::Registers_ppc64() {
1292 memset(&_registers, 0, sizeof(_registers));
1293 memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
1294}
1295
1296inline bool Registers_ppc64::validRegister(int regNum) const {
1297 switch (regNum) {
1298 case UNW_REG_IP:
1299 case UNW_REG_SP:
1300 case UNW_PPC64_XER:
1301 case UNW_PPC64_LR:
1302 case UNW_PPC64_CTR:
1303 case UNW_PPC64_VRSAVE:
1304 return true;
1305 }
1306
1307 if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
1308 return true;
1309 if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
1310 return true;
1311
1312 return false;
1313}
1314
1315inline uint64_t Registers_ppc64::getRegister(int regNum) const {
1316 switch (regNum) {
1317 case UNW_REG_IP:
1318 return _registers.__srr0;
1319 case UNW_PPC64_R0:
1320 return _registers.__r0;
1321 case UNW_PPC64_R1:
1322 case UNW_REG_SP:
1323 return _registers.__r1;
1324 case UNW_PPC64_R2:
1325 return _registers.__r2;
1326 case UNW_PPC64_R3:
1327 return _registers.__r3;
1328 case UNW_PPC64_R4:
1329 return _registers.__r4;
1330 case UNW_PPC64_R5:
1331 return _registers.__r5;
1332 case UNW_PPC64_R6:
1333 return _registers.__r6;
1334 case UNW_PPC64_R7:
1335 return _registers.__r7;
1336 case UNW_PPC64_R8:
1337 return _registers.__r8;
1338 case UNW_PPC64_R9:
1339 return _registers.__r9;
1340 case UNW_PPC64_R10:
1341 return _registers.__r10;
1342 case UNW_PPC64_R11:
1343 return _registers.__r11;
1344 case UNW_PPC64_R12:
1345 return _registers.__r12;
1346 case UNW_PPC64_R13:
1347 return _registers.__r13;
1348 case UNW_PPC64_R14:
1349 return _registers.__r14;
1350 case UNW_PPC64_R15:
1351 return _registers.__r15;
1352 case UNW_PPC64_R16:
1353 return _registers.__r16;
1354 case UNW_PPC64_R17:
1355 return _registers.__r17;
1356 case UNW_PPC64_R18:
1357 return _registers.__r18;
1358 case UNW_PPC64_R19:
1359 return _registers.__r19;
1360 case UNW_PPC64_R20:
1361 return _registers.__r20;
1362 case UNW_PPC64_R21:
1363 return _registers.__r21;
1364 case UNW_PPC64_R22:
1365 return _registers.__r22;
1366 case UNW_PPC64_R23:
1367 return _registers.__r23;
1368 case UNW_PPC64_R24:
1369 return _registers.__r24;
1370 case UNW_PPC64_R25:
1371 return _registers.__r25;
1372 case UNW_PPC64_R26:
1373 return _registers.__r26;
1374 case UNW_PPC64_R27:
1375 return _registers.__r27;
1376 case UNW_PPC64_R28:
1377 return _registers.__r28;
1378 case UNW_PPC64_R29:
1379 return _registers.__r29;
1380 case UNW_PPC64_R30:
1381 return _registers.__r30;
1382 case UNW_PPC64_R31:
1383 return _registers.__r31;
1384 case UNW_PPC64_CR0:
1385 return (_registers.__cr & 0xF0000000);
1386 case UNW_PPC64_CR1:
1387 return (_registers.__cr & 0x0F000000);
1388 case UNW_PPC64_CR2:
1389 return (_registers.__cr & 0x00F00000);
1390 case UNW_PPC64_CR3:
1391 return (_registers.__cr & 0x000F0000);
1392 case UNW_PPC64_CR4:
1393 return (_registers.__cr & 0x0000F000);
1394 case UNW_PPC64_CR5:
1395 return (_registers.__cr & 0x00000F00);
1396 case UNW_PPC64_CR6:
1397 return (_registers.__cr & 0x000000F0);
1398 case UNW_PPC64_CR7:
1399 return (_registers.__cr & 0x0000000F);
1400 case UNW_PPC64_XER:
1401 return _registers.__xer;
1402 case UNW_PPC64_LR:
1403 return _registers.__lr;
1404 case UNW_PPC64_CTR:
1405 return _registers.__ctr;
1406 case UNW_PPC64_VRSAVE:
1407 return _registers.__vrsave;
1408 }
1409 _LIBUNWIND_ABORT("unsupported ppc64 register");
1410}
1411
1412inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
1413 switch (regNum) {
1414 case UNW_REG_IP:
1415 _registers.__srr0 = value;
1416 return;
1417 case UNW_PPC64_R0:
1418 _registers.__r0 = value;
1419 return;
1420 case UNW_PPC64_R1:
1421 case UNW_REG_SP:
1422 _registers.__r1 = value;
1423 return;
1424 case UNW_PPC64_R2:
1425 _registers.__r2 = value;
1426 return;
1427 case UNW_PPC64_R3:
1428 _registers.__r3 = value;
1429 return;
1430 case UNW_PPC64_R4:
1431 _registers.__r4 = value;
1432 return;
1433 case UNW_PPC64_R5:
1434 _registers.__r5 = value;
1435 return;
1436 case UNW_PPC64_R6:
1437 _registers.__r6 = value;
1438 return;
1439 case UNW_PPC64_R7:
1440 _registers.__r7 = value;
1441 return;
1442 case UNW_PPC64_R8:
1443 _registers.__r8 = value;
1444 return;
1445 case UNW_PPC64_R9:
1446 _registers.__r9 = value;
1447 return;
1448 case UNW_PPC64_R10:
1449 _registers.__r10 = value;
1450 return;
1451 case UNW_PPC64_R11:
1452 _registers.__r11 = value;
1453 return;
1454 case UNW_PPC64_R12:
1455 _registers.__r12 = value;
1456 return;
1457 case UNW_PPC64_R13:
1458 _registers.__r13 = value;
1459 return;
1460 case UNW_PPC64_R14:
1461 _registers.__r14 = value;
1462 return;
1463 case UNW_PPC64_R15:
1464 _registers.__r15 = value;
1465 return;
1466 case UNW_PPC64_R16:
1467 _registers.__r16 = value;
1468 return;
1469 case UNW_PPC64_R17:
1470 _registers.__r17 = value;
1471 return;
1472 case UNW_PPC64_R18:
1473 _registers.__r18 = value;
1474 return;
1475 case UNW_PPC64_R19:
1476 _registers.__r19 = value;
1477 return;
1478 case UNW_PPC64_R20:
1479 _registers.__r20 = value;
1480 return;
1481 case UNW_PPC64_R21:
1482 _registers.__r21 = value;
1483 return;
1484 case UNW_PPC64_R22:
1485 _registers.__r22 = value;
1486 return;
1487 case UNW_PPC64_R23:
1488 _registers.__r23 = value;
1489 return;
1490 case UNW_PPC64_R24:
1491 _registers.__r24 = value;
1492 return;
1493 case UNW_PPC64_R25:
1494 _registers.__r25 = value;
1495 return;
1496 case UNW_PPC64_R26:
1497 _registers.__r26 = value;
1498 return;
1499 case UNW_PPC64_R27:
1500 _registers.__r27 = value;
1501 return;
1502 case UNW_PPC64_R28:
1503 _registers.__r28 = value;
1504 return;
1505 case UNW_PPC64_R29:
1506 _registers.__r29 = value;
1507 return;
1508 case UNW_PPC64_R30:
1509 _registers.__r30 = value;
1510 return;
1511 case UNW_PPC64_R31:
1512 _registers.__r31 = value;
1513 return;
1514 case UNW_PPC64_CR0:
1515 _registers.__cr &= 0x0FFFFFFF;
1516 _registers.__cr |= (value & 0xF0000000);
1517 return;
1518 case UNW_PPC64_CR1:
1519 _registers.__cr &= 0xF0FFFFFF;
1520 _registers.__cr |= (value & 0x0F000000);
1521 return;
1522 case UNW_PPC64_CR2:
1523 _registers.__cr &= 0xFF0FFFFF;
1524 _registers.__cr |= (value & 0x00F00000);
1525 return;
1526 case UNW_PPC64_CR3:
1527 _registers.__cr &= 0xFFF0FFFF;
1528 _registers.__cr |= (value & 0x000F0000);
1529 return;
1530 case UNW_PPC64_CR4:
1531 _registers.__cr &= 0xFFFF0FFF;
1532 _registers.__cr |= (value & 0x0000F000);
1533 return;
1534 case UNW_PPC64_CR5:
1535 _registers.__cr &= 0xFFFFF0FF;
1536 _registers.__cr |= (value & 0x00000F00);
1537 return;
1538 case UNW_PPC64_CR6:
1539 _registers.__cr &= 0xFFFFFF0F;
1540 _registers.__cr |= (value & 0x000000F0);
1541 return;
1542 case UNW_PPC64_CR7:
1543 _registers.__cr &= 0xFFFFFFF0;
1544 _registers.__cr |= (value & 0x0000000F);
1545 return;
1546 case UNW_PPC64_XER:
1547 _registers.__xer = value;
1548 return;
1549 case UNW_PPC64_LR:
1550 _registers.__lr = value;
1551 return;
1552 case UNW_PPC64_CTR:
1553 _registers.__ctr = value;
1554 return;
1555 case UNW_PPC64_VRSAVE:
1556 _registers.__vrsave = value;
1557 return;
1558 }
1559 _LIBUNWIND_ABORT("unsupported ppc64 register");
1560}
1561
1562inline bool Registers_ppc64::validFloatRegister(int regNum) const {
1563 return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
1564}
1565
1566inline double Registers_ppc64::getFloatRegister(int regNum) const {
1567 assert(validFloatRegister(regNum));
1568 return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
1569}
1570
1571inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
1572 assert(validFloatRegister(regNum));
1573 _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
1574}
1575
1576inline bool Registers_ppc64::validVectorRegister(int regNum) const {
1577#if defined(__VSX__)
1578 if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
1579 return true;
1580 if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
1581 return true;
1582#elif defined(__ALTIVEC__)
1583 if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
1584 return true;
1585#endif
1586 return false;
1587}
1588
1589inline int Registers_ppc64::getVectorRegNum(int num)
1590{
1591 if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
1592 return num - UNW_PPC64_VS0;
1593 else
1594 return num - UNW_PPC64_VS32 + 32;
1595}
1596
1597inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
1598 assert(validVectorRegister(regNum));
1599 return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
1600}
1601
1602inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
1603 assert(validVectorRegister(regNum));
1604 _vectorScalarRegisters[getVectorRegNum(regNum)].v = value;
1605}
1606
1607inline const char *Registers_ppc64::getRegisterName(int regNum) {
1608 switch (regNum) {
1609 case UNW_REG_IP:
1610 return "ip";
1611 case UNW_REG_SP:
1612 return "sp";
1613 case UNW_PPC64_R0:
1614 return "r0";
1615 case UNW_PPC64_R1:
1616 return "r1";
1617 case UNW_PPC64_R2:
1618 return "r2";
1619 case UNW_PPC64_R3:
1620 return "r3";
1621 case UNW_PPC64_R4:
1622 return "r4";
1623 case UNW_PPC64_R5:
1624 return "r5";
1625 case UNW_PPC64_R6:
1626 return "r6";
1627 case UNW_PPC64_R7:
1628 return "r7";
1629 case UNW_PPC64_R8:
1630 return "r8";
1631 case UNW_PPC64_R9:
1632 return "r9";
1633 case UNW_PPC64_R10:
1634 return "r10";
1635 case UNW_PPC64_R11:
1636 return "r11";
1637 case UNW_PPC64_R12:
1638 return "r12";
1639 case UNW_PPC64_R13:
1640 return "r13";
1641 case UNW_PPC64_R14:
1642 return "r14";
1643 case UNW_PPC64_R15:
1644 return "r15";
1645 case UNW_PPC64_R16:
1646 return "r16";
1647 case UNW_PPC64_R17:
1648 return "r17";
1649 case UNW_PPC64_R18:
1650 return "r18";
1651 case UNW_PPC64_R19:
1652 return "r19";
1653 case UNW_PPC64_R20:
1654 return "r20";
1655 case UNW_PPC64_R21:
1656 return "r21";
1657 case UNW_PPC64_R22:
1658 return "r22";
1659 case UNW_PPC64_R23:
1660 return "r23";
1661 case UNW_PPC64_R24:
1662 return "r24";
1663 case UNW_PPC64_R25:
1664 return "r25";
1665 case UNW_PPC64_R26:
1666 return "r26";
1667 case UNW_PPC64_R27:
1668 return "r27";
1669 case UNW_PPC64_R28:
1670 return "r28";
1671 case UNW_PPC64_R29:
1672 return "r29";
1673 case UNW_PPC64_R30:
1674 return "r30";
1675 case UNW_PPC64_R31:
1676 return "r31";
1677 case UNW_PPC64_CR0:
1678 return "cr0";
1679 case UNW_PPC64_CR1:
1680 return "cr1";
1681 case UNW_PPC64_CR2:
1682 return "cr2";
1683 case UNW_PPC64_CR3:
1684 return "cr3";
1685 case UNW_PPC64_CR4:
1686 return "cr4";
1687 case UNW_PPC64_CR5:
1688 return "cr5";
1689 case UNW_PPC64_CR6:
1690 return "cr6";
1691 case UNW_PPC64_CR7:
1692 return "cr7";
1693 case UNW_PPC64_XER:
1694 return "xer";
1695 case UNW_PPC64_LR:
1696 return "lr";
1697 case UNW_PPC64_CTR:
1698 return "ctr";
1699 case UNW_PPC64_VRSAVE:
1700 return "vrsave";
1701 case UNW_PPC64_F0:
1702 return "fp0";
1703 case UNW_PPC64_F1:
1704 return "fp1";
1705 case UNW_PPC64_F2:
1706 return "fp2";
1707 case UNW_PPC64_F3:
1708 return "fp3";
1709 case UNW_PPC64_F4:
1710 return "fp4";
1711 case UNW_PPC64_F5:
1712 return "fp5";
1713 case UNW_PPC64_F6:
1714 return "fp6";
1715 case UNW_PPC64_F7:
1716 return "fp7";
1717 case UNW_PPC64_F8:
1718 return "fp8";
1719 case UNW_PPC64_F9:
1720 return "fp9";
1721 case UNW_PPC64_F10:
1722 return "fp10";
1723 case UNW_PPC64_F11:
1724 return "fp11";
1725 case UNW_PPC64_F12:
1726 return "fp12";
1727 case UNW_PPC64_F13:
1728 return "fp13";
1729 case UNW_PPC64_F14:
1730 return "fp14";
1731 case UNW_PPC64_F15:
1732 return "fp15";
1733 case UNW_PPC64_F16:
1734 return "fp16";
1735 case UNW_PPC64_F17:
1736 return "fp17";
1737 case UNW_PPC64_F18:
1738 return "fp18";
1739 case UNW_PPC64_F19:
1740 return "fp19";
1741 case UNW_PPC64_F20:
1742 return "fp20";
1743 case UNW_PPC64_F21:
1744 return "fp21";
1745 case UNW_PPC64_F22:
1746 return "fp22";
1747 case UNW_PPC64_F23:
1748 return "fp23";
1749 case UNW_PPC64_F24:
1750 return "fp24";
1751 case UNW_PPC64_F25:
1752 return "fp25";
1753 case UNW_PPC64_F26:
1754 return "fp26";
1755 case UNW_PPC64_F27:
1756 return "fp27";
1757 case UNW_PPC64_F28:
1758 return "fp28";
1759 case UNW_PPC64_F29:
1760 return "fp29";
1761 case UNW_PPC64_F30:
1762 return "fp30";
1763 case UNW_PPC64_F31:
1764 return "fp31";
1765 case UNW_PPC64_V0:
1766 return "v0";
1767 case UNW_PPC64_V1:
1768 return "v1";
1769 case UNW_PPC64_V2:
1770 return "v2";
1771 case UNW_PPC64_V3:
1772 return "v3";
1773 case UNW_PPC64_V4:
1774 return "v4";
1775 case UNW_PPC64_V5:
1776 return "v5";
1777 case UNW_PPC64_V6:
1778 return "v6";
1779 case UNW_PPC64_V7:
1780 return "v7";
1781 case UNW_PPC64_V8:
1782 return "v8";
1783 case UNW_PPC64_V9:
1784 return "v9";
1785 case UNW_PPC64_V10:
1786 return "v10";
1787 case UNW_PPC64_V11:
1788 return "v11";
1789 case UNW_PPC64_V12:
1790 return "v12";
1791 case UNW_PPC64_V13:
1792 return "v13";
1793 case UNW_PPC64_V14:
1794 return "v14";
1795 case UNW_PPC64_V15:
1796 return "v15";
1797 case UNW_PPC64_V16:
1798 return "v16";
1799 case UNW_PPC64_V17:
1800 return "v17";
1801 case UNW_PPC64_V18:
1802 return "v18";
1803 case UNW_PPC64_V19:
1804 return "v19";
1805 case UNW_PPC64_V20:
1806 return "v20";
1807 case UNW_PPC64_V21:
1808 return "v21";
1809 case UNW_PPC64_V22:
1810 return "v22";
1811 case UNW_PPC64_V23:
1812 return "v23";
1813 case UNW_PPC64_V24:
1814 return "v24";
1815 case UNW_PPC64_V25:
1816 return "v25";
1817 case UNW_PPC64_V26:
1818 return "v26";
1819 case UNW_PPC64_V27:
1820 return "v27";
1821 case UNW_PPC64_V28:
1822 return "v28";
1823 case UNW_PPC64_V29:
1824 return "v29";
1825 case UNW_PPC64_V30:
1826 return "v30";
1827 case UNW_PPC64_V31:
1828 return "v31";
1829 }
1830 return "unknown register";
1831}
1832#endif // _LIBUNWIND_TARGET_PPC64
1833
1834
1835#if defined(_LIBUNWIND_TARGET_AARCH64)
1836/// Registers_arm64 holds the register state of a thread in a 64-bit arm
1837/// process.
1838class _LIBUNWIND_HIDDEN Registers_arm64;
1839extern "C" int64_t __libunwind_Registers_arm64_za_disable();
1840extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *,
1841 unsigned walkedFrames);
1842
1843#if defined(_LIBUNWIND_USE_GCS)
1844extern "C" void *__libunwind_shstk_get_jump_target() {
1845 return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto);
1846}
1847#endif
1848
1849class _LIBUNWIND_HIDDEN Registers_arm64 {
1850public:
1851 Registers_arm64() = default;
1852 Registers_arm64(const void *registers);
1853 Registers_arm64(const Registers_arm64 &);
1854 Registers_arm64 &operator=(const Registers_arm64 &);
1855
1856 typedef uint64_t reg_t;
1857 typedef uint64_t __ptrauth_unwind_registers_arm64_link_reg link_reg_t;
1858
1859 // Use `link_hardened_reg_arg_t` to pass values of `link_reg_t` type as
1860 // function arguments. We need to use a const l-value reference to keep
1861 // signature of `__ptrauth`-qualified values of `link_reg_t` type on AArch64
1862 // PAuth-enabled ABI intact. Passing the raw pointer by value would cause
1863 // authentication on the caller side and make the pointer prone to
1864 // substitution if spilled to the stack in the callee.
1865 typedef const link_reg_t &link_hardened_reg_arg_t;
1866
1867 bool validRegister(int num) const;
1868 uint64_t getRegister(int num) const;
1869 void setRegister(int num, uint64_t value);
1870 bool validFloatRegister(int num) const;
1871 double getFloatRegister(int num) const;
1872 void setFloatRegister(int num, double value);
1873 bool validVectorRegister(int num) const;
1874 v128 getVectorRegister(int num) const;
1875 void setVectorRegister(int num, v128 value);
1876 static const char *getRegisterName(int num);
1877 void jumpto(unsigned walkedFrames = 0) {
1878 zaDisable();
1879 __libunwind_Registers_arm64_jumpto(this, walkedFrames);
1880 }
1881#ifdef _LIBUNWIND_TRACE_RET_INJECT
1882 _LIBUNWIND_TRACE_NO_INLINE
1883 void returnto(unsigned walkedFrames) { jumpto(walkedFrames); }
1884#endif
1885 static constexpr int lastDwarfRegNum() {
1886 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
1887 }
1888 static int getArch() { return REGISTERS_ARM64; }
1889
1890 uint64_t getSP() const { return _registers.__sp; }
1891 void setSP(uint64_t value) { _registers.__sp = value; }
1892 uint64_t getIP() const {
1893 uint64_t value = _registers.__pc;
1894#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
1895 // Note the value of the PC was signed to its address in the register state
1896 // but everyone else expects it to be signed by the SP, so convert on return.
1897 value = (uint64_t)ptrauth_auth_and_resign((void *)_registers.__pc,
1898 ptrauth_key_return_address,
1899 &_registers.__pc,
1900 ptrauth_key_return_address,
1901 getSP());
1902#endif
1903 return value;
1904 }
1905 void setIP(uint64_t value) {
1906#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
1907 // Note the value which was set should have been signed with the SP.
1908 // We then resign with the slot we are being stored in to so that both SP
1909 // and LR can't be spoofed at the same time.
1910 value = (uint64_t)ptrauth_auth_and_resign((void *)value,
1911 ptrauth_key_return_address,
1912 getSP(),
1913 ptrauth_key_return_address,
1914 &_registers.__pc);
1915#endif
1916 _registers.__pc = value;
1917 }
1918 uint64_t getFP() const { return _registers.__fp; }
1919 void setFP(uint64_t value) { _registers.__fp = value; }
1920
1921#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
1922 void
1923 loadAndAuthenticateLinkRegister(reg_t inplaceAuthedLinkRegister,
1924 link_reg_t *referenceAuthedLinkRegister) {
1925 // If we are in an arm64/arm64e frame, then the PC should have been signed
1926 // with the SP
1927 *referenceAuthedLinkRegister =
1928 (uint64_t)ptrauth_auth_data((void *)inplaceAuthedLinkRegister,
1929 ptrauth_key_return_address,
1930 _registers.__sp);
1931 }
1932#endif
1933
1934private:
1935 uint64_t lazyGetVG() const;
1936
1937 void zaDisable() const {
1938 if (!_misc_registers.__has_sme)
1939 return;
1940 if (__libunwind_Registers_arm64_za_disable() != 0)
1941 _LIBUNWIND_ABORT("SME ZA disable failed");
1942 }
1943
1944 static bool checkHasSME() {
1945#if defined(HAVE_SYS_AUXV_H)
1946 constexpr int hwcap2_sme = (1 << 23);
1947 unsigned long hwcap2 = getauxval(AT_HWCAP2);
1948 return (hwcap2 & hwcap2_sme) != 0;
1949#endif
1950 // TODO: Support other platforms.
1951 return false;
1952 }
1953
1954 struct GPRs {
1955 uint64_t __x[29] = {}; // x0-x28
1956 uint64_t __fp = 0; // Frame pointer x29
1957 uint64_t __lr = 0; // Link register x30
1958 uint64_t __sp = 0; // Stack pointer x31
1959 uint64_t __pc = 0; // Program counter
1960 uint64_t __ra_sign_state = 0; // RA sign state register
1961 };
1962
1963 struct Misc {
1964 mutable uint32_t __vg = 0; // Vector Granule
1965 bool __has_sme = checkHasSME();
1966 };
1967
1968 GPRs _registers = {};
1969 // Currently only the lower double in 128-bit vectore registers
1970 // is perserved during unwinding. We could define new register
1971 // numbers (> 96) which mean whole vector registers, then this
1972 // struct would need to change to contain whole vector registers.
1973 double _vectorHalfRegisters[32] = {};
1974
1975 // Miscellaneous/virtual registers. These are stored below the GPRs and FPRs
1976 // as they do not correspond to physical registers, so do not need to be
1977 // saved/restored in UnwindRegistersRestore.S and UnwindRegistersSave.S, and
1978 // we don't want to modify the existing offsets for GPRs and FPRs.
1979 Misc _misc_registers;
1980};
1981
1982inline Registers_arm64::Registers_arm64(const void *registers) {
1983 static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
1984 "arm64 registers do not fit into unw_context_t");
1985 memcpy(&_registers, registers, sizeof(_registers));
1986 static_assert(sizeof(GPRs) == 0x110,
1987 "expected VFP registers to be at offset 272");
1988 memcpy(_vectorHalfRegisters,
1989 static_cast<const uint8_t *>(registers) + sizeof(GPRs),
1990 sizeof(_vectorHalfRegisters));
1991 _misc_registers.__vg = 0;
1992
1993#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
1994 // We have to do some pointer authentication fixups after this copy,
1995 // and as part of that we need to load the source pc without
1996 // authenticating so that we maintain the signature for the resigning
1997 // performed by setIP.
1998 uint64_t pcRegister = 0;
1999 memmove(&pcRegister, ((uint8_t *)&_registers) + offsetof(GPRs, __pc),
2000 sizeof(pcRegister));
2001 setIP(pcRegister);
2002#endif
2003}
2004
2005inline Registers_arm64::Registers_arm64(const Registers_arm64 &other) {
2006 *this = other;
2007}
2008
2009inline Registers_arm64 &
2010Registers_arm64::operator=(const Registers_arm64 &other) {
2011 memmove(static_cast<void *>(this), &other, sizeof(*this));
2012 // We perform this step to ensure that we correctly authenticate and re-sign
2013 // the pc after the bitwise copy.
2014 setIP(other.getIP());
2015 return *this;
2016}
2017
2018inline bool Registers_arm64::validRegister(int regNum) const {
2019 if (regNum == UNW_REG_IP)
2020 return true;
2021 if (regNum == UNW_REG_SP)
2022 return true;
2023 if (regNum < 0)
2024 return false;
2025 if (regNum > 95)
2026 return false;
2027 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
2028 return true;
2029 if (regNum == UNW_AARCH64_VG)
2030 return true;
2031 if ((regNum > 32) && (regNum < 64))
2032 return false;
2033 return true;
2034}
2035
2036inline uint64_t Registers_arm64::lazyGetVG() const {
2037 if (!_misc_registers.__vg) {
2038#if defined(__aarch64__)
2039 register uint64_t vg asm("x0");
2040 asm(".inst 0x04e0e3e0" // CNTD x0
2041 : "=r"(vg));
2042 _misc_registers.__vg = vg;
2043#else
2044 _LIBUNWIND_ABORT("arm64 VG undefined");
2045#endif
2046 }
2047 return _misc_registers.__vg;
2048}
2049
2050inline uint64_t Registers_arm64::getRegister(int regNum) const {
2051 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
2052 return getIP();
2053 if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
2054 return _registers.__sp;
2055 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
2056 return _registers.__ra_sign_state;
2057 if (regNum == UNW_AARCH64_FP)
2058 return getFP();
2059 if (regNum == UNW_AARCH64_LR)
2060 return _registers.__lr;
2061 if (regNum == UNW_AARCH64_VG)
2062 return lazyGetVG();
2063 if ((regNum >= 0) && (regNum < 29))
2064 return _registers.__x[regNum];
2065 _LIBUNWIND_ABORT("unsupported arm64 register");
2066}
2067
2068inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
2069 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
2070 setIP(value);
2071 else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
2072 _registers.__sp = value;
2073 else if (regNum == UNW_AARCH64_RA_SIGN_STATE)
2074 _registers.__ra_sign_state = value;
2075 else if (regNum == UNW_AARCH64_FP)
2076 setFP(value);
2077 else if (regNum == UNW_AARCH64_LR)
2078 _registers.__lr = value;
2079 else if (regNum == UNW_AARCH64_VG)
2080 _misc_registers.__vg = value;
2081 else if ((regNum >= 0) && (regNum < 29))
2082 _registers.__x[regNum] = value;
2083 else
2084 _LIBUNWIND_ABORT("unsupported arm64 register");
2085}
2086
2087inline const char *Registers_arm64::getRegisterName(int regNum) {
2088 switch (regNum) {
2089 case UNW_REG_IP:
2090 return "pc";
2091 case UNW_REG_SP:
2092 return "sp";
2093 case UNW_AARCH64_X0:
2094 return "x0";
2095 case UNW_AARCH64_X1:
2096 return "x1";
2097 case UNW_AARCH64_X2:
2098 return "x2";
2099 case UNW_AARCH64_X3:
2100 return "x3";
2101 case UNW_AARCH64_X4:
2102 return "x4";
2103 case UNW_AARCH64_X5:
2104 return "x5";
2105 case UNW_AARCH64_X6:
2106 return "x6";
2107 case UNW_AARCH64_X7:
2108 return "x7";
2109 case UNW_AARCH64_X8:
2110 return "x8";
2111 case UNW_AARCH64_X9:
2112 return "x9";
2113 case UNW_AARCH64_X10:
2114 return "x10";
2115 case UNW_AARCH64_X11:
2116 return "x11";
2117 case UNW_AARCH64_X12:
2118 return "x12";
2119 case UNW_AARCH64_X13:
2120 return "x13";
2121 case UNW_AARCH64_X14:
2122 return "x14";
2123 case UNW_AARCH64_X15:
2124 return "x15";
2125 case UNW_AARCH64_X16:
2126 return "x16";
2127 case UNW_AARCH64_X17:
2128 return "x17";
2129 case UNW_AARCH64_X18:
2130 return "x18";
2131 case UNW_AARCH64_X19:
2132 return "x19";
2133 case UNW_AARCH64_X20:
2134 return "x20";
2135 case UNW_AARCH64_X21:
2136 return "x21";
2137 case UNW_AARCH64_X22:
2138 return "x22";
2139 case UNW_AARCH64_X23:
2140 return "x23";
2141 case UNW_AARCH64_X24:
2142 return "x24";
2143 case UNW_AARCH64_X25:
2144 return "x25";
2145 case UNW_AARCH64_X26:
2146 return "x26";
2147 case UNW_AARCH64_X27:
2148 return "x27";
2149 case UNW_AARCH64_X28:
2150 return "x28";
2151 case UNW_AARCH64_FP:
2152 return "fp";
2153 case UNW_AARCH64_LR:
2154 return "lr";
2155 case UNW_AARCH64_SP:
2156 return "sp";
2157 case UNW_AARCH64_PC:
2158 return "pc";
2159 case UNW_AARCH64_V0:
2160 return "d0";
2161 case UNW_AARCH64_V1:
2162 return "d1";
2163 case UNW_AARCH64_V2:
2164 return "d2";
2165 case UNW_AARCH64_V3:
2166 return "d3";
2167 case UNW_AARCH64_V4:
2168 return "d4";
2169 case UNW_AARCH64_V5:
2170 return "d5";
2171 case UNW_AARCH64_V6:
2172 return "d6";
2173 case UNW_AARCH64_V7:
2174 return "d7";
2175 case UNW_AARCH64_V8:
2176 return "d8";
2177 case UNW_AARCH64_V9:
2178 return "d9";
2179 case UNW_AARCH64_V10:
2180 return "d10";
2181 case UNW_AARCH64_V11:
2182 return "d11";
2183 case UNW_AARCH64_V12:
2184 return "d12";
2185 case UNW_AARCH64_V13:
2186 return "d13";
2187 case UNW_AARCH64_V14:
2188 return "d14";
2189 case UNW_AARCH64_V15:
2190 return "d15";
2191 case UNW_AARCH64_V16:
2192 return "d16";
2193 case UNW_AARCH64_V17:
2194 return "d17";
2195 case UNW_AARCH64_V18:
2196 return "d18";
2197 case UNW_AARCH64_V19:
2198 return "d19";
2199 case UNW_AARCH64_V20:
2200 return "d20";
2201 case UNW_AARCH64_V21:
2202 return "d21";
2203 case UNW_AARCH64_V22:
2204 return "d22";
2205 case UNW_AARCH64_V23:
2206 return "d23";
2207 case UNW_AARCH64_V24:
2208 return "d24";
2209 case UNW_AARCH64_V25:
2210 return "d25";
2211 case UNW_AARCH64_V26:
2212 return "d26";
2213 case UNW_AARCH64_V27:
2214 return "d27";
2215 case UNW_AARCH64_V28:
2216 return "d28";
2217 case UNW_AARCH64_V29:
2218 return "d29";
2219 case UNW_AARCH64_V30:
2220 return "d30";
2221 case UNW_AARCH64_V31:
2222 return "d31";
2223 default:
2224 return "unknown register";
2225 }
2226}
2227
2228inline bool Registers_arm64::validFloatRegister(int regNum) const {
2229 if (regNum < UNW_AARCH64_V0)
2230 return false;
2231 if (regNum > UNW_AARCH64_V31)
2232 return false;
2233 return true;
2234}
2235
2236inline double Registers_arm64::getFloatRegister(int regNum) const {
2237 assert(validFloatRegister(regNum));
2238 return _vectorHalfRegisters[regNum - UNW_AARCH64_V0];
2239}
2240
2241inline void Registers_arm64::setFloatRegister(int regNum, double value) {
2242 assert(validFloatRegister(regNum));
2243 _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value;
2244}
2245
2246inline bool Registers_arm64::validVectorRegister(int) const {
2247 return false;
2248}
2249
2250inline v128 Registers_arm64::getVectorRegister(int) const {
2251 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2252}
2253
2254inline void Registers_arm64::setVectorRegister(int, v128) {
2255 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2256}
2257#endif // _LIBUNWIND_TARGET_AARCH64
2258
2259#if defined(_LIBUNWIND_TARGET_ARM)
2260/// Registers_arm holds the register state of a thread in a 32-bit arm
2261/// process.
2262///
2263/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2264/// this uses more memory than required.
2265class _LIBUNWIND_HIDDEN Registers_arm {
2266public:
2267 Registers_arm();
2268 Registers_arm(const void *registers);
2269
2270 typedef uint32_t reg_t;
2271 typedef uint32_t link_reg_t;
2272 typedef const link_reg_t &link_hardened_reg_arg_t;
2273
2274 bool validRegister(int num) const;
2275 uint32_t getRegister(int num) const;
2276 void setRegister(int num, uint32_t value);
2277 bool validFloatRegister(int num) const;
2278 unw_fpreg_t getFloatRegister(int num);
2279 void setFloatRegister(int num, unw_fpreg_t value);
2280 bool validVectorRegister(int num) const;
2281 v128 getVectorRegister(int num) const;
2282 void setVectorRegister(int num, v128 value);
2283 static const char *getRegisterName(int num);
2284 void jumpto() {
2285 restoreSavedFloatRegisters();
2286 restoreCoreAndJumpTo();
2287 }
2288 static constexpr int lastDwarfRegNum() {
2289 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM;
2290 }
2291 static int getArch() { return REGISTERS_ARM; }
2292
2293 uint32_t getSP() const { return _registers.__sp; }
2294 void setSP(uint32_t value) { _registers.__sp = value; }
2295 uint32_t getIP() const { return _registers.__pc; }
2296 void setIP(uint32_t value) { _registers.__pc = value; }
2297
2298 void saveVFPAsX() {
2299 assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
2300 _use_X_for_vfp_save = true;
2301 }
2302
2303 void restoreSavedFloatRegisters() {
2304 if (_saved_vfp_d0_d15) {
2305 if (_use_X_for_vfp_save)
2306 restoreVFPWithFLDMX(_vfp_d0_d15_pad);
2307 else
2308 restoreVFPWithFLDMD(_vfp_d0_d15_pad);
2309 }
2310 if (_saved_vfp_d16_d31)
2311 restoreVFPv3(_vfp_d16_d31);
2312#if defined(__ARM_WMMX)
2313 if (_saved_iwmmx)
2314 restoreiWMMX(_iwmmx);
2315 if (_saved_iwmmx_control)
2316 restoreiWMMXControl(_iwmmx_control);
2317#endif
2318 }
2319
2320private:
2321 struct GPRs {
2322 uint32_t __r[13]; // r0-r12
2323 uint32_t __sp; // Stack pointer r13
2324 uint32_t __lr; // Link register r14
2325 uint32_t __pc; // Program counter r15
2326 };
2327
2328 struct PseudoRegisters {
2329 uint32_t __pac; // Return Authentication Code (PAC)
2330 };
2331
2332 static void saveVFPWithFSTMD(void*);
2333 static void saveVFPWithFSTMX(void*);
2334 static void saveVFPv3(void*);
2335 static void restoreVFPWithFLDMD(void*);
2336 static void restoreVFPWithFLDMX(void*);
2337 static void restoreVFPv3(void*);
2338#if defined(__ARM_WMMX)
2339 static void saveiWMMX(void*);
2340 static void saveiWMMXControl(uint32_t*);
2341 static void restoreiWMMX(void*);
2342 static void restoreiWMMXControl(uint32_t*);
2343#endif
2344 void restoreCoreAndJumpTo();
2345
2346 // ARM registers
2347 GPRs _registers;
2348 PseudoRegisters _pseudo_registers;
2349
2350 // We save floating point registers lazily because we can't know ahead of
2351 // time which ones are used. See EHABI #4.7.
2352
2353 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2354 //
2355 // See EHABI #7.5 that explains how matching instruction sequences for load
2356 // and store need to be used to correctly restore the exact register bits.
2357 bool _use_X_for_vfp_save;
2358 // Whether VFP D0-D15 are saved.
2359 bool _saved_vfp_d0_d15;
2360 // Whether VFPv3 D16-D31 are saved.
2361 bool _saved_vfp_d16_d31;
2362 // VFP registers D0-D15, + padding if saved using FSTMX
2363 unw_fpreg_t _vfp_d0_d15_pad[17];
2364 // VFPv3 registers D16-D31, always saved using FSTMD
2365 unw_fpreg_t _vfp_d16_d31[16];
2366#if defined(__ARM_WMMX)
2367 // Whether iWMMX data registers are saved.
2368 bool _saved_iwmmx;
2369 // Whether iWMMX control registers are saved.
2370 mutable bool _saved_iwmmx_control;
2371 // iWMMX registers
2372 unw_fpreg_t _iwmmx[16];
2373 // iWMMX control registers
2374 mutable uint32_t _iwmmx_control[4];
2375#endif
2376};
2377
2378inline Registers_arm::Registers_arm(const void *registers)
2379 : _use_X_for_vfp_save(false),
2380 _saved_vfp_d0_d15(false),
2381 _saved_vfp_d16_d31(false) {
2382 static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
2383 "arm registers do not fit into unw_context_t");
2384 // See __unw_getcontext() note about data.
2385 memcpy(&_registers, registers, sizeof(_registers));
2386 memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));
2387 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2388 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2389#if defined(__ARM_WMMX)
2390 _saved_iwmmx = false;
2391 _saved_iwmmx_control = false;
2392 memset(&_iwmmx, 0, sizeof(_iwmmx));
2393 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2394#endif
2395}
2396
2397inline Registers_arm::Registers_arm()
2398 : _use_X_for_vfp_save(false),
2399 _saved_vfp_d0_d15(false),
2400 _saved_vfp_d16_d31(false) {
2401 memset(&_registers, 0, sizeof(_registers));
2402 memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));
2403 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2404 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2405#if defined(__ARM_WMMX)
2406 _saved_iwmmx = false;
2407 _saved_iwmmx_control = false;
2408 memset(&_iwmmx, 0, sizeof(_iwmmx));
2409 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2410#endif
2411}
2412
2413inline bool Registers_arm::validRegister(int regNum) const {
2414 // Returns true for all non-VFP registers supported by the EHABI
2415 // virtual register set (VRS).
2416 if (regNum == UNW_REG_IP)
2417 return true;
2418
2419 if (regNum == UNW_REG_SP)
2420 return true;
2421
2422 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
2423 return true;
2424
2425#if defined(__ARM_WMMX)
2426 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
2427 return true;
2428#endif
2429
2430#ifdef __ARM_FEATURE_PAUTH
2431 if (regNum == UNW_ARM_RA_AUTH_CODE)
2432 return true;
2433#endif
2434
2435 return false;
2436}
2437
2438inline uint32_t Registers_arm::getRegister(int regNum) const {
2439 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
2440 return _registers.__sp;
2441
2442 if (regNum == UNW_ARM_LR)
2443 return _registers.__lr;
2444
2445 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
2446 return _registers.__pc;
2447
2448 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
2449 return _registers.__r[regNum];
2450
2451#if defined(__ARM_WMMX)
2452 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2453 if (!_saved_iwmmx_control) {
2454 _saved_iwmmx_control = true;
2455 saveiWMMXControl(_iwmmx_control);
2456 }
2457 return _iwmmx_control[regNum - UNW_ARM_WC0];
2458 }
2459#endif
2460
2461#ifdef __ARM_FEATURE_PAUTH
2462 if (regNum == UNW_ARM_RA_AUTH_CODE)
2463 return _pseudo_registers.__pac;
2464#endif
2465
2466 _LIBUNWIND_ABORT("unsupported arm register");
2467}
2468
2469inline void Registers_arm::setRegister(int regNum, uint32_t value) {
2470 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
2471 _registers.__sp = value;
2472 return;
2473 }
2474
2475 if (regNum == UNW_ARM_LR) {
2476 _registers.__lr = value;
2477 return;
2478 }
2479
2480 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
2481 _registers.__pc = value;
2482 return;
2483 }
2484
2485 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
2486 _registers.__r[regNum] = value;
2487 return;
2488 }
2489
2490#if defined(__ARM_WMMX)
2491 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2492 if (!_saved_iwmmx_control) {
2493 _saved_iwmmx_control = true;
2494 saveiWMMXControl(_iwmmx_control);
2495 }
2496 _iwmmx_control[regNum - UNW_ARM_WC0] = value;
2497 return;
2498 }
2499#endif
2500
2501 if (regNum == UNW_ARM_RA_AUTH_CODE) {
2502 _pseudo_registers.__pac = value;
2503 return;
2504 }
2505
2506 _LIBUNWIND_ABORT("unsupported arm register");
2507}
2508
2509inline const char *Registers_arm::getRegisterName(int regNum) {
2510 switch (regNum) {
2511 case UNW_REG_IP:
2512 case UNW_ARM_IP: // UNW_ARM_R15 is alias
2513 return "pc";
2514 case UNW_ARM_LR: // UNW_ARM_R14 is alias
2515 return "lr";
2516 case UNW_REG_SP:
2517 case UNW_ARM_SP: // UNW_ARM_R13 is alias
2518 return "sp";
2519 case UNW_ARM_R0:
2520 return "r0";
2521 case UNW_ARM_R1:
2522 return "r1";
2523 case UNW_ARM_R2:
2524 return "r2";
2525 case UNW_ARM_R3:
2526 return "r3";
2527 case UNW_ARM_R4:
2528 return "r4";
2529 case UNW_ARM_R5:
2530 return "r5";
2531 case UNW_ARM_R6:
2532 return "r6";
2533 case UNW_ARM_R7:
2534 return "r7";
2535 case UNW_ARM_R8:
2536 return "r8";
2537 case UNW_ARM_R9:
2538 return "r9";
2539 case UNW_ARM_R10:
2540 return "r10";
2541 case UNW_ARM_R11:
2542 return "r11";
2543 case UNW_ARM_R12:
2544 return "r12";
2545 case UNW_ARM_S0:
2546 return "s0";
2547 case UNW_ARM_S1:
2548 return "s1";
2549 case UNW_ARM_S2:
2550 return "s2";
2551 case UNW_ARM_S3:
2552 return "s3";
2553 case UNW_ARM_S4:
2554 return "s4";
2555 case UNW_ARM_S5:
2556 return "s5";
2557 case UNW_ARM_S6:
2558 return "s6";
2559 case UNW_ARM_S7:
2560 return "s7";
2561 case UNW_ARM_S8:
2562 return "s8";
2563 case UNW_ARM_S9:
2564 return "s9";
2565 case UNW_ARM_S10:
2566 return "s10";
2567 case UNW_ARM_S11:
2568 return "s11";
2569 case UNW_ARM_S12:
2570 return "s12";
2571 case UNW_ARM_S13:
2572 return "s13";
2573 case UNW_ARM_S14:
2574 return "s14";
2575 case UNW_ARM_S15:
2576 return "s15";
2577 case UNW_ARM_S16:
2578 return "s16";
2579 case UNW_ARM_S17:
2580 return "s17";
2581 case UNW_ARM_S18:
2582 return "s18";
2583 case UNW_ARM_S19:
2584 return "s19";
2585 case UNW_ARM_S20:
2586 return "s20";
2587 case UNW_ARM_S21:
2588 return "s21";
2589 case UNW_ARM_S22:
2590 return "s22";
2591 case UNW_ARM_S23:
2592 return "s23";
2593 case UNW_ARM_S24:
2594 return "s24";
2595 case UNW_ARM_S25:
2596 return "s25";
2597 case UNW_ARM_S26:
2598 return "s26";
2599 case UNW_ARM_S27:
2600 return "s27";
2601 case UNW_ARM_S28:
2602 return "s28";
2603 case UNW_ARM_S29:
2604 return "s29";
2605 case UNW_ARM_S30:
2606 return "s30";
2607 case UNW_ARM_S31:
2608 return "s31";
2609 case UNW_ARM_D0:
2610 return "d0";
2611 case UNW_ARM_D1:
2612 return "d1";
2613 case UNW_ARM_D2:
2614 return "d2";
2615 case UNW_ARM_D3:
2616 return "d3";
2617 case UNW_ARM_D4:
2618 return "d4";
2619 case UNW_ARM_D5:
2620 return "d5";
2621 case UNW_ARM_D6:
2622 return "d6";
2623 case UNW_ARM_D7:
2624 return "d7";
2625 case UNW_ARM_D8:
2626 return "d8";
2627 case UNW_ARM_D9:
2628 return "d9";
2629 case UNW_ARM_D10:
2630 return "d10";
2631 case UNW_ARM_D11:
2632 return "d11";
2633 case UNW_ARM_D12:
2634 return "d12";
2635 case UNW_ARM_D13:
2636 return "d13";
2637 case UNW_ARM_D14:
2638 return "d14";
2639 case UNW_ARM_D15:
2640 return "d15";
2641 case UNW_ARM_D16:
2642 return "d16";
2643 case UNW_ARM_D17:
2644 return "d17";
2645 case UNW_ARM_D18:
2646 return "d18";
2647 case UNW_ARM_D19:
2648 return "d19";
2649 case UNW_ARM_D20:
2650 return "d20";
2651 case UNW_ARM_D21:
2652 return "d21";
2653 case UNW_ARM_D22:
2654 return "d22";
2655 case UNW_ARM_D23:
2656 return "d23";
2657 case UNW_ARM_D24:
2658 return "d24";
2659 case UNW_ARM_D25:
2660 return "d25";
2661 case UNW_ARM_D26:
2662 return "d26";
2663 case UNW_ARM_D27:
2664 return "d27";
2665 case UNW_ARM_D28:
2666 return "d28";
2667 case UNW_ARM_D29:
2668 return "d29";
2669 case UNW_ARM_D30:
2670 return "d30";
2671 case UNW_ARM_D31:
2672 return "d31";
2673 default:
2674 return "unknown register";
2675 }
2676}
2677
2678inline bool Registers_arm::validFloatRegister(int regNum) const {
2679 // NOTE: Consider the intel MMX registers floating points so the
2680 // __unw_get_fpreg can be used to transmit the 64-bit data back.
2681 return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
2682#if defined(__ARM_WMMX)
2683 || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
2684#endif
2685 ;
2686}
2687
2688inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
2689 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2690 if (!_saved_vfp_d0_d15) {
2691 _saved_vfp_d0_d15 = true;
2692 if (_use_X_for_vfp_save)
2693 saveVFPWithFSTMX(_vfp_d0_d15_pad);
2694 else
2695 saveVFPWithFSTMD(_vfp_d0_d15_pad);
2696 }
2697 return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
2698 }
2699
2700 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2701 if (!_saved_vfp_d16_d31) {
2702 _saved_vfp_d16_d31 = true;
2703 saveVFPv3(_vfp_d16_d31);
2704 }
2705 return _vfp_d16_d31[regNum - UNW_ARM_D16];
2706 }
2707
2708#if defined(__ARM_WMMX)
2709 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2710 if (!_saved_iwmmx) {
2711 _saved_iwmmx = true;
2712 saveiWMMX(_iwmmx);
2713 }
2714 return _iwmmx[regNum - UNW_ARM_WR0];
2715 }
2716#endif
2717
2718 _LIBUNWIND_ABORT("Unknown ARM float register");
2719}
2720
2721inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
2722 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2723 if (!_saved_vfp_d0_d15) {
2724 _saved_vfp_d0_d15 = true;
2725 if (_use_X_for_vfp_save)
2726 saveVFPWithFSTMX(_vfp_d0_d15_pad);
2727 else
2728 saveVFPWithFSTMD(_vfp_d0_d15_pad);
2729 }
2730 _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
2731 return;
2732 }
2733
2734 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2735 if (!_saved_vfp_d16_d31) {
2736 _saved_vfp_d16_d31 = true;
2737 saveVFPv3(_vfp_d16_d31);
2738 }
2739 _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
2740 return;
2741 }
2742
2743#if defined(__ARM_WMMX)
2744 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2745 if (!_saved_iwmmx) {
2746 _saved_iwmmx = true;
2747 saveiWMMX(_iwmmx);
2748 }
2749 _iwmmx[regNum - UNW_ARM_WR0] = value;
2750 return;
2751 }
2752#endif
2753
2754 _LIBUNWIND_ABORT("Unknown ARM float register");
2755}
2756
2757inline bool Registers_arm::validVectorRegister(int) const {
2758 return false;
2759}
2760
2761inline v128 Registers_arm::getVectorRegister(int) const {
2762 _LIBUNWIND_ABORT("ARM vector support not implemented");
2763}
2764
2765inline void Registers_arm::setVectorRegister(int, v128) {
2766 _LIBUNWIND_ABORT("ARM vector support not implemented");
2767}
2768#endif // _LIBUNWIND_TARGET_ARM
2769
2770
2771#if defined(_LIBUNWIND_TARGET_OR1K)
2772/// Registers_or1k holds the register state of a thread in an OpenRISC1000
2773/// process.
2774class _LIBUNWIND_HIDDEN Registers_or1k {
2775public:
2776 Registers_or1k();
2777 Registers_or1k(const void *registers);
2778
2779 typedef uint32_t reg_t;
2780 typedef uint32_t link_reg_t;
2781 typedef const link_reg_t &link_hardened_reg_arg_t;
2782
2783 bool validRegister(int num) const;
2784 uint32_t getRegister(int num) const;
2785 void setRegister(int num, uint32_t value);
2786 bool validFloatRegister(int num) const;
2787 double getFloatRegister(int num) const;
2788 void setFloatRegister(int num, double value);
2789 bool validVectorRegister(int num) const;
2790 v128 getVectorRegister(int num) const;
2791 void setVectorRegister(int num, v128 value);
2792 static const char *getRegisterName(int num);
2793 void jumpto();
2794 static constexpr int lastDwarfRegNum() {
2795 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K;
2796 }
2797 static int getArch() { return REGISTERS_OR1K; }
2798
2799 uint64_t getSP() const { return _registers.__r[1]; }
2800 void setSP(uint32_t value) { _registers.__r[1] = value; }
2801 uint64_t getIP() const { return _registers.__pc; }
2802 void setIP(uint32_t value) { _registers.__pc = value; }
2803
2804private:
2805 struct or1k_thread_state_t {
2806 unsigned int __r[32]; // r0-r31
2807 unsigned int __pc; // Program counter
2808 unsigned int __epcr; // Program counter at exception
2809 };
2810
2811 or1k_thread_state_t _registers;
2812};
2813
2814inline Registers_or1k::Registers_or1k(const void *registers) {
2815 static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
2816 "or1k registers do not fit into unw_context_t");
2817 memcpy(&_registers, static_cast<const uint8_t *>(registers),
2818 sizeof(_registers));
2819}
2820
2821inline Registers_or1k::Registers_or1k() {
2822 memset(&_registers, 0, sizeof(_registers));
2823}
2824
2825inline bool Registers_or1k::validRegister(int regNum) const {
2826 if (regNum == UNW_REG_IP)
2827 return true;
2828 if (regNum == UNW_REG_SP)
2829 return true;
2830 if (regNum < 0)
2831 return false;
2832 if (regNum <= UNW_OR1K_R31)
2833 return true;
2834 if (regNum == UNW_OR1K_EPCR)
2835 return true;
2836 return false;
2837}
2838
2839inline uint32_t Registers_or1k::getRegister(int regNum) const {
2840 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
2841 return _registers.__r[regNum - UNW_OR1K_R0];
2842
2843 switch (regNum) {
2844 case UNW_REG_IP:
2845 return _registers.__pc;
2846 case UNW_REG_SP:
2847 return _registers.__r[1];
2848 case UNW_OR1K_EPCR:
2849 return _registers.__epcr;
2850 }
2851 _LIBUNWIND_ABORT("unsupported or1k register");
2852}
2853
2854inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
2855 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
2856 _registers.__r[regNum - UNW_OR1K_R0] = value;
2857 return;
2858 }
2859
2860 switch (regNum) {
2861 case UNW_REG_IP:
2862 _registers.__pc = value;
2863 return;
2864 case UNW_REG_SP:
2865 _registers.__r[1] = value;
2866 return;
2867 case UNW_OR1K_EPCR:
2868 _registers.__epcr = value;
2869 return;
2870 }
2871 _LIBUNWIND_ABORT("unsupported or1k register");
2872}
2873
2874inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2875 return false;
2876}
2877
2878inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2879 _LIBUNWIND_ABORT("or1k float support not implemented");
2880}
2881
2882inline void Registers_or1k::setFloatRegister(int /* regNum */,
2883 double /* value */) {
2884 _LIBUNWIND_ABORT("or1k float support not implemented");
2885}
2886
2887inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2888 return false;
2889}
2890
2891inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
2892 _LIBUNWIND_ABORT("or1k vector support not implemented");
2893}
2894
2895inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
2896 _LIBUNWIND_ABORT("or1k vector support not implemented");
2897}
2898
2899inline const char *Registers_or1k::getRegisterName(int regNum) {
2900 switch (regNum) {
2901 case UNW_OR1K_R0:
2902 return "r0";
2903 case UNW_OR1K_R1:
2904 return "r1";
2905 case UNW_OR1K_R2:
2906 return "r2";
2907 case UNW_OR1K_R3:
2908 return "r3";
2909 case UNW_OR1K_R4:
2910 return "r4";
2911 case UNW_OR1K_R5:
2912 return "r5";
2913 case UNW_OR1K_R6:
2914 return "r6";
2915 case UNW_OR1K_R7:
2916 return "r7";
2917 case UNW_OR1K_R8:
2918 return "r8";
2919 case UNW_OR1K_R9:
2920 return "r9";
2921 case UNW_OR1K_R10:
2922 return "r10";
2923 case UNW_OR1K_R11:
2924 return "r11";
2925 case UNW_OR1K_R12:
2926 return "r12";
2927 case UNW_OR1K_R13:
2928 return "r13";
2929 case UNW_OR1K_R14:
2930 return "r14";
2931 case UNW_OR1K_R15:
2932 return "r15";
2933 case UNW_OR1K_R16:
2934 return "r16";
2935 case UNW_OR1K_R17:
2936 return "r17";
2937 case UNW_OR1K_R18:
2938 return "r18";
2939 case UNW_OR1K_R19:
2940 return "r19";
2941 case UNW_OR1K_R20:
2942 return "r20";
2943 case UNW_OR1K_R21:
2944 return "r21";
2945 case UNW_OR1K_R22:
2946 return "r22";
2947 case UNW_OR1K_R23:
2948 return "r23";
2949 case UNW_OR1K_R24:
2950 return "r24";
2951 case UNW_OR1K_R25:
2952 return "r25";
2953 case UNW_OR1K_R26:
2954 return "r26";
2955 case UNW_OR1K_R27:
2956 return "r27";
2957 case UNW_OR1K_R28:
2958 return "r28";
2959 case UNW_OR1K_R29:
2960 return "r29";
2961 case UNW_OR1K_R30:
2962 return "r30";
2963 case UNW_OR1K_R31:
2964 return "r31";
2965 case UNW_OR1K_EPCR:
2966 return "EPCR";
2967 default:
2968 return "unknown register";
2969 }
2970
2971}
2972#endif // _LIBUNWIND_TARGET_OR1K
2973
2974#if defined(_LIBUNWIND_TARGET_MIPS_O32)
2975/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2976/// process.
2977class _LIBUNWIND_HIDDEN Registers_mips_o32 {
2978public:
2979 Registers_mips_o32();
2980 Registers_mips_o32(const void *registers);
2981
2982 typedef uint32_t reg_t;
2983 typedef uint32_t link_reg_t;
2984 typedef const link_reg_t &link_hardened_reg_arg_t;
2985
2986 bool validRegister(int num) const;
2987 uint32_t getRegister(int num) const;
2988 void setRegister(int num, uint32_t value);
2989 bool validFloatRegister(int num) const;
2990 double getFloatRegister(int num) const;
2991 void setFloatRegister(int num, double value);
2992 bool validVectorRegister(int num) const;
2993 v128 getVectorRegister(int num) const;
2994 void setVectorRegister(int num, v128 value);
2995 static const char *getRegisterName(int num);
2996 void jumpto();
2997 static constexpr int lastDwarfRegNum() {
2998 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
2999 }
3000 static int getArch() { return REGISTERS_MIPS_O32; }
3001
3002 uint32_t getSP() const { return _registers.__r[29]; }
3003 void setSP(uint32_t value) { _registers.__r[29] = value; }
3004 uint32_t getIP() const { return _registers.__pc; }
3005 void setIP(uint32_t value) { _registers.__pc = value; }
3006
3007private:
3008 struct mips_o32_thread_state_t {
3009 uint32_t __r[32];
3010 uint32_t __pc;
3011 uint32_t __hi;
3012 uint32_t __lo;
3013 };
3014
3015 mips_o32_thread_state_t _registers;
3016#ifdef __mips_hard_float
3017 /// O32 with 32-bit floating point registers only uses half of this
3018 /// space. However, using the same layout for 32-bit vs 64-bit
3019 /// floating point registers results in a single context size for
3020 /// O32 with hard float.
3021 uint32_t _padding;
3022 double _floats[32];
3023#endif
3024};
3025
3026inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
3027 static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
3028 "mips_o32 registers do not fit into unw_context_t");
3029 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3030 sizeof(_registers));
3031}
3032
3033inline Registers_mips_o32::Registers_mips_o32() {
3034 memset(&_registers, 0, sizeof(_registers));
3035}
3036
3037inline bool Registers_mips_o32::validRegister(int regNum) const {
3038 if (regNum == UNW_REG_IP)
3039 return true;
3040 if (regNum == UNW_REG_SP)
3041 return true;
3042 if (regNum < 0)
3043 return false;
3044 if (regNum <= UNW_MIPS_R31)
3045 return true;
3046#if __mips_isa_rev < 6
3047 if (regNum == UNW_MIPS_HI)
3048 return true;
3049 if (regNum == UNW_MIPS_LO)
3050 return true;
3051#endif
3052#if defined(__mips_hard_float) && __mips_fpr == 32
3053 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3054 return true;
3055#endif
3056 // FIXME: DSP accumulator registers, MSA registers
3057 return false;
3058}
3059
3060inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
3061 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
3062 return _registers.__r[regNum - UNW_MIPS_R0];
3063#if defined(__mips_hard_float) && __mips_fpr == 32
3064 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
3065 uint32_t *p;
3066
3067 if (regNum % 2 == 0)
3068 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
3069 else
3070 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
3071 return *p;
3072 }
3073#endif
3074
3075 switch (regNum) {
3076 case UNW_REG_IP:
3077 return _registers.__pc;
3078 case UNW_REG_SP:
3079 return _registers.__r[29];
3080#if __mips_isa_rev < 6
3081 case UNW_MIPS_HI:
3082 return _registers.__hi;
3083 case UNW_MIPS_LO:
3084 return _registers.__lo;
3085#endif
3086 }
3087 _LIBUNWIND_ABORT("unsupported mips_o32 register");
3088}
3089
3090inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
3091 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
3092 _registers.__r[regNum - UNW_MIPS_R0] = value;
3093 return;
3094 }
3095#if defined(__mips_hard_float) && __mips_fpr == 32
3096 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
3097 uint32_t *p;
3098
3099 if (regNum % 2 == 0)
3100 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
3101 else
3102 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
3103 *p = value;
3104 return;
3105 }
3106#endif
3107
3108 switch (regNum) {
3109 case UNW_REG_IP:
3110 _registers.__pc = value;
3111 return;
3112 case UNW_REG_SP:
3113 _registers.__r[29] = value;
3114 return;
3115#if __mips_isa_rev < 6
3116 case UNW_MIPS_HI:
3117 _registers.__hi = value;
3118 return;
3119 case UNW_MIPS_LO:
3120 _registers.__lo = value;
3121#endif
3122 return;
3123 }
3124 _LIBUNWIND_ABORT("unsupported mips_o32 register");
3125}
3126
3127inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
3128#if defined(__mips_hard_float) && __mips_fpr == 64
3129 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3130 return true;
3131#else
3132 (void)regNum;
3133#endif
3134 return false;
3135}
3136
3137inline double Registers_mips_o32::getFloatRegister(int regNum) const {
3138#if defined(__mips_hard_float) && __mips_fpr == 64
3139 assert(validFloatRegister(regNum));
3140 return _floats[regNum - UNW_MIPS_F0];
3141#else
3142 (void)regNum;
3143 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
3144#endif
3145}
3146
3147inline void Registers_mips_o32::setFloatRegister(int regNum,
3148 double value) {
3149#if defined(__mips_hard_float) && __mips_fpr == 64
3150 assert(validFloatRegister(regNum));
3151 _floats[regNum - UNW_MIPS_F0] = value;
3152#else
3153 (void)regNum;
3154 (void)value;
3155 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
3156#endif
3157}
3158
3159inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
3160 return false;
3161}
3162
3163inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
3164 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
3165}
3166
3167inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
3168 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
3169}
3170
3171inline const char *Registers_mips_o32::getRegisterName(int regNum) {
3172 switch (regNum) {
3173 case UNW_MIPS_R0:
3174 return "$0";
3175 case UNW_MIPS_R1:
3176 return "$1";
3177 case UNW_MIPS_R2:
3178 return "$2";
3179 case UNW_MIPS_R3:
3180 return "$3";
3181 case UNW_MIPS_R4:
3182 return "$4";
3183 case UNW_MIPS_R5:
3184 return "$5";
3185 case UNW_MIPS_R6:
3186 return "$6";
3187 case UNW_MIPS_R7:
3188 return "$7";
3189 case UNW_MIPS_R8:
3190 return "$8";
3191 case UNW_MIPS_R9:
3192 return "$9";
3193 case UNW_MIPS_R10:
3194 return "$10";
3195 case UNW_MIPS_R11:
3196 return "$11";
3197 case UNW_MIPS_R12:
3198 return "$12";
3199 case UNW_MIPS_R13:
3200 return "$13";
3201 case UNW_MIPS_R14:
3202 return "$14";
3203 case UNW_MIPS_R15:
3204 return "$15";
3205 case UNW_MIPS_R16:
3206 return "$16";
3207 case UNW_MIPS_R17:
3208 return "$17";
3209 case UNW_MIPS_R18:
3210 return "$18";
3211 case UNW_MIPS_R19:
3212 return "$19";
3213 case UNW_MIPS_R20:
3214 return "$20";
3215 case UNW_MIPS_R21:
3216 return "$21";
3217 case UNW_MIPS_R22:
3218 return "$22";
3219 case UNW_MIPS_R23:
3220 return "$23";
3221 case UNW_MIPS_R24:
3222 return "$24";
3223 case UNW_MIPS_R25:
3224 return "$25";
3225 case UNW_MIPS_R26:
3226 return "$26";
3227 case UNW_MIPS_R27:
3228 return "$27";
3229 case UNW_MIPS_R28:
3230 return "$28";
3231 case UNW_MIPS_R29:
3232 return "$29";
3233 case UNW_MIPS_R30:
3234 return "$30";
3235 case UNW_MIPS_R31:
3236 return "$31";
3237 case UNW_MIPS_F0:
3238 return "$f0";
3239 case UNW_MIPS_F1:
3240 return "$f1";
3241 case UNW_MIPS_F2:
3242 return "$f2";
3243 case UNW_MIPS_F3:
3244 return "$f3";
3245 case UNW_MIPS_F4:
3246 return "$f4";
3247 case UNW_MIPS_F5:
3248 return "$f5";
3249 case UNW_MIPS_F6:
3250 return "$f6";
3251 case UNW_MIPS_F7:
3252 return "$f7";
3253 case UNW_MIPS_F8:
3254 return "$f8";
3255 case UNW_MIPS_F9:
3256 return "$f9";
3257 case UNW_MIPS_F10:
3258 return "$f10";
3259 case UNW_MIPS_F11:
3260 return "$f11";
3261 case UNW_MIPS_F12:
3262 return "$f12";
3263 case UNW_MIPS_F13:
3264 return "$f13";
3265 case UNW_MIPS_F14:
3266 return "$f14";
3267 case UNW_MIPS_F15:
3268 return "$f15";
3269 case UNW_MIPS_F16:
3270 return "$f16";
3271 case UNW_MIPS_F17:
3272 return "$f17";
3273 case UNW_MIPS_F18:
3274 return "$f18";
3275 case UNW_MIPS_F19:
3276 return "$f19";
3277 case UNW_MIPS_F20:
3278 return "$f20";
3279 case UNW_MIPS_F21:
3280 return "$f21";
3281 case UNW_MIPS_F22:
3282 return "$f22";
3283 case UNW_MIPS_F23:
3284 return "$f23";
3285 case UNW_MIPS_F24:
3286 return "$f24";
3287 case UNW_MIPS_F25:
3288 return "$f25";
3289 case UNW_MIPS_F26:
3290 return "$f26";
3291 case UNW_MIPS_F27:
3292 return "$f27";
3293 case UNW_MIPS_F28:
3294 return "$f28";
3295 case UNW_MIPS_F29:
3296 return "$f29";
3297 case UNW_MIPS_F30:
3298 return "$f30";
3299 case UNW_MIPS_F31:
3300 return "$f31";
3301#if __mips_isa_rev < 6
3302 case UNW_MIPS_HI:
3303 return "$hi";
3304 case UNW_MIPS_LO:
3305 return "$lo";
3306#endif
3307 default:
3308 return "unknown register";
3309 }
3310}
3311#endif // _LIBUNWIND_TARGET_MIPS_O32
3312
3313#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3314/// Registers_mips_newabi holds the register state of a thread in a
3315/// MIPS process using NEWABI (the N32 or N64 ABIs).
3316class _LIBUNWIND_HIDDEN Registers_mips_newabi {
3317public:
3318 Registers_mips_newabi();
3319 Registers_mips_newabi(const void *registers);
3320
3321 typedef uint64_t reg_t;
3322 typedef uint64_t link_reg_t;
3323 typedef const link_reg_t &link_hardened_reg_arg_t;
3324
3325 bool validRegister(int num) const;
3326 uint64_t getRegister(int num) const;
3327 void setRegister(int num, uint64_t value);
3328 bool validFloatRegister(int num) const;
3329 double getFloatRegister(int num) const;
3330 void setFloatRegister(int num, double value);
3331 bool validVectorRegister(int num) const;
3332 v128 getVectorRegister(int num) const;
3333 void setVectorRegister(int num, v128 value);
3334 static const char *getRegisterName(int num);
3335 void jumpto();
3336 static constexpr int lastDwarfRegNum() {
3337 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
3338 }
3339 static int getArch() { return REGISTERS_MIPS_NEWABI; }
3340
3341 uint64_t getSP() const { return _registers.__r[29]; }
3342 void setSP(uint64_t value) { _registers.__r[29] = value; }
3343 uint64_t getIP() const { return _registers.__pc; }
3344 void setIP(uint64_t value) { _registers.__pc = value; }
3345
3346private:
3347 struct mips_newabi_thread_state_t {
3348 uint64_t __r[32];
3349 uint64_t __pc;
3350 uint64_t __hi;
3351 uint64_t __lo;
3352 };
3353
3354 mips_newabi_thread_state_t _registers;
3355#ifdef __mips_hard_float
3356 double _floats[32];
3357#endif
3358};
3359
3360inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
3361 static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
3362 "mips_newabi registers do not fit into unw_context_t");
3363 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3364 sizeof(_registers));
3365}
3366
3367inline Registers_mips_newabi::Registers_mips_newabi() {
3368 memset(&_registers, 0, sizeof(_registers));
3369}
3370
3371inline bool Registers_mips_newabi::validRegister(int regNum) const {
3372 if (regNum == UNW_REG_IP)
3373 return true;
3374 if (regNum == UNW_REG_SP)
3375 return true;
3376 if (regNum < 0)
3377 return false;
3378 if (regNum <= UNW_MIPS_R31)
3379 return true;
3380#if __mips_isa_rev < 6
3381 if (regNum == UNW_MIPS_HI)
3382 return true;
3383 if (regNum == UNW_MIPS_LO)
3384 return true;
3385#endif
3386 // FIXME: Hard float, DSP accumulator registers, MSA registers
3387 return false;
3388}
3389
3390inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
3391 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
3392 return _registers.__r[regNum - UNW_MIPS_R0];
3393
3394 switch (regNum) {
3395 case UNW_REG_IP:
3396 return _registers.__pc;
3397 case UNW_REG_SP:
3398 return _registers.__r[29];
3399#if __mips_isa_rev < 6
3400 case UNW_MIPS_HI:
3401 return _registers.__hi;
3402 case UNW_MIPS_LO:
3403 return _registers.__lo;
3404#endif
3405 }
3406 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3407}
3408
3409inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
3410 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
3411 _registers.__r[regNum - UNW_MIPS_R0] = value;
3412 return;
3413 }
3414
3415 switch (regNum) {
3416 case UNW_REG_IP:
3417 _registers.__pc = value;
3418 return;
3419 case UNW_REG_SP:
3420 _registers.__r[29] = value;
3421 return;
3422#if __mips_isa_rev < 6
3423 case UNW_MIPS_HI:
3424 _registers.__hi = value;
3425 return;
3426 case UNW_MIPS_LO:
3427 _registers.__lo = value;
3428 return;
3429#endif
3430 }
3431 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3432}
3433
3434inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
3435#ifdef __mips_hard_float
3436 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3437 return true;
3438#else
3439 (void)regNum;
3440#endif
3441 return false;
3442}
3443
3444inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
3445#ifdef __mips_hard_float
3446 assert(validFloatRegister(regNum));
3447 return _floats[regNum - UNW_MIPS_F0];
3448#else
3449 (void)regNum;
3450 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3451#endif
3452}
3453
3454inline void Registers_mips_newabi::setFloatRegister(int regNum,
3455 double value) {
3456#ifdef __mips_hard_float
3457 assert(validFloatRegister(regNum));
3458 _floats[regNum - UNW_MIPS_F0] = value;
3459#else
3460 (void)regNum;
3461 (void)value;
3462 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3463#endif
3464}
3465
3466inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3467 return false;
3468}
3469
3470inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3471 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3472}
3473
3474inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
3475 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3476}
3477
3478inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
3479 switch (regNum) {
3480 case UNW_MIPS_R0:
3481 return "$0";
3482 case UNW_MIPS_R1:
3483 return "$1";
3484 case UNW_MIPS_R2:
3485 return "$2";
3486 case UNW_MIPS_R3:
3487 return "$3";
3488 case UNW_MIPS_R4:
3489 return "$4";
3490 case UNW_MIPS_R5:
3491 return "$5";
3492 case UNW_MIPS_R6:
3493 return "$6";
3494 case UNW_MIPS_R7:
3495 return "$7";
3496 case UNW_MIPS_R8:
3497 return "$8";
3498 case UNW_MIPS_R9:
3499 return "$9";
3500 case UNW_MIPS_R10:
3501 return "$10";
3502 case UNW_MIPS_R11:
3503 return "$11";
3504 case UNW_MIPS_R12:
3505 return "$12";
3506 case UNW_MIPS_R13:
3507 return "$13";
3508 case UNW_MIPS_R14:
3509 return "$14";
3510 case UNW_MIPS_R15:
3511 return "$15";
3512 case UNW_MIPS_R16:
3513 return "$16";
3514 case UNW_MIPS_R17:
3515 return "$17";
3516 case UNW_MIPS_R18:
3517 return "$18";
3518 case UNW_MIPS_R19:
3519 return "$19";
3520 case UNW_MIPS_R20:
3521 return "$20";
3522 case UNW_MIPS_R21:
3523 return "$21";
3524 case UNW_MIPS_R22:
3525 return "$22";
3526 case UNW_MIPS_R23:
3527 return "$23";
3528 case UNW_MIPS_R24:
3529 return "$24";
3530 case UNW_MIPS_R25:
3531 return "$25";
3532 case UNW_MIPS_R26:
3533 return "$26";
3534 case UNW_MIPS_R27:
3535 return "$27";
3536 case UNW_MIPS_R28:
3537 return "$28";
3538 case UNW_MIPS_R29:
3539 return "$29";
3540 case UNW_MIPS_R30:
3541 return "$30";
3542 case UNW_MIPS_R31:
3543 return "$31";
3544 case UNW_MIPS_F0:
3545 return "$f0";
3546 case UNW_MIPS_F1:
3547 return "$f1";
3548 case UNW_MIPS_F2:
3549 return "$f2";
3550 case UNW_MIPS_F3:
3551 return "$f3";
3552 case UNW_MIPS_F4:
3553 return "$f4";
3554 case UNW_MIPS_F5:
3555 return "$f5";
3556 case UNW_MIPS_F6:
3557 return "$f6";
3558 case UNW_MIPS_F7:
3559 return "$f7";
3560 case UNW_MIPS_F8:
3561 return "$f8";
3562 case UNW_MIPS_F9:
3563 return "$f9";
3564 case UNW_MIPS_F10:
3565 return "$f10";
3566 case UNW_MIPS_F11:
3567 return "$f11";
3568 case UNW_MIPS_F12:
3569 return "$f12";
3570 case UNW_MIPS_F13:
3571 return "$f13";
3572 case UNW_MIPS_F14:
3573 return "$f14";
3574 case UNW_MIPS_F15:
3575 return "$f15";
3576 case UNW_MIPS_F16:
3577 return "$f16";
3578 case UNW_MIPS_F17:
3579 return "$f17";
3580 case UNW_MIPS_F18:
3581 return "$f18";
3582 case UNW_MIPS_F19:
3583 return "$f19";
3584 case UNW_MIPS_F20:
3585 return "$f20";
3586 case UNW_MIPS_F21:
3587 return "$f21";
3588 case UNW_MIPS_F22:
3589 return "$f22";
3590 case UNW_MIPS_F23:
3591 return "$f23";
3592 case UNW_MIPS_F24:
3593 return "$f24";
3594 case UNW_MIPS_F25:
3595 return "$f25";
3596 case UNW_MIPS_F26:
3597 return "$f26";
3598 case UNW_MIPS_F27:
3599 return "$f27";
3600 case UNW_MIPS_F28:
3601 return "$f28";
3602 case UNW_MIPS_F29:
3603 return "$f29";
3604 case UNW_MIPS_F30:
3605 return "$f30";
3606 case UNW_MIPS_F31:
3607 return "$f31";
3608#if __mips_isa_rev < 6
3609 case UNW_MIPS_HI:
3610 return "$hi";
3611 case UNW_MIPS_LO:
3612 return "$lo";
3613#endif
3614 default:
3615 return "unknown register";
3616 }
3617}
3618#endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3619
3620#if defined(_LIBUNWIND_TARGET_SPARC)
3621/// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3622/// process.
3623class _LIBUNWIND_HIDDEN Registers_sparc {
3624public:
3625 Registers_sparc();
3626 Registers_sparc(const void *registers);
3627
3628 typedef uint32_t reg_t;
3629 typedef uint32_t link_reg_t;
3630 typedef const link_reg_t &link_hardened_reg_arg_t;
3631
3632 bool validRegister(int num) const;
3633 uint32_t getRegister(int num) const;
3634 void setRegister(int num, uint32_t value);
3635 bool validFloatRegister(int num) const;
3636 double getFloatRegister(int num) const;
3637 void setFloatRegister(int num, double value);
3638 bool validVectorRegister(int num) const;
3639 v128 getVectorRegister(int num) const;
3640 void setVectorRegister(int num, v128 value);
3641 static const char *getRegisterName(int num);
3642 void jumpto();
3643 static constexpr int lastDwarfRegNum() {
3644 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC;
3645 }
3646 static int getArch() { return REGISTERS_SPARC; }
3647
3648 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
3649 void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
3650 uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
3651 void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3652
3653private:
3654 struct sparc_thread_state_t {
3655 unsigned int __regs[32];
3656 };
3657
3658 sparc_thread_state_t _registers;
3659};
3660
3661inline Registers_sparc::Registers_sparc(const void *registers) {
3662 static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
3663 "sparc registers do not fit into unw_context_t");
3664 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3665 sizeof(_registers));
3666}
3667
3668inline Registers_sparc::Registers_sparc() {
3669 memset(&_registers, 0, sizeof(_registers));
3670}
3671
3672inline bool Registers_sparc::validRegister(int regNum) const {
3673 if (regNum == UNW_REG_IP)
3674 return true;
3675 if (regNum == UNW_REG_SP)
3676 return true;
3677 if (regNum < 0)
3678 return false;
3679 if (regNum <= UNW_SPARC_I7)
3680 return true;
3681 return false;
3682}
3683
3684inline uint32_t Registers_sparc::getRegister(int regNum) const {
3685 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3686 return _registers.__regs[regNum];
3687 }
3688
3689 switch (regNum) {
3690 case UNW_REG_IP:
3691 return _registers.__regs[UNW_SPARC_O7];
3692 case UNW_REG_SP:
3693 return _registers.__regs[UNW_SPARC_O6];
3694 }
3695 _LIBUNWIND_ABORT("unsupported sparc register");
3696}
3697
3698inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
3699 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3700 _registers.__regs[regNum] = value;
3701 return;
3702 }
3703
3704 switch (regNum) {
3705 case UNW_REG_IP:
3706 _registers.__regs[UNW_SPARC_O7] = value;
3707 return;
3708 case UNW_REG_SP:
3709 _registers.__regs[UNW_SPARC_O6] = value;
3710 return;
3711 }
3712 _LIBUNWIND_ABORT("unsupported sparc register");
3713}
3714
3715inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3716
3717inline double Registers_sparc::getFloatRegister(int) const {
3718 _LIBUNWIND_ABORT("no sparc float registers");
3719}
3720
3721inline void Registers_sparc::setFloatRegister(int, double) {
3722 _LIBUNWIND_ABORT("no sparc float registers");
3723}
3724
3725inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3726
3727inline v128 Registers_sparc::getVectorRegister(int) const {
3728 _LIBUNWIND_ABORT("no sparc vector registers");
3729}
3730
3731inline void Registers_sparc::setVectorRegister(int, v128) {
3732 _LIBUNWIND_ABORT("no sparc vector registers");
3733}
3734
3735inline const char *Registers_sparc::getRegisterName(int regNum) {
3736 switch (regNum) {
3737 case UNW_REG_IP:
3738 return "pc";
3739 case UNW_SPARC_G0:
3740 return "g0";
3741 case UNW_SPARC_G1:
3742 return "g1";
3743 case UNW_SPARC_G2:
3744 return "g2";
3745 case UNW_SPARC_G3:
3746 return "g3";
3747 case UNW_SPARC_G4:
3748 return "g4";
3749 case UNW_SPARC_G5:
3750 return "g5";
3751 case UNW_SPARC_G6:
3752 return "g6";
3753 case UNW_SPARC_G7:
3754 return "g7";
3755 case UNW_SPARC_O0:
3756 return "o0";
3757 case UNW_SPARC_O1:
3758 return "o1";
3759 case UNW_SPARC_O2:
3760 return "o2";
3761 case UNW_SPARC_O3:
3762 return "o3";
3763 case UNW_SPARC_O4:
3764 return "o4";
3765 case UNW_SPARC_O5:
3766 return "o5";
3767 case UNW_REG_SP:
3768 case UNW_SPARC_O6:
3769 return "sp";
3770 case UNW_SPARC_O7:
3771 return "o7";
3772 case UNW_SPARC_L0:
3773 return "l0";
3774 case UNW_SPARC_L1:
3775 return "l1";
3776 case UNW_SPARC_L2:
3777 return "l2";
3778 case UNW_SPARC_L3:
3779 return "l3";
3780 case UNW_SPARC_L4:
3781 return "l4";
3782 case UNW_SPARC_L5:
3783 return "l5";
3784 case UNW_SPARC_L6:
3785 return "l6";
3786 case UNW_SPARC_L7:
3787 return "l7";
3788 case UNW_SPARC_I0:
3789 return "i0";
3790 case UNW_SPARC_I1:
3791 return "i1";
3792 case UNW_SPARC_I2:
3793 return "i2";
3794 case UNW_SPARC_I3:
3795 return "i3";
3796 case UNW_SPARC_I4:
3797 return "i4";
3798 case UNW_SPARC_I5:
3799 return "i5";
3800 case UNW_SPARC_I6:
3801 return "fp";
3802 case UNW_SPARC_I7:
3803 return "i7";
3804 default:
3805 return "unknown register";
3806 }
3807}
3808#endif // _LIBUNWIND_TARGET_SPARC
3809
3810#if defined(_LIBUNWIND_TARGET_SPARC64)
3811/// Registers_sparc64 holds the register state of a thread in a 64-bit
3812/// sparc process.
3813class _LIBUNWIND_HIDDEN Registers_sparc64 {
3814public:
3815 Registers_sparc64() = default;
3816 Registers_sparc64(const void *registers);
3817
3818 typedef uint64_t reg_t;
3819 typedef uint64_t link_reg_t;
3820 typedef const link_reg_t &link_hardened_reg_arg_t;
3821
3822 bool validRegister(int num) const;
3823 uint64_t getRegister(int num) const;
3824 void setRegister(int num, uint64_t value);
3825 bool validFloatRegister(int num) const;
3826 double getFloatRegister(int num) const;
3827 void setFloatRegister(int num, double value);
3828 bool validVectorRegister(int num) const;
3829 v128 getVectorRegister(int num) const;
3830 void setVectorRegister(int num, v128 value);
3831 const char *getRegisterName(int num);
3832 void jumpto();
3833 static constexpr int lastDwarfRegNum() {
3834 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;
3835 }
3836 static int getArch() { return REGISTERS_SPARC64; }
3837
3838 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; }
3839 void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; }
3840 uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
3841 void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3842 uint64_t getWCookie() const { return _wcookie; }
3843
3844private:
3845 struct sparc64_thread_state_t {
3846 uint64_t __regs[32];
3847 };
3848
3849 sparc64_thread_state_t _registers{};
3850 uint64_t _wcookie = 0;
3851};
3852
3853inline Registers_sparc64::Registers_sparc64(const void *registers) {
3854 static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit),
3855 "sparc64 registers do not fit into unw_context_t");
3856 memcpy(&_registers, registers, sizeof(_registers));
3857 memcpy(&_wcookie,
3858 static_cast<const uint8_t *>(registers) + sizeof(_registers),
3859 sizeof(_wcookie));
3860}
3861
3862inline bool Registers_sparc64::validRegister(int regNum) const {
3863 if (regNum == UNW_REG_IP)
3864 return true;
3865 if (regNum == UNW_REG_SP)
3866 return true;
3867 if (regNum < 0)
3868 return false;
3869 if (regNum <= UNW_SPARC_I7)
3870 return true;
3871 return false;
3872}
3873
3874inline uint64_t Registers_sparc64::getRegister(int regNum) const {
3875 if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7)
3876 return _registers.__regs[regNum];
3877
3878 switch (regNum) {
3879 case UNW_REG_IP:
3880 return _registers.__regs[UNW_SPARC_O7];
3881 case UNW_REG_SP:
3882 return _registers.__regs[UNW_SPARC_O6] + 2047;
3883 }
3884 _LIBUNWIND_ABORT("unsupported sparc64 register");
3885}
3886
3887inline void Registers_sparc64::setRegister(int regNum, uint64_t value) {
3888 if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) {
3889 _registers.__regs[regNum] = value;
3890 return;
3891 }
3892
3893 switch (regNum) {
3894 case UNW_REG_IP:
3895 _registers.__regs[UNW_SPARC_O7] = value;
3896 return;
3897 case UNW_REG_SP:
3898 _registers.__regs[UNW_SPARC_O6] = value - 2047;
3899 return;
3900 }
3901 _LIBUNWIND_ABORT("unsupported sparc64 register");
3902}
3903
3904inline bool Registers_sparc64::validFloatRegister(int) const { return false; }
3905
3906inline double Registers_sparc64::getFloatRegister(int) const {
3907 _LIBUNWIND_ABORT("no sparc64 float registers");
3908}
3909
3910inline void Registers_sparc64::setFloatRegister(int, double) {
3911 _LIBUNWIND_ABORT("no sparc64 float registers");
3912}
3913
3914inline bool Registers_sparc64::validVectorRegister(int) const { return false; }
3915
3916inline v128 Registers_sparc64::getVectorRegister(int) const {
3917 _LIBUNWIND_ABORT("no sparc64 vector registers");
3918}
3919
3920inline void Registers_sparc64::setVectorRegister(int, v128) {
3921 _LIBUNWIND_ABORT("no sparc64 vector registers");
3922}
3923
3924inline const char *Registers_sparc64::getRegisterName(int regNum) {
3925 switch (regNum) {
3926 case UNW_REG_IP:
3927 return "pc";
3928 case UNW_SPARC_G0:
3929 return "g0";
3930 case UNW_SPARC_G1:
3931 return "g1";
3932 case UNW_SPARC_G2:
3933 return "g2";
3934 case UNW_SPARC_G3:
3935 return "g3";
3936 case UNW_SPARC_G4:
3937 return "g4";
3938 case UNW_SPARC_G5:
3939 return "g5";
3940 case UNW_SPARC_G6:
3941 return "g6";
3942 case UNW_SPARC_G7:
3943 return "g7";
3944 case UNW_SPARC_O0:
3945 return "o0";
3946 case UNW_SPARC_O1:
3947 return "o1";
3948 case UNW_SPARC_O2:
3949 return "o2";
3950 case UNW_SPARC_O3:
3951 return "o3";
3952 case UNW_SPARC_O4:
3953 return "o4";
3954 case UNW_SPARC_O5:
3955 return "o5";
3956 case UNW_REG_SP:
3957 case UNW_SPARC_O6:
3958 return "o6";
3959 case UNW_SPARC_O7:
3960 return "o7";
3961 case UNW_SPARC_L0:
3962 return "l0";
3963 case UNW_SPARC_L1:
3964 return "l1";
3965 case UNW_SPARC_L2:
3966 return "l2";
3967 case UNW_SPARC_L3:
3968 return "l3";
3969 case UNW_SPARC_L4:
3970 return "l4";
3971 case UNW_SPARC_L5:
3972 return "l5";
3973 case UNW_SPARC_L6:
3974 return "l6";
3975 case UNW_SPARC_L7:
3976 return "l7";
3977 case UNW_SPARC_I0:
3978 return "i0";
3979 case UNW_SPARC_I1:
3980 return "i1";
3981 case UNW_SPARC_I2:
3982 return "i2";
3983 case UNW_SPARC_I3:
3984 return "i3";
3985 case UNW_SPARC_I4:
3986 return "i4";
3987 case UNW_SPARC_I5:
3988 return "i5";
3989 case UNW_SPARC_I6:
3990 return "i6";
3991 case UNW_SPARC_I7:
3992 return "i7";
3993 default:
3994 return "unknown register";
3995 }
3996}
3997#endif // _LIBUNWIND_TARGET_SPARC64
3998
3999#if defined(_LIBUNWIND_TARGET_HEXAGON)
4000/// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
4001/// process.
4002class _LIBUNWIND_HIDDEN Registers_hexagon {
4003public:
4004 Registers_hexagon();
4005 Registers_hexagon(const void *registers);
4006
4007 typedef uint32_t reg_t;
4008 typedef uint32_t link_reg_t;
4009 typedef const link_reg_t &link_hardened_reg_arg_t;
4010
4011 bool validRegister(int num) const;
4012 uint32_t getRegister(int num) const;
4013 void setRegister(int num, uint32_t value);
4014 bool validFloatRegister(int num) const;
4015 double getFloatRegister(int num) const;
4016 void setFloatRegister(int num, double value);
4017 bool validVectorRegister(int num) const;
4018 v128 getVectorRegister(int num) const;
4019 void setVectorRegister(int num, v128 value);
4020 const char *getRegisterName(int num);
4021 void jumpto();
4022 static constexpr int lastDwarfRegNum() {
4023 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON;
4024 }
4025 static int getArch() { return REGISTERS_HEXAGON; }
4026
4027 uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }
4028 void setSP(uint32_t value) { _registers.__r[UNW_HEXAGON_R29] = value; }
4029 uint32_t getIP() const { return _registers.__r[UNW_HEXAGON_PC]; }
4030 void setIP(uint32_t value) { _registers.__r[UNW_HEXAGON_PC] = value; }
4031
4032private:
4033 struct hexagon_thread_state_t {
4034 unsigned int __r[35];
4035 };
4036
4037 hexagon_thread_state_t _registers;
4038};
4039
4040inline Registers_hexagon::Registers_hexagon(const void *registers) {
4041 static_assert((check_fit<Registers_hexagon, unw_context_t>::does_fit),
4042 "hexagon registers do not fit into unw_context_t");
4043 memcpy(&_registers, static_cast<const uint8_t *>(registers),
4044 sizeof(_registers));
4045}
4046
4047inline Registers_hexagon::Registers_hexagon() {
4048 memset(&_registers, 0, sizeof(_registers));
4049}
4050
4051inline bool Registers_hexagon::validRegister(int regNum) const {
4052 if (regNum <= UNW_HEXAGON_R31)
4053 return true;
4054 return false;
4055}
4056
4057inline uint32_t Registers_hexagon::getRegister(int regNum) const {
4058 if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31)
4059 return _registers.__r[regNum - UNW_HEXAGON_R0];
4060
4061 switch (regNum) {
4062 case UNW_REG_IP:
4063 return _registers.__r[UNW_HEXAGON_PC];
4064 case UNW_REG_SP:
4065 return _registers.__r[UNW_HEXAGON_R29];
4066 }
4067 _LIBUNWIND_ABORT("unsupported hexagon register");
4068}
4069
4070inline void Registers_hexagon::setRegister(int regNum, uint32_t value) {
4071 if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) {
4072 _registers.__r[regNum - UNW_HEXAGON_R0] = value;
4073 return;
4074 }
4075
4076 switch (regNum) {
4077 case UNW_REG_IP:
4078 _registers.__r[UNW_HEXAGON_PC] = value;
4079 return;
4080 case UNW_REG_SP:
4081 _registers.__r[UNW_HEXAGON_R29] = value;
4082 return;
4083 }
4084 _LIBUNWIND_ABORT("unsupported hexagon register");
4085}
4086
4087inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {
4088 return false;
4089}
4090
4091inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {
4092 _LIBUNWIND_ABORT("hexagon float support not implemented");
4093}
4094
4095inline void Registers_hexagon::setFloatRegister(int /* regNum */,
4096 double /* value */) {
4097 _LIBUNWIND_ABORT("hexagon float support not implemented");
4098}
4099
4100inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {
4101 return false;
4102}
4103
4104inline v128 Registers_hexagon::getVectorRegister(int /* regNum */) const {
4105 _LIBUNWIND_ABORT("hexagon vector support not implemented");
4106}
4107
4108inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128 /* value */) {
4109 _LIBUNWIND_ABORT("hexagon vector support not implemented");
4110}
4111
4112inline const char *Registers_hexagon::getRegisterName(int regNum) {
4113 switch (regNum) {
4114 case UNW_HEXAGON_R0:
4115 return "r0";
4116 case UNW_HEXAGON_R1:
4117 return "r1";
4118 case UNW_HEXAGON_R2:
4119 return "r2";
4120 case UNW_HEXAGON_R3:
4121 return "r3";
4122 case UNW_HEXAGON_R4:
4123 return "r4";
4124 case UNW_HEXAGON_R5:
4125 return "r5";
4126 case UNW_HEXAGON_R6:
4127 return "r6";
4128 case UNW_HEXAGON_R7:
4129 return "r7";
4130 case UNW_HEXAGON_R8:
4131 return "r8";
4132 case UNW_HEXAGON_R9:
4133 return "r9";
4134 case UNW_HEXAGON_R10:
4135 return "r10";
4136 case UNW_HEXAGON_R11:
4137 return "r11";
4138 case UNW_HEXAGON_R12:
4139 return "r12";
4140 case UNW_HEXAGON_R13:
4141 return "r13";
4142 case UNW_HEXAGON_R14:
4143 return "r14";
4144 case UNW_HEXAGON_R15:
4145 return "r15";
4146 case UNW_HEXAGON_R16:
4147 return "r16";
4148 case UNW_HEXAGON_R17:
4149 return "r17";
4150 case UNW_HEXAGON_R18:
4151 return "r18";
4152 case UNW_HEXAGON_R19:
4153 return "r19";
4154 case UNW_HEXAGON_R20:
4155 return "r20";
4156 case UNW_HEXAGON_R21:
4157 return "r21";
4158 case UNW_HEXAGON_R22:
4159 return "r22";
4160 case UNW_HEXAGON_R23:
4161 return "r23";
4162 case UNW_HEXAGON_R24:
4163 return "r24";
4164 case UNW_HEXAGON_R25:
4165 return "r25";
4166 case UNW_HEXAGON_R26:
4167 return "r26";
4168 case UNW_HEXAGON_R27:
4169 return "r27";
4170 case UNW_HEXAGON_R28:
4171 return "r28";
4172 case UNW_HEXAGON_R29:
4173 return "r29";
4174 case UNW_HEXAGON_R30:
4175 return "r30";
4176 case UNW_HEXAGON_R31:
4177 return "r31";
4178 default:
4179 return "unknown register";
4180 }
4181
4182}
4183#endif // _LIBUNWIND_TARGET_HEXAGON
4184
4185
4186#if defined(_LIBUNWIND_TARGET_RISCV)
4187/// Registers_riscv holds the register state of a thread in a RISC-V
4188/// process.
4189
4190// This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.
4191# ifdef __riscv
4192# if __riscv_xlen == 32
4193typedef uint32_t reg_t;
4194# elif __riscv_xlen == 64
4195typedef uint64_t reg_t;
4196# else
4197# error "Unsupported __riscv_xlen"
4198# endif
4199
4200# if defined(__riscv_flen)
4201# if __riscv_flen == 64
4202typedef double fp_t;
4203# elif __riscv_flen == 32
4204typedef float fp_t;
4205# else
4206# error "Unsupported __riscv_flen"
4207# endif
4208# else
4209// This is just for suppressing undeclared error of fp_t.
4210typedef double fp_t;
4211# endif
4212# else
4213// Use Max possible width when cross unwinding
4214typedef uint64_t reg_t;
4215typedef double fp_t;
4216# define __riscv_xlen 64
4217# define __riscv_flen 64
4218#endif
4219
4220/// Registers_riscv holds the register state of a thread.
4221class _LIBUNWIND_HIDDEN Registers_riscv {
4222public:
4223 Registers_riscv();
4224 Registers_riscv(const void *registers);
4225
4226 typedef ::libunwind::reg_t reg_t;
4227 typedef ::libunwind::reg_t link_reg_t;
4228 typedef const link_reg_t &link_hardened_reg_arg_t;
4229
4230 bool validRegister(int num) const;
4231 reg_t getRegister(int num) const;
4232 void setRegister(int num, reg_t value);
4233 bool validFloatRegister(int num) const;
4234 fp_t getFloatRegister(int num) const;
4235 void setFloatRegister(int num, fp_t value);
4236 bool validVectorRegister(int num) const;
4237 v128 getVectorRegister(int num) const;
4238 void setVectorRegister(int num, v128 value);
4239 static const char *getRegisterName(int num);
4240 void jumpto();
4241 static constexpr int lastDwarfRegNum() {
4242 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV;
4243 }
4244 static int getArch() { return REGISTERS_RISCV; }
4245
4246 reg_t getSP() const { return _registers[2]; }
4247 void setSP(reg_t value) { _registers[2] = value; }
4248 reg_t getIP() const { return _registers[0]; }
4249 void setIP(reg_t value) { _registers[0] = value; }
4250
4251private:
4252 // _registers[0] holds the pc
4253 reg_t _registers[32];
4254# if defined(__riscv_flen)
4255 fp_t _floats[32];
4256# endif
4257};
4258
4259inline Registers_riscv::Registers_riscv(const void *registers) {
4260 static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit),
4261 "riscv registers do not fit into unw_context_t");
4262 memcpy(&_registers, registers, sizeof(_registers));
4263# if __riscv_xlen == 32
4264 static_assert(sizeof(_registers) == 0x80,
4265 "expected float registers to be at offset 128");
4266# elif __riscv_xlen == 64
4267 static_assert(sizeof(_registers) == 0x100,
4268 "expected float registers to be at offset 256");
4269# else
4270# error "Unexpected float registers."
4271# endif
4272
4273# if defined(__riscv_flen)
4274 memcpy(_floats,
4275 static_cast<const uint8_t *>(registers) + sizeof(_registers),
4276 sizeof(_floats));
4277# endif
4278}
4279
4280inline Registers_riscv::Registers_riscv() {
4281 memset(&_registers, 0, sizeof(_registers));
4282# if defined(__riscv_flen)
4283 memset(&_floats, 0, sizeof(_floats));
4284# endif
4285}
4286
4287inline bool Registers_riscv::validRegister(int regNum) const {
4288 if (regNum == UNW_REG_IP)
4289 return true;
4290 if (regNum == UNW_REG_SP)
4291 return true;
4292 if (regNum < 0)
4293 return false;
4294 if (regNum == UNW_RISCV_VLENB)
4295 return true;
4296 if (regNum > UNW_RISCV_F31)
4297 return false;
4298 return true;
4299}
4300
4301inline reg_t Registers_riscv::getRegister(int regNum) const {
4302 if (regNum == UNW_REG_IP)
4303 return _registers[0];
4304 if (regNum == UNW_REG_SP)
4305 return _registers[2];
4306 if (regNum == UNW_RISCV_X0)
4307 return 0;
4308 if ((regNum > 0) && (regNum < 32))
4309 return _registers[regNum];
4310 if (regNum == UNW_RISCV_VLENB) {
4311 reg_t vlenb;
4312 __asm__ volatile("csrr %0, 0xC22" : "=r"(vlenb));
4313 return vlenb;
4314 }
4315 _LIBUNWIND_ABORT("unsupported riscv register");
4316}
4317
4318inline void Registers_riscv::setRegister(int regNum, reg_t value) {
4319 if (regNum == UNW_REG_IP)
4320 _registers[0] = value;
4321 else if (regNum == UNW_REG_SP)
4322 _registers[2] = value;
4323 else if (regNum == UNW_RISCV_X0)
4324 /* x0 is hardwired to zero */
4325 return;
4326 else if ((regNum > 0) && (regNum < 32))
4327 _registers[regNum] = value;
4328 else
4329 _LIBUNWIND_ABORT("unsupported riscv register");
4330}
4331
4332inline const char *Registers_riscv::getRegisterName(int regNum) {
4333 switch (regNum) {
4334 case UNW_REG_IP:
4335 return "pc";
4336 case UNW_REG_SP:
4337 return "sp";
4338 case UNW_RISCV_X0:
4339 return "zero";
4340 case UNW_RISCV_X1:
4341 return "ra";
4342 case UNW_RISCV_X2:
4343 return "sp";
4344 case UNW_RISCV_X3:
4345 return "gp";
4346 case UNW_RISCV_X4:
4347 return "tp";
4348 case UNW_RISCV_X5:
4349 return "t0";
4350 case UNW_RISCV_X6:
4351 return "t1";
4352 case UNW_RISCV_X7:
4353 return "t2";
4354 case UNW_RISCV_X8:
4355 return "s0";
4356 case UNW_RISCV_X9:
4357 return "s1";
4358 case UNW_RISCV_X10:
4359 return "a0";
4360 case UNW_RISCV_X11:
4361 return "a1";
4362 case UNW_RISCV_X12:
4363 return "a2";
4364 case UNW_RISCV_X13:
4365 return "a3";
4366 case UNW_RISCV_X14:
4367 return "a4";
4368 case UNW_RISCV_X15:
4369 return "a5";
4370 case UNW_RISCV_X16:
4371 return "a6";
4372 case UNW_RISCV_X17:
4373 return "a7";
4374 case UNW_RISCV_X18:
4375 return "s2";
4376 case UNW_RISCV_X19:
4377 return "s3";
4378 case UNW_RISCV_X20:
4379 return "s4";
4380 case UNW_RISCV_X21:
4381 return "s5";
4382 case UNW_RISCV_X22:
4383 return "s6";
4384 case UNW_RISCV_X23:
4385 return "s7";
4386 case UNW_RISCV_X24:
4387 return "s8";
4388 case UNW_RISCV_X25:
4389 return "s9";
4390 case UNW_RISCV_X26:
4391 return "s10";
4392 case UNW_RISCV_X27:
4393 return "s11";
4394 case UNW_RISCV_X28:
4395 return "t3";
4396 case UNW_RISCV_X29:
4397 return "t4";
4398 case UNW_RISCV_X30:
4399 return "t5";
4400 case UNW_RISCV_X31:
4401 return "t6";
4402 case UNW_RISCV_F0:
4403 return "ft0";
4404 case UNW_RISCV_F1:
4405 return "ft1";
4406 case UNW_RISCV_F2:
4407 return "ft2";
4408 case UNW_RISCV_F3:
4409 return "ft3";
4410 case UNW_RISCV_F4:
4411 return "ft4";
4412 case UNW_RISCV_F5:
4413 return "ft5";
4414 case UNW_RISCV_F6:
4415 return "ft6";
4416 case UNW_RISCV_F7:
4417 return "ft7";
4418 case UNW_RISCV_F8:
4419 return "fs0";
4420 case UNW_RISCV_F9:
4421 return "fs1";
4422 case UNW_RISCV_F10:
4423 return "fa0";
4424 case UNW_RISCV_F11:
4425 return "fa1";
4426 case UNW_RISCV_F12:
4427 return "fa2";
4428 case UNW_RISCV_F13:
4429 return "fa3";
4430 case UNW_RISCV_F14:
4431 return "fa4";
4432 case UNW_RISCV_F15:
4433 return "fa5";
4434 case UNW_RISCV_F16:
4435 return "fa6";
4436 case UNW_RISCV_F17:
4437 return "fa7";
4438 case UNW_RISCV_F18:
4439 return "fs2";
4440 case UNW_RISCV_F19:
4441 return "fs3";
4442 case UNW_RISCV_F20:
4443 return "fs4";
4444 case UNW_RISCV_F21:
4445 return "fs5";
4446 case UNW_RISCV_F22:
4447 return "fs6";
4448 case UNW_RISCV_F23:
4449 return "fs7";
4450 case UNW_RISCV_F24:
4451 return "fs8";
4452 case UNW_RISCV_F25:
4453 return "fs9";
4454 case UNW_RISCV_F26:
4455 return "fs10";
4456 case UNW_RISCV_F27:
4457 return "fs11";
4458 case UNW_RISCV_F28:
4459 return "ft8";
4460 case UNW_RISCV_F29:
4461 return "ft9";
4462 case UNW_RISCV_F30:
4463 return "ft10";
4464 case UNW_RISCV_F31:
4465 return "ft11";
4466 case UNW_RISCV_VLENB:
4467 return "vlenb";
4468 default:
4469 return "unknown register";
4470 }
4471}
4472
4473inline bool Registers_riscv::validFloatRegister(int regNum) const {
4474# if defined(__riscv_flen)
4475 if (regNum < UNW_RISCV_F0)
4476 return false;
4477 if (regNum > UNW_RISCV_F31)
4478 return false;
4479 return true;
4480# else
4481 (void)regNum;
4482 return false;
4483# endif
4484}
4485
4486inline fp_t Registers_riscv::getFloatRegister(int regNum) const {
4487# if defined(__riscv_flen)
4488 assert(validFloatRegister(regNum));
4489 return _floats[regNum - UNW_RISCV_F0];
4490# else
4491 (void)regNum;
4492 _LIBUNWIND_ABORT("libunwind not built with float support");
4493# endif
4494}
4495
4496inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) {
4497# if defined(__riscv_flen)
4498 assert(validFloatRegister(regNum));
4499 _floats[regNum - UNW_RISCV_F0] = value;
4500# else
4501 (void)regNum;
4502 (void)value;
4503 _LIBUNWIND_ABORT("libunwind not built with float support");
4504# endif
4505}
4506
4507inline bool Registers_riscv::validVectorRegister(int) const {
4508 return false;
4509}
4510
4511inline v128 Registers_riscv::getVectorRegister(int) const {
4512 _LIBUNWIND_ABORT("no riscv vector register support yet");
4513}
4514
4515inline void Registers_riscv::setVectorRegister(int, v128) {
4516 _LIBUNWIND_ABORT("no riscv vector register support yet");
4517}
4518#endif // _LIBUNWIND_TARGET_RISCV
4519
4520#if defined(_LIBUNWIND_TARGET_VE)
4521/// Registers_ve holds the register state of a thread in a VE process.
4522class _LIBUNWIND_HIDDEN Registers_ve {
4523public:
4524 Registers_ve();
4525 Registers_ve(const void *registers);
4526
4527 typedef uint64_t reg_t;
4528 typedef uint64_t link_reg_t;
4529 typedef const link_reg_t &link_hardened_reg_arg_t;
4530
4531 bool validRegister(int num) const;
4532 uint64_t getRegister(int num) const;
4533 void setRegister(int num, uint64_t value);
4534 bool validFloatRegister(int num) const;
4535 double getFloatRegister(int num) const;
4536 void setFloatRegister(int num, double value);
4537 bool validVectorRegister(int num) const;
4538 v128 getVectorRegister(int num) const;
4539 void setVectorRegister(int num, v128 value);
4540 static const char *getRegisterName(int num);
4541 void jumpto();
4542 static constexpr int lastDwarfRegNum() {
4543 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE;
4544 }
4545 static int getArch() { return REGISTERS_VE; }
4546
4547 uint64_t getSP() const { return _registers.__s[11]; }
4548 void setSP(uint64_t value) { _registers.__s[11] = value; }
4549 uint64_t getIP() const { return _registers.__ic; }
4550 void setIP(uint64_t value) { _registers.__ic = value; }
4551
4552private:
4553 // FIXME: Need to store not only scalar registers but also vector and vector
4554 // mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes
4555 // 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for
4556 // SjLj exception support only, so Registers_ve is not implemented completely.
4557 struct ve_thread_state_t {
4558 uint64_t __s[64]; // s0-s64
4559 uint64_t __ic; // Instruction counter (IC)
4560 uint64_t __vixr; // Vector Index Register
4561 uint64_t __vl; // Vector Length Register
4562 };
4563
4564 ve_thread_state_t _registers; // total 67 registers
4565
4566 // Currently no vector register is preserved.
4567};
4568
4569inline Registers_ve::Registers_ve(const void *registers) {
4570 static_assert((check_fit<Registers_ve, unw_context_t>::does_fit),
4571 "ve registers do not fit into unw_context_t");
4572 memcpy(&_registers, static_cast<const uint8_t *>(registers),
4573 sizeof(_registers));
4574 static_assert(sizeof(_registers) == 536,
4575 "expected vector register offset to be 536");
4576}
4577
4578inline Registers_ve::Registers_ve() {
4579 memset(&_registers, 0, sizeof(_registers));
4580}
4581
4582inline bool Registers_ve::validRegister(int regNum) const {
4583 if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
4584 return true;
4585
4586 switch (regNum) {
4587 case UNW_REG_IP:
4588 case UNW_REG_SP:
4589 case UNW_VE_VIXR:
4590 case UNW_VE_VL:
4591 return true;
4592 default:
4593 return false;
4594 }
4595}
4596
4597inline uint64_t Registers_ve::getRegister(int regNum) const {
4598 if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
4599 return _registers.__s[regNum - UNW_VE_S0];
4600
4601 switch (regNum) {
4602 case UNW_REG_IP:
4603 return _registers.__ic;
4604 case UNW_REG_SP:
4605 return _registers.__s[11];
4606 case UNW_VE_VIXR:
4607 return _registers.__vixr;
4608 case UNW_VE_VL:
4609 return _registers.__vl;
4610 }
4611 _LIBUNWIND_ABORT("unsupported ve register");
4612}
4613
4614inline void Registers_ve::setRegister(int regNum, uint64_t value) {
4615 if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) {
4616 _registers.__s[regNum - UNW_VE_S0] = value;
4617 return;
4618 }
4619
4620 switch (regNum) {
4621 case UNW_REG_IP:
4622 _registers.__ic = value;
4623 return;
4624 case UNW_REG_SP:
4625 _registers.__s[11] = value;
4626 return;
4627 case UNW_VE_VIXR:
4628 _registers.__vixr = value;
4629 return;
4630 case UNW_VE_VL:
4631 _registers.__vl = value;
4632 return;
4633 }
4634 _LIBUNWIND_ABORT("unsupported ve register");
4635}
4636
4637inline bool Registers_ve::validFloatRegister(int /* regNum */) const {
4638 return false;
4639}
4640
4641inline double Registers_ve::getFloatRegister(int /* regNum */) const {
4642 _LIBUNWIND_ABORT("VE doesn't have float registers");
4643}
4644
4645inline void Registers_ve::setFloatRegister(int /* regNum */,
4646 double /* value */) {
4647 _LIBUNWIND_ABORT("VE doesn't have float registers");
4648}
4649
4650inline bool Registers_ve::validVectorRegister(int /* regNum */) const {
4651 return false;
4652}
4653
4654inline v128 Registers_ve::getVectorRegister(int /* regNum */) const {
4655 _LIBUNWIND_ABORT("VE vector support not implemented");
4656}
4657
4658inline void Registers_ve::setVectorRegister(int /* regNum */,
4659 v128 /* value */) {
4660 _LIBUNWIND_ABORT("VE vector support not implemented");
4661}
4662
4663inline const char *Registers_ve::getRegisterName(int regNum) {
4664 switch (regNum) {
4665 case UNW_REG_IP:
4666 return "ip";
4667 case UNW_REG_SP:
4668 return "sp";
4669 case UNW_VE_VIXR:
4670 return "vixr";
4671 case UNW_VE_VL:
4672 return "vl";
4673 case UNW_VE_S0:
4674 return "s0";
4675 case UNW_VE_S1:
4676 return "s1";
4677 case UNW_VE_S2:
4678 return "s2";
4679 case UNW_VE_S3:
4680 return "s3";
4681 case UNW_VE_S4:
4682 return "s4";
4683 case UNW_VE_S5:
4684 return "s5";
4685 case UNW_VE_S6:
4686 return "s6";
4687 case UNW_VE_S7:
4688 return "s7";
4689 case UNW_VE_S8:
4690 return "s8";
4691 case UNW_VE_S9:
4692 return "s9";
4693 case UNW_VE_S10:
4694 return "s10";
4695 case UNW_VE_S11:
4696 return "s11";
4697 case UNW_VE_S12:
4698 return "s12";
4699 case UNW_VE_S13:
4700 return "s13";
4701 case UNW_VE_S14:
4702 return "s14";
4703 case UNW_VE_S15:
4704 return "s15";
4705 case UNW_VE_S16:
4706 return "s16";
4707 case UNW_VE_S17:
4708 return "s17";
4709 case UNW_VE_S18:
4710 return "s18";
4711 case UNW_VE_S19:
4712 return "s19";
4713 case UNW_VE_S20:
4714 return "s20";
4715 case UNW_VE_S21:
4716 return "s21";
4717 case UNW_VE_S22:
4718 return "s22";
4719 case UNW_VE_S23:
4720 return "s23";
4721 case UNW_VE_S24:
4722 return "s24";
4723 case UNW_VE_S25:
4724 return "s25";
4725 case UNW_VE_S26:
4726 return "s26";
4727 case UNW_VE_S27:
4728 return "s27";
4729 case UNW_VE_S28:
4730 return "s28";
4731 case UNW_VE_S29:
4732 return "s29";
4733 case UNW_VE_S30:
4734 return "s30";
4735 case UNW_VE_S31:
4736 return "s31";
4737 case UNW_VE_S32:
4738 return "s32";
4739 case UNW_VE_S33:
4740 return "s33";
4741 case UNW_VE_S34:
4742 return "s34";
4743 case UNW_VE_S35:
4744 return "s35";
4745 case UNW_VE_S36:
4746 return "s36";
4747 case UNW_VE_S37:
4748 return "s37";
4749 case UNW_VE_S38:
4750 return "s38";
4751 case UNW_VE_S39:
4752 return "s39";
4753 case UNW_VE_S40:
4754 return "s40";
4755 case UNW_VE_S41:
4756 return "s41";
4757 case UNW_VE_S42:
4758 return "s42";
4759 case UNW_VE_S43:
4760 return "s43";
4761 case UNW_VE_S44:
4762 return "s44";
4763 case UNW_VE_S45:
4764 return "s45";
4765 case UNW_VE_S46:
4766 return "s46";
4767 case UNW_VE_S47:
4768 return "s47";
4769 case UNW_VE_S48:
4770 return "s48";
4771 case UNW_VE_S49:
4772 return "s49";
4773 case UNW_VE_S50:
4774 return "s50";
4775 case UNW_VE_S51:
4776 return "s51";
4777 case UNW_VE_S52:
4778 return "s52";
4779 case UNW_VE_S53:
4780 return "s53";
4781 case UNW_VE_S54:
4782 return "s54";
4783 case UNW_VE_S55:
4784 return "s55";
4785 case UNW_VE_S56:
4786 return "s56";
4787 case UNW_VE_S57:
4788 return "s57";
4789 case UNW_VE_S58:
4790 return "s58";
4791 case UNW_VE_S59:
4792 return "s59";
4793 case UNW_VE_S60:
4794 return "s60";
4795 case UNW_VE_S61:
4796 return "s61";
4797 case UNW_VE_S62:
4798 return "s62";
4799 case UNW_VE_S63:
4800 return "s63";
4801 case UNW_VE_V0:
4802 return "v0";
4803 case UNW_VE_V1:
4804 return "v1";
4805 case UNW_VE_V2:
4806 return "v2";
4807 case UNW_VE_V3:
4808 return "v3";
4809 case UNW_VE_V4:
4810 return "v4";
4811 case UNW_VE_V5:
4812 return "v5";
4813 case UNW_VE_V6:
4814 return "v6";
4815 case UNW_VE_V7:
4816 return "v7";
4817 case UNW_VE_V8:
4818 return "v8";
4819 case UNW_VE_V9:
4820 return "v9";
4821 case UNW_VE_V10:
4822 return "v10";
4823 case UNW_VE_V11:
4824 return "v11";
4825 case UNW_VE_V12:
4826 return "v12";
4827 case UNW_VE_V13:
4828 return "v13";
4829 case UNW_VE_V14:
4830 return "v14";
4831 case UNW_VE_V15:
4832 return "v15";
4833 case UNW_VE_V16:
4834 return "v16";
4835 case UNW_VE_V17:
4836 return "v17";
4837 case UNW_VE_V18:
4838 return "v18";
4839 case UNW_VE_V19:
4840 return "v19";
4841 case UNW_VE_V20:
4842 return "v20";
4843 case UNW_VE_V21:
4844 return "v21";
4845 case UNW_VE_V22:
4846 return "v22";
4847 case UNW_VE_V23:
4848 return "v23";
4849 case UNW_VE_V24:
4850 return "v24";
4851 case UNW_VE_V25:
4852 return "v25";
4853 case UNW_VE_V26:
4854 return "v26";
4855 case UNW_VE_V27:
4856 return "v27";
4857 case UNW_VE_V28:
4858 return "v28";
4859 case UNW_VE_V29:
4860 return "v29";
4861 case UNW_VE_V30:
4862 return "v30";
4863 case UNW_VE_V31:
4864 return "v31";
4865 case UNW_VE_V32:
4866 return "v32";
4867 case UNW_VE_V33:
4868 return "v33";
4869 case UNW_VE_V34:
4870 return "v34";
4871 case UNW_VE_V35:
4872 return "v35";
4873 case UNW_VE_V36:
4874 return "v36";
4875 case UNW_VE_V37:
4876 return "v37";
4877 case UNW_VE_V38:
4878 return "v38";
4879 case UNW_VE_V39:
4880 return "v39";
4881 case UNW_VE_V40:
4882 return "v40";
4883 case UNW_VE_V41:
4884 return "v41";
4885 case UNW_VE_V42:
4886 return "v42";
4887 case UNW_VE_V43:
4888 return "v43";
4889 case UNW_VE_V44:
4890 return "v44";
4891 case UNW_VE_V45:
4892 return "v45";
4893 case UNW_VE_V46:
4894 return "v46";
4895 case UNW_VE_V47:
4896 return "v47";
4897 case UNW_VE_V48:
4898 return "v48";
4899 case UNW_VE_V49:
4900 return "v49";
4901 case UNW_VE_V50:
4902 return "v50";
4903 case UNW_VE_V51:
4904 return "v51";
4905 case UNW_VE_V52:
4906 return "v52";
4907 case UNW_VE_V53:
4908 return "v53";
4909 case UNW_VE_V54:
4910 return "v54";
4911 case UNW_VE_V55:
4912 return "v55";
4913 case UNW_VE_V56:
4914 return "v56";
4915 case UNW_VE_V57:
4916 return "v57";
4917 case UNW_VE_V58:
4918 return "v58";
4919 case UNW_VE_V59:
4920 return "v59";
4921 case UNW_VE_V60:
4922 return "v60";
4923 case UNW_VE_V61:
4924 return "v61";
4925 case UNW_VE_V62:
4926 return "v62";
4927 case UNW_VE_V63:
4928 return "v63";
4929 case UNW_VE_VM0:
4930 return "vm0";
4931 case UNW_VE_VM1:
4932 return "vm1";
4933 case UNW_VE_VM2:
4934 return "vm2";
4935 case UNW_VE_VM3:
4936 return "vm3";
4937 case UNW_VE_VM4:
4938 return "vm4";
4939 case UNW_VE_VM5:
4940 return "vm5";
4941 case UNW_VE_VM6:
4942 return "vm6";
4943 case UNW_VE_VM7:
4944 return "vm7";
4945 case UNW_VE_VM8:
4946 return "vm8";
4947 case UNW_VE_VM9:
4948 return "vm9";
4949 case UNW_VE_VM10:
4950 return "vm10";
4951 case UNW_VE_VM11:
4952 return "vm11";
4953 case UNW_VE_VM12:
4954 return "vm12";
4955 case UNW_VE_VM13:
4956 return "vm13";
4957 case UNW_VE_VM14:
4958 return "vm14";
4959 case UNW_VE_VM15:
4960 return "vm15";
4961 }
4962 return "unknown register";
4963}
4964#endif // _LIBUNWIND_TARGET_VE
4965
4966#if defined(_LIBUNWIND_TARGET_S390X)
4967/// Registers_s390x holds the register state of a thread in a
4968/// 64-bit Linux on IBM zSystems process.
4969class _LIBUNWIND_HIDDEN Registers_s390x {
4970public:
4971 Registers_s390x();
4972 Registers_s390x(const void *registers);
4973
4974 typedef uint64_t reg_t;
4975 typedef uint64_t link_reg_t;
4976 typedef const link_reg_t &link_hardened_reg_arg_t;
4977
4978 bool validRegister(int num) const;
4979 uint64_t getRegister(int num) const;
4980 void setRegister(int num, uint64_t value);
4981 bool validFloatRegister(int num) const;
4982 double getFloatRegister(int num) const;
4983 void setFloatRegister(int num, double value);
4984 bool validVectorRegister(int num) const;
4985 v128 getVectorRegister(int num) const;
4986 void setVectorRegister(int num, v128 value);
4987 static const char *getRegisterName(int num);
4988 void jumpto();
4989 static constexpr int lastDwarfRegNum() {
4990 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X;
4991 }
4992 static int getArch() { return REGISTERS_S390X; }
4993
4994 uint64_t getSP() const { return _registers.__gpr[15]; }
4995 void setSP(uint64_t value) { _registers.__gpr[15] = value; }
4996 uint64_t getIP() const { return _registers.__pswa; }
4997 void setIP(uint64_t value) { _registers.__pswa = value; }
4998
4999private:
5000 struct s390x_thread_state_t {
5001 uint64_t __pswm; // Problem Status Word: Mask
5002 uint64_t __pswa; // Problem Status Word: Address (PC)
5003 uint64_t __gpr[16]; // General Purpose Registers
5004 double __fpr[16]; // Floating-Point Registers
5005 };
5006
5007 s390x_thread_state_t _registers;
5008};
5009
5010inline Registers_s390x::Registers_s390x(const void *registers) {
5011 static_assert((check_fit<Registers_s390x, unw_context_t>::does_fit),
5012 "s390x registers do not fit into unw_context_t");
5013 memcpy(&_registers, static_cast<const uint8_t *>(registers),
5014 sizeof(_registers));
5015}
5016
5017inline Registers_s390x::Registers_s390x() {
5018 memset(&_registers, 0, sizeof(_registers));
5019}
5020
5021inline bool Registers_s390x::validRegister(int regNum) const {
5022 switch (regNum) {
5023 case UNW_S390X_PSWM:
5024 case UNW_S390X_PSWA:
5025 case UNW_REG_IP:
5026 case UNW_REG_SP:
5027 return true;
5028 }
5029
5030 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
5031 return true;
5032
5033 return false;
5034}
5035
5036inline uint64_t Registers_s390x::getRegister(int regNum) const {
5037 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
5038 return _registers.__gpr[regNum - UNW_S390X_R0];
5039
5040 switch (regNum) {
5041 case UNW_S390X_PSWM:
5042 return _registers.__pswm;
5043 case UNW_S390X_PSWA:
5044 case UNW_REG_IP:
5045 return _registers.__pswa;
5046 case UNW_REG_SP:
5047 return _registers.__gpr[15];
5048 }
5049 _LIBUNWIND_ABORT("unsupported s390x register");
5050}
5051
5052inline void Registers_s390x::setRegister(int regNum, uint64_t value) {
5053 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) {
5054 _registers.__gpr[regNum - UNW_S390X_R0] = value;
5055 return;
5056 }
5057
5058 switch (regNum) {
5059 case UNW_S390X_PSWM:
5060 _registers.__pswm = value;
5061 return;
5062 case UNW_S390X_PSWA:
5063 case UNW_REG_IP:
5064 _registers.__pswa = value;
5065 return;
5066 case UNW_REG_SP:
5067 _registers.__gpr[15] = value;
5068 return;
5069 }
5070 _LIBUNWIND_ABORT("unsupported s390x register");
5071}
5072
5073inline bool Registers_s390x::validFloatRegister(int regNum) const {
5074 return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15;
5075}
5076
5077inline double Registers_s390x::getFloatRegister(int regNum) const {
5078 // NOTE: FPR DWARF register numbers are not consecutive.
5079 switch (regNum) {
5080 case UNW_S390X_F0:
5081 return _registers.__fpr[0];
5082 case UNW_S390X_F1:
5083 return _registers.__fpr[1];
5084 case UNW_S390X_F2:
5085 return _registers.__fpr[2];
5086 case UNW_S390X_F3:
5087 return _registers.__fpr[3];
5088 case UNW_S390X_F4:
5089 return _registers.__fpr[4];
5090 case UNW_S390X_F5:
5091 return _registers.__fpr[5];
5092 case UNW_S390X_F6:
5093 return _registers.__fpr[6];
5094 case UNW_S390X_F7:
5095 return _registers.__fpr[7];
5096 case UNW_S390X_F8:
5097 return _registers.__fpr[8];
5098 case UNW_S390X_F9:
5099 return _registers.__fpr[9];
5100 case UNW_S390X_F10:
5101 return _registers.__fpr[10];
5102 case UNW_S390X_F11:
5103 return _registers.__fpr[11];
5104 case UNW_S390X_F12:
5105 return _registers.__fpr[12];
5106 case UNW_S390X_F13:
5107 return _registers.__fpr[13];
5108 case UNW_S390X_F14:
5109 return _registers.__fpr[14];
5110 case UNW_S390X_F15:
5111 return _registers.__fpr[15];
5112 }
5113 _LIBUNWIND_ABORT("unsupported s390x register");
5114}
5115
5116inline void Registers_s390x::setFloatRegister(int regNum, double value) {
5117 // NOTE: FPR DWARF register numbers are not consecutive.
5118 switch (regNum) {
5119 case UNW_S390X_F0:
5120 _registers.__fpr[0] = value;
5121 return;
5122 case UNW_S390X_F1:
5123 _registers.__fpr[1] = value;
5124 return;
5125 case UNW_S390X_F2:
5126 _registers.__fpr[2] = value;
5127 return;
5128 case UNW_S390X_F3:
5129 _registers.__fpr[3] = value;
5130 return;
5131 case UNW_S390X_F4:
5132 _registers.__fpr[4] = value;
5133 return;
5134 case UNW_S390X_F5:
5135 _registers.__fpr[5] = value;
5136 return;
5137 case UNW_S390X_F6:
5138 _registers.__fpr[6] = value;
5139 return;
5140 case UNW_S390X_F7:
5141 _registers.__fpr[7] = value;
5142 return;
5143 case UNW_S390X_F8:
5144 _registers.__fpr[8] = value;
5145 return;
5146 case UNW_S390X_F9:
5147 _registers.__fpr[9] = value;
5148 return;
5149 case UNW_S390X_F10:
5150 _registers.__fpr[10] = value;
5151 return;
5152 case UNW_S390X_F11:
5153 _registers.__fpr[11] = value;
5154 return;
5155 case UNW_S390X_F12:
5156 _registers.__fpr[12] = value;
5157 return;
5158 case UNW_S390X_F13:
5159 _registers.__fpr[13] = value;
5160 return;
5161 case UNW_S390X_F14:
5162 _registers.__fpr[14] = value;
5163 return;
5164 case UNW_S390X_F15:
5165 _registers.__fpr[15] = value;
5166 return;
5167 }
5168 _LIBUNWIND_ABORT("unsupported s390x register");
5169}
5170
5171inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
5172 return false;
5173}
5174
5175inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const {
5176 _LIBUNWIND_ABORT("s390x vector support not implemented");
5177}
5178
5179inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) {
5180 _LIBUNWIND_ABORT("s390x vector support not implemented");
5181}
5182
5183inline const char *Registers_s390x::getRegisterName(int regNum) {
5184 switch (regNum) {
5185 case UNW_REG_IP:
5186 return "ip";
5187 case UNW_REG_SP:
5188 return "sp";
5189 case UNW_S390X_R0:
5190 return "r0";
5191 case UNW_S390X_R1:
5192 return "r1";
5193 case UNW_S390X_R2:
5194 return "r2";
5195 case UNW_S390X_R3:
5196 return "r3";
5197 case UNW_S390X_R4:
5198 return "r4";
5199 case UNW_S390X_R5:
5200 return "r5";
5201 case UNW_S390X_R6:
5202 return "r6";
5203 case UNW_S390X_R7:
5204 return "r7";
5205 case UNW_S390X_R8:
5206 return "r8";
5207 case UNW_S390X_R9:
5208 return "r9";
5209 case UNW_S390X_R10:
5210 return "r10";
5211 case UNW_S390X_R11:
5212 return "r11";
5213 case UNW_S390X_R12:
5214 return "r12";
5215 case UNW_S390X_R13:
5216 return "r13";
5217 case UNW_S390X_R14:
5218 return "r14";
5219 case UNW_S390X_R15:
5220 return "r15";
5221 case UNW_S390X_F0:
5222 return "f0";
5223 case UNW_S390X_F1:
5224 return "f1";
5225 case UNW_S390X_F2:
5226 return "f2";
5227 case UNW_S390X_F3:
5228 return "f3";
5229 case UNW_S390X_F4:
5230 return "f4";
5231 case UNW_S390X_F5:
5232 return "f5";
5233 case UNW_S390X_F6:
5234 return "f6";
5235 case UNW_S390X_F7:
5236 return "f7";
5237 case UNW_S390X_F8:
5238 return "f8";
5239 case UNW_S390X_F9:
5240 return "f9";
5241 case UNW_S390X_F10:
5242 return "f10";
5243 case UNW_S390X_F11:
5244 return "f11";
5245 case UNW_S390X_F12:
5246 return "f12";
5247 case UNW_S390X_F13:
5248 return "f13";
5249 case UNW_S390X_F14:
5250 return "f14";
5251 case UNW_S390X_F15:
5252 return "f15";
5253 }
5254 return "unknown register";
5255}
5256#endif // _LIBUNWIND_TARGET_S390X
5257
5258#if defined(_LIBUNWIND_TARGET_LOONGARCH)
5259/// Registers_loongarch holds the register state of a thread in a 64-bit
5260/// LoongArch process.
5261class _LIBUNWIND_HIDDEN Registers_loongarch {
5262public:
5263 Registers_loongarch();
5264 Registers_loongarch(const void *registers);
5265
5266 typedef uint64_t reg_t;
5267 typedef uint64_t link_reg_t;
5268 typedef const link_reg_t &link_hardened_reg_arg_t;
5269
5270 bool validRegister(int num) const;
5271 uint64_t getRegister(int num) const;
5272 void setRegister(int num, uint64_t value);
5273 bool validFloatRegister(int num) const;
5274 double getFloatRegister(int num) const;
5275 void setFloatRegister(int num, double value);
5276 bool validVectorRegister(int num) const;
5277 v128 getVectorRegister(int num) const;
5278 void setVectorRegister(int num, v128 value);
5279 static const char *getRegisterName(int num);
5280 void jumpto();
5281 static constexpr int lastDwarfRegNum() {
5282 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH;
5283 }
5284 static int getArch() { return REGISTERS_LOONGARCH; }
5285
5286 uint64_t getSP() const { return _registers.__r[3]; }
5287 void setSP(uint64_t value) { _registers.__r[3] = value; }
5288 uint64_t getIP() const { return _registers.__pc; }
5289 void setIP(uint64_t value) { _registers.__pc = value; }
5290
5291private:
5292 struct loongarch_thread_state_t {
5293 uint64_t __r[32];
5294 uint64_t __pc;
5295 };
5296
5297 loongarch_thread_state_t _registers;
5298#if __loongarch_frlen == 64
5299 double _floats[32];
5300#endif
5301};
5302
5303inline Registers_loongarch::Registers_loongarch(const void *registers) {
5304 static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit),
5305 "loongarch registers do not fit into unw_context_t");
5306 memcpy(&_registers, registers, sizeof(_registers));
5307 static_assert(sizeof(_registers) == 0x108,
5308 "expected float registers to be at offset 264");
5309#if __loongarch_frlen == 64
5310 memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers),
5311 sizeof(_floats));
5312#endif
5313}
5314
5315inline Registers_loongarch::Registers_loongarch() {
5316 memset(&_registers, 0, sizeof(_registers));
5317#if __loongarch_frlen == 64
5318 memset(&_floats, 0, sizeof(_floats));
5319#endif
5320}
5321
5322inline bool Registers_loongarch::validRegister(int regNum) const {
5323 if (regNum == UNW_REG_IP || regNum == UNW_REG_SP)
5324 return true;
5325 if (regNum < 0 || regNum > UNW_LOONGARCH_F31)
5326 return false;
5327 return true;
5328}
5329
5330inline uint64_t Registers_loongarch::getRegister(int regNum) const {
5331 if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
5332 return _registers.__r[regNum - UNW_LOONGARCH_R0];
5333
5334 if (regNum == UNW_REG_IP)
5335 return _registers.__pc;
5336 if (regNum == UNW_REG_SP)
5337 return _registers.__r[3];
5338 _LIBUNWIND_ABORT("unsupported loongarch register");
5339}
5340
5341inline void Registers_loongarch::setRegister(int regNum, uint64_t value) {
5342 if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
5343 _registers.__r[regNum - UNW_LOONGARCH_R0] = value;
5344 else if (regNum == UNW_REG_IP)
5345 _registers.__pc = value;
5346 else if (regNum == UNW_REG_SP)
5347 _registers.__r[3] = value;
5348 else
5349 _LIBUNWIND_ABORT("unsupported loongarch register");
5350}
5351
5352inline const char *Registers_loongarch::getRegisterName(int regNum) {
5353 switch (regNum) {
5354 case UNW_REG_IP:
5355 return "$pc";
5356 case UNW_REG_SP:
5357 return "$sp";
5358 case UNW_LOONGARCH_R0:
5359 return "$r0";
5360 case UNW_LOONGARCH_R1:
5361 return "$r1";
5362 case UNW_LOONGARCH_R2:
5363 return "$r2";
5364 case UNW_LOONGARCH_R3:
5365 return "$r3";
5366 case UNW_LOONGARCH_R4:
5367 return "$r4";
5368 case UNW_LOONGARCH_R5:
5369 return "$r5";
5370 case UNW_LOONGARCH_R6:
5371 return "$r6";
5372 case UNW_LOONGARCH_R7:
5373 return "$r7";
5374 case UNW_LOONGARCH_R8:
5375 return "$r8";
5376 case UNW_LOONGARCH_R9:
5377 return "$r9";
5378 case UNW_LOONGARCH_R10:
5379 return "$r10";
5380 case UNW_LOONGARCH_R11:
5381 return "$r11";
5382 case UNW_LOONGARCH_R12:
5383 return "$r12";
5384 case UNW_LOONGARCH_R13:
5385 return "$r13";
5386 case UNW_LOONGARCH_R14:
5387 return "$r14";
5388 case UNW_LOONGARCH_R15:
5389 return "$r15";
5390 case UNW_LOONGARCH_R16:
5391 return "$r16";
5392 case UNW_LOONGARCH_R17:
5393 return "$r17";
5394 case UNW_LOONGARCH_R18:
5395 return "$r18";
5396 case UNW_LOONGARCH_R19:
5397 return "$r19";
5398 case UNW_LOONGARCH_R20:
5399 return "$r20";
5400 case UNW_LOONGARCH_R21:
5401 return "$r21";
5402 case UNW_LOONGARCH_R22:
5403 return "$r22";
5404 case UNW_LOONGARCH_R23:
5405 return "$r23";
5406 case UNW_LOONGARCH_R24:
5407 return "$r24";
5408 case UNW_LOONGARCH_R25:
5409 return "$r25";
5410 case UNW_LOONGARCH_R26:
5411 return "$r26";
5412 case UNW_LOONGARCH_R27:
5413 return "$r27";
5414 case UNW_LOONGARCH_R28:
5415 return "$r28";
5416 case UNW_LOONGARCH_R29:
5417 return "$r29";
5418 case UNW_LOONGARCH_R30:
5419 return "$r30";
5420 case UNW_LOONGARCH_R31:
5421 return "$r31";
5422 case UNW_LOONGARCH_F0:
5423 return "$f0";
5424 case UNW_LOONGARCH_F1:
5425 return "$f1";
5426 case UNW_LOONGARCH_F2:
5427 return "$f2";
5428 case UNW_LOONGARCH_F3:
5429 return "$f3";
5430 case UNW_LOONGARCH_F4:
5431 return "$f4";
5432 case UNW_LOONGARCH_F5:
5433 return "$f5";
5434 case UNW_LOONGARCH_F6:
5435 return "$f6";
5436 case UNW_LOONGARCH_F7:
5437 return "$f7";
5438 case UNW_LOONGARCH_F8:
5439 return "$f8";
5440 case UNW_LOONGARCH_F9:
5441 return "$f9";
5442 case UNW_LOONGARCH_F10:
5443 return "$f10";
5444 case UNW_LOONGARCH_F11:
5445 return "$f11";
5446 case UNW_LOONGARCH_F12:
5447 return "$f12";
5448 case UNW_LOONGARCH_F13:
5449 return "$f13";
5450 case UNW_LOONGARCH_F14:
5451 return "$f14";
5452 case UNW_LOONGARCH_F15:
5453 return "$f15";
5454 case UNW_LOONGARCH_F16:
5455 return "$f16";
5456 case UNW_LOONGARCH_F17:
5457 return "$f17";
5458 case UNW_LOONGARCH_F18:
5459 return "$f18";
5460 case UNW_LOONGARCH_F19:
5461 return "$f19";
5462 case UNW_LOONGARCH_F20:
5463 return "$f20";
5464 case UNW_LOONGARCH_F21:
5465 return "$f21";
5466 case UNW_LOONGARCH_F22:
5467 return "$f22";
5468 case UNW_LOONGARCH_F23:
5469 return "$f23";
5470 case UNW_LOONGARCH_F24:
5471 return "$f24";
5472 case UNW_LOONGARCH_F25:
5473 return "$f25";
5474 case UNW_LOONGARCH_F26:
5475 return "$f26";
5476 case UNW_LOONGARCH_F27:
5477 return "$f27";
5478 case UNW_LOONGARCH_F28:
5479 return "$f28";
5480 case UNW_LOONGARCH_F29:
5481 return "$f29";
5482 case UNW_LOONGARCH_F30:
5483 return "$f30";
5484 case UNW_LOONGARCH_F31:
5485 return "$f31";
5486 default:
5487 return "unknown register";
5488 }
5489}
5490
5491inline bool Registers_loongarch::validFloatRegister(int regNum) const {
5492 if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31)
5493 return false;
5494 return true;
5495}
5496
5497inline double Registers_loongarch::getFloatRegister(int regNum) const {
5498#if __loongarch_frlen == 64
5499 assert(validFloatRegister(regNum));
5500 return _floats[regNum - UNW_LOONGARCH_F0];
5501#else
5502 _LIBUNWIND_ABORT("libunwind not built with float support");
5503#endif
5504}
5505
5506inline void Registers_loongarch::setFloatRegister(int regNum, double value) {
5507#if __loongarch_frlen == 64
5508 assert(validFloatRegister(regNum));
5509 _floats[regNum - UNW_LOONGARCH_F0] = value;
5510#else
5511 _LIBUNWIND_ABORT("libunwind not built with float support");
5512#endif
5513}
5514
5515inline bool Registers_loongarch::validVectorRegister(int) const {
5516 return false;
5517}
5518
5519inline v128 Registers_loongarch::getVectorRegister(int) const {
5520 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5521}
5522
5523inline void Registers_loongarch::setVectorRegister(int, v128) {
5524 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5525}
5526#endif //_LIBUNWIND_TARGET_LOONGARCH
5527
5528} // namespace libunwind
5529
5530#endif // __REGISTERS_HPP__
5531