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