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