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;
1985 if (elf_aux_info(AT_HWCAP2, &hwcap2, sizeof(hwcap2)) != 0)
1986 return false;
1987 return (hwcap2 & hwcap2_sme) != 0;
1988 }
1989#else
1990 static bool checkHasSME() {
1991 // TODO: Support other platforms.
1992 return false;
1993 }
1994#endif
1995
1996 struct GPRs {
1997 uint64_t __x[29] = {}; // x0-x28
1998 uint64_t __fp = 0; // Frame pointer x29
1999 uint64_t __lr = 0; // Link register x30
2000 uint64_t __sp = 0; // Stack pointer x31
2001 uint64_t __pc = 0; // Program counter
2002 uint64_t __ra_sign_state = 0; // RA sign state register
2003 };
2004
2005 struct Misc {
2006 mutable uint32_t __vg = 0; // Vector Granule
2007 bool __has_sme = checkHasSME();
2008 };
2009
2010 GPRs _registers = {};
2011 // Currently only the lower double in 128-bit vectore registers
2012 // is perserved during unwinding. We could define new register
2013 // numbers (> 96) which mean whole vector registers, then this
2014 // struct would need to change to contain whole vector registers.
2015 double _vectorHalfRegisters[32] = {};
2016
2017 // Miscellaneous/virtual registers. These are stored below the GPRs and FPRs
2018 // as they do not correspond to physical registers, so do not need to be
2019 // saved/restored in UnwindRegistersRestore.S and UnwindRegistersSave.S, and
2020 // we don't want to modify the existing offsets for GPRs and FPRs.
2021 Misc _misc_registers;
2022};
2023
2024inline Registers_arm64::Registers_arm64(const void *registers) {
2025 static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
2026 "arm64 registers do not fit into unw_context_t");
2027 memcpy(&_registers, registers, sizeof(_registers));
2028 static_assert(sizeof(GPRs) == 0x110,
2029 "expected VFP registers to be at offset 272");
2030 memcpy(_vectorHalfRegisters,
2031 static_cast<const uint8_t *>(registers) + sizeof(GPRs),
2032 sizeof(_vectorHalfRegisters));
2033 _misc_registers.__vg = 0;
2034
2035#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
2036 // We have to do some pointer authentication fixups after this copy,
2037 // and as part of that we need to load the source pc without
2038 // authenticating so that we maintain the signature for the resigning
2039 // performed by setIP.
2040 uint64_t pcRegister = 0;
2041 memmove(&pcRegister, ((uint8_t *)&_registers) + offsetof(GPRs, __pc),
2042 sizeof(pcRegister));
2043 setIP(pcRegister);
2044#endif
2045}
2046
2047inline Registers_arm64::Registers_arm64(const Registers_arm64 &other) {
2048 *this = other;
2049}
2050
2051inline Registers_arm64 &
2052Registers_arm64::operator=(const Registers_arm64 &other) {
2053 memmove(static_cast<void *>(this), &other, sizeof(*this));
2054 // We perform this step to ensure that we correctly authenticate and re-sign
2055 // the pc after the bitwise copy.
2056 setIP(other.getIP());
2057 return *this;
2058}
2059
2060inline bool Registers_arm64::validRegister(int regNum) const {
2061 if (regNum == UNW_REG_IP)
2062 return true;
2063 if (regNum == UNW_REG_SP)
2064 return true;
2065 if (regNum < 0)
2066 return false;
2067 if (regNum > 95)
2068 return false;
2069 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
2070 return true;
2071 if (regNum == UNW_AARCH64_VG)
2072 return true;
2073 if ((regNum > 32) && (regNum < 64))
2074 return false;
2075 return true;
2076}
2077
2078inline uint64_t Registers_arm64::lazyGetVG() const {
2079 if (!_misc_registers.__vg) {
2080#if defined(__aarch64__)
2081 register uint64_t vg asm("x0");
2082 asm(".inst 0x04e0e3e0" // CNTD x0
2083 : "=r"(vg));
2084 _misc_registers.__vg = vg;
2085#else
2086 _LIBUNWIND_ABORT("arm64 VG undefined");
2087#endif
2088 }
2089 return _misc_registers.__vg;
2090}
2091
2092inline uint64_t Registers_arm64::getRegister(int regNum) const {
2093 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
2094 return getIP();
2095 if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
2096 return _registers.__sp;
2097 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
2098 return _registers.__ra_sign_state;
2099 if (regNum == UNW_AARCH64_FP)
2100 return getFP();
2101 if (regNum == UNW_AARCH64_LR)
2102 return _registers.__lr;
2103 if (regNum == UNW_AARCH64_VG)
2104 return lazyGetVG();
2105 if ((regNum >= 0) && (regNum < 29))
2106 return _registers.__x[regNum];
2107 _LIBUNWIND_ABORT("unsupported arm64 register");
2108}
2109
2110inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
2111 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
2112 setIP(value);
2113 else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
2114 _registers.__sp = value;
2115 else if (regNum == UNW_AARCH64_RA_SIGN_STATE)
2116 _registers.__ra_sign_state = value;
2117 else if (regNum == UNW_AARCH64_FP)
2118 setFP(value);
2119 else if (regNum == UNW_AARCH64_LR)
2120 _registers.__lr = value;
2121 else if (regNum == UNW_AARCH64_VG)
2122 _misc_registers.__vg = value;
2123 else if ((regNum >= 0) && (regNum < 29))
2124 _registers.__x[regNum] = value;
2125 else
2126 _LIBUNWIND_ABORT("unsupported arm64 register");
2127}
2128
2129inline const char *Registers_arm64::getRegisterName(int regNum) {
2130 switch (regNum) {
2131 case UNW_REG_IP:
2132 return "pc";
2133 case UNW_REG_SP:
2134 return "sp";
2135 case UNW_AARCH64_X0:
2136 return "x0";
2137 case UNW_AARCH64_X1:
2138 return "x1";
2139 case UNW_AARCH64_X2:
2140 return "x2";
2141 case UNW_AARCH64_X3:
2142 return "x3";
2143 case UNW_AARCH64_X4:
2144 return "x4";
2145 case UNW_AARCH64_X5:
2146 return "x5";
2147 case UNW_AARCH64_X6:
2148 return "x6";
2149 case UNW_AARCH64_X7:
2150 return "x7";
2151 case UNW_AARCH64_X8:
2152 return "x8";
2153 case UNW_AARCH64_X9:
2154 return "x9";
2155 case UNW_AARCH64_X10:
2156 return "x10";
2157 case UNW_AARCH64_X11:
2158 return "x11";
2159 case UNW_AARCH64_X12:
2160 return "x12";
2161 case UNW_AARCH64_X13:
2162 return "x13";
2163 case UNW_AARCH64_X14:
2164 return "x14";
2165 case UNW_AARCH64_X15:
2166 return "x15";
2167 case UNW_AARCH64_X16:
2168 return "x16";
2169 case UNW_AARCH64_X17:
2170 return "x17";
2171 case UNW_AARCH64_X18:
2172 return "x18";
2173 case UNW_AARCH64_X19:
2174 return "x19";
2175 case UNW_AARCH64_X20:
2176 return "x20";
2177 case UNW_AARCH64_X21:
2178 return "x21";
2179 case UNW_AARCH64_X22:
2180 return "x22";
2181 case UNW_AARCH64_X23:
2182 return "x23";
2183 case UNW_AARCH64_X24:
2184 return "x24";
2185 case UNW_AARCH64_X25:
2186 return "x25";
2187 case UNW_AARCH64_X26:
2188 return "x26";
2189 case UNW_AARCH64_X27:
2190 return "x27";
2191 case UNW_AARCH64_X28:
2192 return "x28";
2193 case UNW_AARCH64_FP:
2194 return "fp";
2195 case UNW_AARCH64_LR:
2196 return "lr";
2197 case UNW_AARCH64_SP:
2198 return "sp";
2199 case UNW_AARCH64_PC:
2200 return "pc";
2201 case UNW_AARCH64_V0:
2202 return "d0";
2203 case UNW_AARCH64_V1:
2204 return "d1";
2205 case UNW_AARCH64_V2:
2206 return "d2";
2207 case UNW_AARCH64_V3:
2208 return "d3";
2209 case UNW_AARCH64_V4:
2210 return "d4";
2211 case UNW_AARCH64_V5:
2212 return "d5";
2213 case UNW_AARCH64_V6:
2214 return "d6";
2215 case UNW_AARCH64_V7:
2216 return "d7";
2217 case UNW_AARCH64_V8:
2218 return "d8";
2219 case UNW_AARCH64_V9:
2220 return "d9";
2221 case UNW_AARCH64_V10:
2222 return "d10";
2223 case UNW_AARCH64_V11:
2224 return "d11";
2225 case UNW_AARCH64_V12:
2226 return "d12";
2227 case UNW_AARCH64_V13:
2228 return "d13";
2229 case UNW_AARCH64_V14:
2230 return "d14";
2231 case UNW_AARCH64_V15:
2232 return "d15";
2233 case UNW_AARCH64_V16:
2234 return "d16";
2235 case UNW_AARCH64_V17:
2236 return "d17";
2237 case UNW_AARCH64_V18:
2238 return "d18";
2239 case UNW_AARCH64_V19:
2240 return "d19";
2241 case UNW_AARCH64_V20:
2242 return "d20";
2243 case UNW_AARCH64_V21:
2244 return "d21";
2245 case UNW_AARCH64_V22:
2246 return "d22";
2247 case UNW_AARCH64_V23:
2248 return "d23";
2249 case UNW_AARCH64_V24:
2250 return "d24";
2251 case UNW_AARCH64_V25:
2252 return "d25";
2253 case UNW_AARCH64_V26:
2254 return "d26";
2255 case UNW_AARCH64_V27:
2256 return "d27";
2257 case UNW_AARCH64_V28:
2258 return "d28";
2259 case UNW_AARCH64_V29:
2260 return "d29";
2261 case UNW_AARCH64_V30:
2262 return "d30";
2263 case UNW_AARCH64_V31:
2264 return "d31";
2265 default:
2266 return "unknown register";
2267 }
2268}
2269
2270inline bool Registers_arm64::validFloatRegister(int regNum) const {
2271 if (regNum < UNW_AARCH64_V0)
2272 return false;
2273 if (regNum > UNW_AARCH64_V31)
2274 return false;
2275 return true;
2276}
2277
2278inline double Registers_arm64::getFloatRegister(int regNum) const {
2279 assert(validFloatRegister(regNum));
2280 return _vectorHalfRegisters[regNum - UNW_AARCH64_V0];
2281}
2282
2283inline void Registers_arm64::setFloatRegister(int regNum, double value) {
2284 assert(validFloatRegister(regNum));
2285 _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value;
2286}
2287
2288inline bool Registers_arm64::validVectorRegister(int) const {
2289 return false;
2290}
2291
2292inline v128 Registers_arm64::getVectorRegister(int) const {
2293 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2294}
2295
2296inline void Registers_arm64::setVectorRegister(int, v128) {
2297 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2298}
2299#endif // _LIBUNWIND_TARGET_AARCH64
2300
2301#if defined(_LIBUNWIND_TARGET_ARM)
2302/// Registers_arm holds the register state of a thread in a 32-bit arm
2303/// process.
2304///
2305/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2306/// this uses more memory than required.
2307class _LIBUNWIND_HIDDEN Registers_arm {
2308public:
2309 Registers_arm();
2310 Registers_arm(const void *registers);
2311
2312 typedef uint32_t reg_t;
2313 typedef uint32_t link_reg_t;
2314 typedef const link_reg_t &link_hardened_reg_arg_t;
2315
2316 bool validRegister(int num) const;
2317 uint32_t getRegister(int num) const;
2318 void setRegister(int num, uint32_t value);
2319 bool validFloatRegister(int num) const;
2320 unw_fpreg_t getFloatRegister(int num);
2321 void setFloatRegister(int num, unw_fpreg_t value);
2322 bool validVectorRegister(int num) const;
2323 v128 getVectorRegister(int num) const;
2324 void setVectorRegister(int num, v128 value);
2325 static const char *getRegisterName(int num);
2326 void jumpto() {
2327 restoreSavedFloatRegisters();
2328 restoreCoreAndJumpTo();
2329 }
2330 static constexpr int lastDwarfRegNum() {
2331 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM;
2332 }
2333 static int getArch() { return REGISTERS_ARM; }
2334
2335 uint32_t getSP() const { return _registers.__sp; }
2336 void setSP(uint32_t value) { _registers.__sp = value; }
2337 uint32_t getIP() const { return _registers.__pc; }
2338 void setIP(uint32_t value) { _registers.__pc = value; }
2339
2340 void saveVFPAsX() {
2341 assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
2342 _use_X_for_vfp_save = true;
2343 }
2344
2345 void restoreSavedFloatRegisters() {
2346 if (_saved_vfp_d0_d15) {
2347 if (_use_X_for_vfp_save)
2348 restoreVFPWithFLDMX(_vfp_d0_d15_pad);
2349 else
2350 restoreVFPWithFLDMD(_vfp_d0_d15_pad);
2351 }
2352 if (_saved_vfp_d16_d31)
2353 restoreVFPv3(_vfp_d16_d31);
2354#if defined(__ARM_WMMX)
2355 if (_saved_iwmmx)
2356 restoreiWMMX(_iwmmx);
2357 if (_saved_iwmmx_control)
2358 restoreiWMMXControl(_iwmmx_control);
2359#endif
2360 }
2361
2362private:
2363 struct GPRs {
2364 uint32_t __r[13]; // r0-r12
2365 uint32_t __sp; // Stack pointer r13
2366 uint32_t __lr; // Link register r14
2367 uint32_t __pc; // Program counter r15
2368 };
2369
2370 struct PseudoRegisters {
2371 uint32_t __pac; // Return Authentication Code (PAC)
2372 };
2373
2374 static void saveVFPWithFSTMD(void*);
2375 static void saveVFPWithFSTMX(void*);
2376 static void saveVFPv3(void*);
2377 static void restoreVFPWithFLDMD(void*);
2378 static void restoreVFPWithFLDMX(void*);
2379 static void restoreVFPv3(void*);
2380#if defined(__ARM_WMMX)
2381 static void saveiWMMX(void*);
2382 static void saveiWMMXControl(uint32_t*);
2383 static void restoreiWMMX(void*);
2384 static void restoreiWMMXControl(uint32_t*);
2385#endif
2386 void restoreCoreAndJumpTo();
2387
2388 // ARM registers
2389 GPRs _registers;
2390 PseudoRegisters _pseudo_registers;
2391
2392 // We save floating point registers lazily because we can't know ahead of
2393 // time which ones are used. See EHABI #4.7.
2394
2395 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2396 //
2397 // See EHABI #7.5 that explains how matching instruction sequences for load
2398 // and store need to be used to correctly restore the exact register bits.
2399 bool _use_X_for_vfp_save;
2400 // Whether VFP D0-D15 are saved.
2401 bool _saved_vfp_d0_d15;
2402 // Whether VFPv3 D16-D31 are saved.
2403 bool _saved_vfp_d16_d31;
2404 // VFP registers D0-D15, + padding if saved using FSTMX
2405 unw_fpreg_t _vfp_d0_d15_pad[17];
2406 // VFPv3 registers D16-D31, always saved using FSTMD
2407 unw_fpreg_t _vfp_d16_d31[16];
2408#if defined(__ARM_WMMX)
2409 // Whether iWMMX data registers are saved.
2410 bool _saved_iwmmx;
2411 // Whether iWMMX control registers are saved.
2412 mutable bool _saved_iwmmx_control;
2413 // iWMMX registers
2414 unw_fpreg_t _iwmmx[16];
2415 // iWMMX control registers
2416 mutable uint32_t _iwmmx_control[4];
2417#endif
2418};
2419
2420inline Registers_arm::Registers_arm(const void *registers)
2421 : _use_X_for_vfp_save(false),
2422 _saved_vfp_d0_d15(false),
2423 _saved_vfp_d16_d31(false) {
2424 static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
2425 "arm registers do not fit into unw_context_t");
2426 // See __unw_getcontext() note about data.
2427 memcpy(&_registers, registers, sizeof(_registers));
2428 memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));
2429 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2430 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2431#if defined(__ARM_WMMX)
2432 _saved_iwmmx = false;
2433 _saved_iwmmx_control = false;
2434 memset(&_iwmmx, 0, sizeof(_iwmmx));
2435 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2436#endif
2437}
2438
2439inline Registers_arm::Registers_arm()
2440 : _use_X_for_vfp_save(false),
2441 _saved_vfp_d0_d15(false),
2442 _saved_vfp_d16_d31(false) {
2443 memset(&_registers, 0, sizeof(_registers));
2444 memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));
2445 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2446 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2447#if defined(__ARM_WMMX)
2448 _saved_iwmmx = false;
2449 _saved_iwmmx_control = false;
2450 memset(&_iwmmx, 0, sizeof(_iwmmx));
2451 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2452#endif
2453}
2454
2455inline bool Registers_arm::validRegister(int regNum) const {
2456 // Returns true for all non-VFP registers supported by the EHABI
2457 // virtual register set (VRS).
2458 if (regNum == UNW_REG_IP)
2459 return true;
2460
2461 if (regNum == UNW_REG_SP)
2462 return true;
2463
2464 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
2465 return true;
2466
2467#if defined(__ARM_WMMX)
2468 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
2469 return true;
2470#endif
2471
2472#ifdef __ARM_FEATURE_PAUTH
2473 if (regNum == UNW_ARM_RA_AUTH_CODE)
2474 return true;
2475#endif
2476
2477 return false;
2478}
2479
2480inline uint32_t Registers_arm::getRegister(int regNum) const {
2481 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
2482 return _registers.__sp;
2483
2484 if (regNum == UNW_ARM_LR)
2485 return _registers.__lr;
2486
2487 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
2488 return _registers.__pc;
2489
2490 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
2491 return _registers.__r[regNum];
2492
2493#if defined(__ARM_WMMX)
2494 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2495 if (!_saved_iwmmx_control) {
2496 _saved_iwmmx_control = true;
2497 saveiWMMXControl(_iwmmx_control);
2498 }
2499 return _iwmmx_control[regNum - UNW_ARM_WC0];
2500 }
2501#endif
2502
2503#ifdef __ARM_FEATURE_PAUTH
2504 if (regNum == UNW_ARM_RA_AUTH_CODE)
2505 return _pseudo_registers.__pac;
2506#endif
2507
2508 _LIBUNWIND_ABORT("unsupported arm register");
2509}
2510
2511inline void Registers_arm::setRegister(int regNum, uint32_t value) {
2512 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
2513 _registers.__sp = value;
2514 return;
2515 }
2516
2517 if (regNum == UNW_ARM_LR) {
2518 _registers.__lr = value;
2519 return;
2520 }
2521
2522 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
2523 _registers.__pc = value;
2524 return;
2525 }
2526
2527 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
2528 _registers.__r[regNum] = value;
2529 return;
2530 }
2531
2532#if defined(__ARM_WMMX)
2533 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2534 if (!_saved_iwmmx_control) {
2535 _saved_iwmmx_control = true;
2536 saveiWMMXControl(_iwmmx_control);
2537 }
2538 _iwmmx_control[regNum - UNW_ARM_WC0] = value;
2539 return;
2540 }
2541#endif
2542
2543 if (regNum == UNW_ARM_RA_AUTH_CODE) {
2544 _pseudo_registers.__pac = value;
2545 return;
2546 }
2547
2548 _LIBUNWIND_ABORT("unsupported arm register");
2549}
2550
2551inline const char *Registers_arm::getRegisterName(int regNum) {
2552 switch (regNum) {
2553 case UNW_REG_IP:
2554 case UNW_ARM_IP: // UNW_ARM_R15 is alias
2555 return "pc";
2556 case UNW_ARM_LR: // UNW_ARM_R14 is alias
2557 return "lr";
2558 case UNW_REG_SP:
2559 case UNW_ARM_SP: // UNW_ARM_R13 is alias
2560 return "sp";
2561 case UNW_ARM_R0:
2562 return "r0";
2563 case UNW_ARM_R1:
2564 return "r1";
2565 case UNW_ARM_R2:
2566 return "r2";
2567 case UNW_ARM_R3:
2568 return "r3";
2569 case UNW_ARM_R4:
2570 return "r4";
2571 case UNW_ARM_R5:
2572 return "r5";
2573 case UNW_ARM_R6:
2574 return "r6";
2575 case UNW_ARM_R7:
2576 return "r7";
2577 case UNW_ARM_R8:
2578 return "r8";
2579 case UNW_ARM_R9:
2580 return "r9";
2581 case UNW_ARM_R10:
2582 return "r10";
2583 case UNW_ARM_R11:
2584 return "r11";
2585 case UNW_ARM_R12:
2586 return "r12";
2587 case UNW_ARM_S0:
2588 return "s0";
2589 case UNW_ARM_S1:
2590 return "s1";
2591 case UNW_ARM_S2:
2592 return "s2";
2593 case UNW_ARM_S3:
2594 return "s3";
2595 case UNW_ARM_S4:
2596 return "s4";
2597 case UNW_ARM_S5:
2598 return "s5";
2599 case UNW_ARM_S6:
2600 return "s6";
2601 case UNW_ARM_S7:
2602 return "s7";
2603 case UNW_ARM_S8:
2604 return "s8";
2605 case UNW_ARM_S9:
2606 return "s9";
2607 case UNW_ARM_S10:
2608 return "s10";
2609 case UNW_ARM_S11:
2610 return "s11";
2611 case UNW_ARM_S12:
2612 return "s12";
2613 case UNW_ARM_S13:
2614 return "s13";
2615 case UNW_ARM_S14:
2616 return "s14";
2617 case UNW_ARM_S15:
2618 return "s15";
2619 case UNW_ARM_S16:
2620 return "s16";
2621 case UNW_ARM_S17:
2622 return "s17";
2623 case UNW_ARM_S18:
2624 return "s18";
2625 case UNW_ARM_S19:
2626 return "s19";
2627 case UNW_ARM_S20:
2628 return "s20";
2629 case UNW_ARM_S21:
2630 return "s21";
2631 case UNW_ARM_S22:
2632 return "s22";
2633 case UNW_ARM_S23:
2634 return "s23";
2635 case UNW_ARM_S24:
2636 return "s24";
2637 case UNW_ARM_S25:
2638 return "s25";
2639 case UNW_ARM_S26:
2640 return "s26";
2641 case UNW_ARM_S27:
2642 return "s27";
2643 case UNW_ARM_S28:
2644 return "s28";
2645 case UNW_ARM_S29:
2646 return "s29";
2647 case UNW_ARM_S30:
2648 return "s30";
2649 case UNW_ARM_S31:
2650 return "s31";
2651 case UNW_ARM_D0:
2652 return "d0";
2653 case UNW_ARM_D1:
2654 return "d1";
2655 case UNW_ARM_D2:
2656 return "d2";
2657 case UNW_ARM_D3:
2658 return "d3";
2659 case UNW_ARM_D4:
2660 return "d4";
2661 case UNW_ARM_D5:
2662 return "d5";
2663 case UNW_ARM_D6:
2664 return "d6";
2665 case UNW_ARM_D7:
2666 return "d7";
2667 case UNW_ARM_D8:
2668 return "d8";
2669 case UNW_ARM_D9:
2670 return "d9";
2671 case UNW_ARM_D10:
2672 return "d10";
2673 case UNW_ARM_D11:
2674 return "d11";
2675 case UNW_ARM_D12:
2676 return "d12";
2677 case UNW_ARM_D13:
2678 return "d13";
2679 case UNW_ARM_D14:
2680 return "d14";
2681 case UNW_ARM_D15:
2682 return "d15";
2683 case UNW_ARM_D16:
2684 return "d16";
2685 case UNW_ARM_D17:
2686 return "d17";
2687 case UNW_ARM_D18:
2688 return "d18";
2689 case UNW_ARM_D19:
2690 return "d19";
2691 case UNW_ARM_D20:
2692 return "d20";
2693 case UNW_ARM_D21:
2694 return "d21";
2695 case UNW_ARM_D22:
2696 return "d22";
2697 case UNW_ARM_D23:
2698 return "d23";
2699 case UNW_ARM_D24:
2700 return "d24";
2701 case UNW_ARM_D25:
2702 return "d25";
2703 case UNW_ARM_D26:
2704 return "d26";
2705 case UNW_ARM_D27:
2706 return "d27";
2707 case UNW_ARM_D28:
2708 return "d28";
2709 case UNW_ARM_D29:
2710 return "d29";
2711 case UNW_ARM_D30:
2712 return "d30";
2713 case UNW_ARM_D31:
2714 return "d31";
2715 default:
2716 return "unknown register";
2717 }
2718}
2719
2720inline bool Registers_arm::validFloatRegister(int regNum) const {
2721 // NOTE: Consider the intel MMX registers floating points so the
2722 // __unw_get_fpreg can be used to transmit the 64-bit data back.
2723 return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
2724#if defined(__ARM_WMMX)
2725 || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
2726#endif
2727 ;
2728}
2729
2730inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
2731 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2732 if (!_saved_vfp_d0_d15) {
2733 _saved_vfp_d0_d15 = true;
2734 if (_use_X_for_vfp_save)
2735 saveVFPWithFSTMX(_vfp_d0_d15_pad);
2736 else
2737 saveVFPWithFSTMD(_vfp_d0_d15_pad);
2738 }
2739 return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
2740 }
2741
2742 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2743 if (!_saved_vfp_d16_d31) {
2744 _saved_vfp_d16_d31 = true;
2745 saveVFPv3(_vfp_d16_d31);
2746 }
2747 return _vfp_d16_d31[regNum - UNW_ARM_D16];
2748 }
2749
2750#if defined(__ARM_WMMX)
2751 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2752 if (!_saved_iwmmx) {
2753 _saved_iwmmx = true;
2754 saveiWMMX(_iwmmx);
2755 }
2756 return _iwmmx[regNum - UNW_ARM_WR0];
2757 }
2758#endif
2759
2760 _LIBUNWIND_ABORT("Unknown ARM float register");
2761}
2762
2763inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
2764 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2765 if (!_saved_vfp_d0_d15) {
2766 _saved_vfp_d0_d15 = true;
2767 if (_use_X_for_vfp_save)
2768 saveVFPWithFSTMX(_vfp_d0_d15_pad);
2769 else
2770 saveVFPWithFSTMD(_vfp_d0_d15_pad);
2771 }
2772 _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
2773 return;
2774 }
2775
2776 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2777 if (!_saved_vfp_d16_d31) {
2778 _saved_vfp_d16_d31 = true;
2779 saveVFPv3(_vfp_d16_d31);
2780 }
2781 _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
2782 return;
2783 }
2784
2785#if defined(__ARM_WMMX)
2786 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2787 if (!_saved_iwmmx) {
2788 _saved_iwmmx = true;
2789 saveiWMMX(_iwmmx);
2790 }
2791 _iwmmx[regNum - UNW_ARM_WR0] = value;
2792 return;
2793 }
2794#endif
2795
2796 _LIBUNWIND_ABORT("Unknown ARM float register");
2797}
2798
2799inline bool Registers_arm::validVectorRegister(int) const {
2800 return false;
2801}
2802
2803inline v128 Registers_arm::getVectorRegister(int) const {
2804 _LIBUNWIND_ABORT("ARM vector support not implemented");
2805}
2806
2807inline void Registers_arm::setVectorRegister(int, v128) {
2808 _LIBUNWIND_ABORT("ARM vector support not implemented");
2809}
2810#endif // _LIBUNWIND_TARGET_ARM
2811
2812
2813#if defined(_LIBUNWIND_TARGET_OR1K)
2814/// Registers_or1k holds the register state of a thread in an OpenRISC1000
2815/// process.
2816class _LIBUNWIND_HIDDEN Registers_or1k {
2817public:
2818 Registers_or1k();
2819 Registers_or1k(const void *registers);
2820
2821 typedef uint32_t reg_t;
2822 typedef uint32_t link_reg_t;
2823 typedef const link_reg_t &link_hardened_reg_arg_t;
2824
2825 bool validRegister(int num) const;
2826 uint32_t getRegister(int num) const;
2827 void setRegister(int num, uint32_t value);
2828 bool validFloatRegister(int num) const;
2829 double getFloatRegister(int num) const;
2830 void setFloatRegister(int num, double value);
2831 bool validVectorRegister(int num) const;
2832 v128 getVectorRegister(int num) const;
2833 void setVectorRegister(int num, v128 value);
2834 static const char *getRegisterName(int num);
2835 void jumpto();
2836 static constexpr int lastDwarfRegNum() {
2837 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K;
2838 }
2839 static int getArch() { return REGISTERS_OR1K; }
2840
2841 uint64_t getSP() const { return _registers.__r[1]; }
2842 void setSP(uint32_t value) { _registers.__r[1] = value; }
2843 uint64_t getIP() const { return _registers.__pc; }
2844 void setIP(uint32_t value) { _registers.__pc = value; }
2845
2846private:
2847 struct or1k_thread_state_t {
2848 unsigned int __r[32]; // r0-r31
2849 unsigned int __pc; // Program counter
2850 unsigned int __epcr; // Program counter at exception
2851 };
2852
2853 or1k_thread_state_t _registers;
2854};
2855
2856inline Registers_or1k::Registers_or1k(const void *registers) {
2857 static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
2858 "or1k registers do not fit into unw_context_t");
2859 memcpy(&_registers, static_cast<const uint8_t *>(registers),
2860 sizeof(_registers));
2861}
2862
2863inline Registers_or1k::Registers_or1k() {
2864 memset(&_registers, 0, sizeof(_registers));
2865}
2866
2867inline bool Registers_or1k::validRegister(int regNum) const {
2868 if (regNum == UNW_REG_IP)
2869 return true;
2870 if (regNum == UNW_REG_SP)
2871 return true;
2872 if (regNum < 0)
2873 return false;
2874 if (regNum <= UNW_OR1K_R31)
2875 return true;
2876 if (regNum == UNW_OR1K_EPCR)
2877 return true;
2878 return false;
2879}
2880
2881inline uint32_t Registers_or1k::getRegister(int regNum) const {
2882 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
2883 return _registers.__r[regNum - UNW_OR1K_R0];
2884
2885 switch (regNum) {
2886 case UNW_REG_IP:
2887 return _registers.__pc;
2888 case UNW_REG_SP:
2889 return _registers.__r[1];
2890 case UNW_OR1K_EPCR:
2891 return _registers.__epcr;
2892 }
2893 _LIBUNWIND_ABORT("unsupported or1k register");
2894}
2895
2896inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
2897 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
2898 _registers.__r[regNum - UNW_OR1K_R0] = value;
2899 return;
2900 }
2901
2902 switch (regNum) {
2903 case UNW_REG_IP:
2904 _registers.__pc = value;
2905 return;
2906 case UNW_REG_SP:
2907 _registers.__r[1] = value;
2908 return;
2909 case UNW_OR1K_EPCR:
2910 _registers.__epcr = value;
2911 return;
2912 }
2913 _LIBUNWIND_ABORT("unsupported or1k register");
2914}
2915
2916inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2917 return false;
2918}
2919
2920inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2921 _LIBUNWIND_ABORT("or1k float support not implemented");
2922}
2923
2924inline void Registers_or1k::setFloatRegister(int /* regNum */,
2925 double /* value */) {
2926 _LIBUNWIND_ABORT("or1k float support not implemented");
2927}
2928
2929inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2930 return false;
2931}
2932
2933inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
2934 _LIBUNWIND_ABORT("or1k vector support not implemented");
2935}
2936
2937inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
2938 _LIBUNWIND_ABORT("or1k vector support not implemented");
2939}
2940
2941inline const char *Registers_or1k::getRegisterName(int regNum) {
2942 switch (regNum) {
2943 case UNW_OR1K_R0:
2944 return "r0";
2945 case UNW_OR1K_R1:
2946 return "r1";
2947 case UNW_OR1K_R2:
2948 return "r2";
2949 case UNW_OR1K_R3:
2950 return "r3";
2951 case UNW_OR1K_R4:
2952 return "r4";
2953 case UNW_OR1K_R5:
2954 return "r5";
2955 case UNW_OR1K_R6:
2956 return "r6";
2957 case UNW_OR1K_R7:
2958 return "r7";
2959 case UNW_OR1K_R8:
2960 return "r8";
2961 case UNW_OR1K_R9:
2962 return "r9";
2963 case UNW_OR1K_R10:
2964 return "r10";
2965 case UNW_OR1K_R11:
2966 return "r11";
2967 case UNW_OR1K_R12:
2968 return "r12";
2969 case UNW_OR1K_R13:
2970 return "r13";
2971 case UNW_OR1K_R14:
2972 return "r14";
2973 case UNW_OR1K_R15:
2974 return "r15";
2975 case UNW_OR1K_R16:
2976 return "r16";
2977 case UNW_OR1K_R17:
2978 return "r17";
2979 case UNW_OR1K_R18:
2980 return "r18";
2981 case UNW_OR1K_R19:
2982 return "r19";
2983 case UNW_OR1K_R20:
2984 return "r20";
2985 case UNW_OR1K_R21:
2986 return "r21";
2987 case UNW_OR1K_R22:
2988 return "r22";
2989 case UNW_OR1K_R23:
2990 return "r23";
2991 case UNW_OR1K_R24:
2992 return "r24";
2993 case UNW_OR1K_R25:
2994 return "r25";
2995 case UNW_OR1K_R26:
2996 return "r26";
2997 case UNW_OR1K_R27:
2998 return "r27";
2999 case UNW_OR1K_R28:
3000 return "r28";
3001 case UNW_OR1K_R29:
3002 return "r29";
3003 case UNW_OR1K_R30:
3004 return "r30";
3005 case UNW_OR1K_R31:
3006 return "r31";
3007 case UNW_OR1K_EPCR:
3008 return "EPCR";
3009 default:
3010 return "unknown register";
3011 }
3012
3013}
3014#endif // _LIBUNWIND_TARGET_OR1K
3015
3016#if defined(_LIBUNWIND_TARGET_MIPS_O32)
3017/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
3018/// process.
3019class _LIBUNWIND_HIDDEN Registers_mips_o32 {
3020public:
3021 Registers_mips_o32();
3022 Registers_mips_o32(const void *registers);
3023
3024 typedef uint32_t reg_t;
3025 typedef uint32_t link_reg_t;
3026 typedef const link_reg_t &link_hardened_reg_arg_t;
3027
3028 bool validRegister(int num) const;
3029 uint32_t getRegister(int num) const;
3030 void setRegister(int num, uint32_t value);
3031 bool validFloatRegister(int num) const;
3032 double getFloatRegister(int num) const;
3033 void setFloatRegister(int num, double value);
3034 bool validVectorRegister(int num) const;
3035 v128 getVectorRegister(int num) const;
3036 void setVectorRegister(int num, v128 value);
3037 static const char *getRegisterName(int num);
3038 void jumpto();
3039 static constexpr int lastDwarfRegNum() {
3040 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
3041 }
3042 static int getArch() { return REGISTERS_MIPS_O32; }
3043
3044 uint32_t getSP() const { return _registers.__r[29]; }
3045 void setSP(uint32_t value) { _registers.__r[29] = value; }
3046 uint32_t getIP() const { return _registers.__pc; }
3047 void setIP(uint32_t value) { _registers.__pc = value; }
3048
3049private:
3050 struct mips_o32_thread_state_t {
3051 uint32_t __r[32];
3052 uint32_t __pc;
3053 uint32_t __hi;
3054 uint32_t __lo;
3055 };
3056
3057 mips_o32_thread_state_t _registers;
3058#ifdef __mips_hard_float
3059 /// O32 with 32-bit floating point registers only uses half of this
3060 /// space. However, using the same layout for 32-bit vs 64-bit
3061 /// floating point registers results in a single context size for
3062 /// O32 with hard float.
3063 uint32_t _padding;
3064 double _floats[32];
3065#endif
3066};
3067
3068inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
3069 static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
3070 "mips_o32 registers do not fit into unw_context_t");
3071 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3072 sizeof(_registers));
3073}
3074
3075inline Registers_mips_o32::Registers_mips_o32() {
3076 memset(&_registers, 0, sizeof(_registers));
3077}
3078
3079inline bool Registers_mips_o32::validRegister(int regNum) const {
3080 if (regNum == UNW_REG_IP)
3081 return true;
3082 if (regNum == UNW_REG_SP)
3083 return true;
3084 if (regNum < 0)
3085 return false;
3086 if (regNum <= UNW_MIPS_R31)
3087 return true;
3088#if __mips_isa_rev < 6
3089 if (regNum == UNW_MIPS_HI)
3090 return true;
3091 if (regNum == UNW_MIPS_LO)
3092 return true;
3093#endif
3094#if defined(__mips_hard_float) && __mips_fpr == 32
3095 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3096 return true;
3097#endif
3098 // FIXME: DSP accumulator registers, MSA registers
3099 return false;
3100}
3101
3102inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
3103 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
3104 return _registers.__r[regNum - UNW_MIPS_R0];
3105#if defined(__mips_hard_float) && __mips_fpr == 32
3106 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
3107 uint32_t *p;
3108
3109 if (regNum % 2 == 0)
3110 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
3111 else
3112 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
3113 return *p;
3114 }
3115#endif
3116
3117 switch (regNum) {
3118 case UNW_REG_IP:
3119 return _registers.__pc;
3120 case UNW_REG_SP:
3121 return _registers.__r[29];
3122#if __mips_isa_rev < 6
3123 case UNW_MIPS_HI:
3124 return _registers.__hi;
3125 case UNW_MIPS_LO:
3126 return _registers.__lo;
3127#endif
3128 }
3129 _LIBUNWIND_ABORT("unsupported mips_o32 register");
3130}
3131
3132inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
3133 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
3134 _registers.__r[regNum - UNW_MIPS_R0] = value;
3135 return;
3136 }
3137#if defined(__mips_hard_float) && __mips_fpr == 32
3138 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
3139 uint32_t *p;
3140
3141 if (regNum % 2 == 0)
3142 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
3143 else
3144 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
3145 *p = value;
3146 return;
3147 }
3148#endif
3149
3150 switch (regNum) {
3151 case UNW_REG_IP:
3152 _registers.__pc = value;
3153 return;
3154 case UNW_REG_SP:
3155 _registers.__r[29] = value;
3156 return;
3157#if __mips_isa_rev < 6
3158 case UNW_MIPS_HI:
3159 _registers.__hi = value;
3160 return;
3161 case UNW_MIPS_LO:
3162 _registers.__lo = value;
3163#endif
3164 return;
3165 }
3166 _LIBUNWIND_ABORT("unsupported mips_o32 register");
3167}
3168
3169inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
3170#if defined(__mips_hard_float) && __mips_fpr == 64
3171 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3172 return true;
3173#else
3174 (void)regNum;
3175#endif
3176 return false;
3177}
3178
3179inline double Registers_mips_o32::getFloatRegister(int regNum) const {
3180#if defined(__mips_hard_float) && __mips_fpr == 64
3181 assert(validFloatRegister(regNum));
3182 return _floats[regNum - UNW_MIPS_F0];
3183#else
3184 (void)regNum;
3185 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
3186#endif
3187}
3188
3189inline void Registers_mips_o32::setFloatRegister(int regNum,
3190 double value) {
3191#if defined(__mips_hard_float) && __mips_fpr == 64
3192 assert(validFloatRegister(regNum));
3193 _floats[regNum - UNW_MIPS_F0] = value;
3194#else
3195 (void)regNum;
3196 (void)value;
3197 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
3198#endif
3199}
3200
3201inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
3202 return false;
3203}
3204
3205inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
3206 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
3207}
3208
3209inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
3210 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
3211}
3212
3213inline const char *Registers_mips_o32::getRegisterName(int regNum) {
3214 switch (regNum) {
3215 case UNW_MIPS_R0:
3216 return "$0";
3217 case UNW_MIPS_R1:
3218 return "$1";
3219 case UNW_MIPS_R2:
3220 return "$2";
3221 case UNW_MIPS_R3:
3222 return "$3";
3223 case UNW_MIPS_R4:
3224 return "$4";
3225 case UNW_MIPS_R5:
3226 return "$5";
3227 case UNW_MIPS_R6:
3228 return "$6";
3229 case UNW_MIPS_R7:
3230 return "$7";
3231 case UNW_MIPS_R8:
3232 return "$8";
3233 case UNW_MIPS_R9:
3234 return "$9";
3235 case UNW_MIPS_R10:
3236 return "$10";
3237 case UNW_MIPS_R11:
3238 return "$11";
3239 case UNW_MIPS_R12:
3240 return "$12";
3241 case UNW_MIPS_R13:
3242 return "$13";
3243 case UNW_MIPS_R14:
3244 return "$14";
3245 case UNW_MIPS_R15:
3246 return "$15";
3247 case UNW_MIPS_R16:
3248 return "$16";
3249 case UNW_MIPS_R17:
3250 return "$17";
3251 case UNW_MIPS_R18:
3252 return "$18";
3253 case UNW_MIPS_R19:
3254 return "$19";
3255 case UNW_MIPS_R20:
3256 return "$20";
3257 case UNW_MIPS_R21:
3258 return "$21";
3259 case UNW_MIPS_R22:
3260 return "$22";
3261 case UNW_MIPS_R23:
3262 return "$23";
3263 case UNW_MIPS_R24:
3264 return "$24";
3265 case UNW_MIPS_R25:
3266 return "$25";
3267 case UNW_MIPS_R26:
3268 return "$26";
3269 case UNW_MIPS_R27:
3270 return "$27";
3271 case UNW_MIPS_R28:
3272 return "$28";
3273 case UNW_MIPS_R29:
3274 return "$29";
3275 case UNW_MIPS_R30:
3276 return "$30";
3277 case UNW_MIPS_R31:
3278 return "$31";
3279 case UNW_MIPS_F0:
3280 return "$f0";
3281 case UNW_MIPS_F1:
3282 return "$f1";
3283 case UNW_MIPS_F2:
3284 return "$f2";
3285 case UNW_MIPS_F3:
3286 return "$f3";
3287 case UNW_MIPS_F4:
3288 return "$f4";
3289 case UNW_MIPS_F5:
3290 return "$f5";
3291 case UNW_MIPS_F6:
3292 return "$f6";
3293 case UNW_MIPS_F7:
3294 return "$f7";
3295 case UNW_MIPS_F8:
3296 return "$f8";
3297 case UNW_MIPS_F9:
3298 return "$f9";
3299 case UNW_MIPS_F10:
3300 return "$f10";
3301 case UNW_MIPS_F11:
3302 return "$f11";
3303 case UNW_MIPS_F12:
3304 return "$f12";
3305 case UNW_MIPS_F13:
3306 return "$f13";
3307 case UNW_MIPS_F14:
3308 return "$f14";
3309 case UNW_MIPS_F15:
3310 return "$f15";
3311 case UNW_MIPS_F16:
3312 return "$f16";
3313 case UNW_MIPS_F17:
3314 return "$f17";
3315 case UNW_MIPS_F18:
3316 return "$f18";
3317 case UNW_MIPS_F19:
3318 return "$f19";
3319 case UNW_MIPS_F20:
3320 return "$f20";
3321 case UNW_MIPS_F21:
3322 return "$f21";
3323 case UNW_MIPS_F22:
3324 return "$f22";
3325 case UNW_MIPS_F23:
3326 return "$f23";
3327 case UNW_MIPS_F24:
3328 return "$f24";
3329 case UNW_MIPS_F25:
3330 return "$f25";
3331 case UNW_MIPS_F26:
3332 return "$f26";
3333 case UNW_MIPS_F27:
3334 return "$f27";
3335 case UNW_MIPS_F28:
3336 return "$f28";
3337 case UNW_MIPS_F29:
3338 return "$f29";
3339 case UNW_MIPS_F30:
3340 return "$f30";
3341 case UNW_MIPS_F31:
3342 return "$f31";
3343#if __mips_isa_rev < 6
3344 case UNW_MIPS_HI:
3345 return "$hi";
3346 case UNW_MIPS_LO:
3347 return "$lo";
3348#endif
3349 default:
3350 return "unknown register";
3351 }
3352}
3353#endif // _LIBUNWIND_TARGET_MIPS_O32
3354
3355#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3356/// Registers_mips_newabi holds the register state of a thread in a
3357/// MIPS process using NEWABI (the N32 or N64 ABIs).
3358class _LIBUNWIND_HIDDEN Registers_mips_newabi {
3359public:
3360 Registers_mips_newabi();
3361 Registers_mips_newabi(const void *registers);
3362
3363 typedef uint64_t reg_t;
3364 typedef uint64_t link_reg_t;
3365 typedef const link_reg_t &link_hardened_reg_arg_t;
3366
3367 bool validRegister(int num) const;
3368 uint64_t getRegister(int num) const;
3369 void setRegister(int num, uint64_t value);
3370 bool validFloatRegister(int num) const;
3371 double getFloatRegister(int num) const;
3372 void setFloatRegister(int num, double value);
3373 bool validVectorRegister(int num) const;
3374 v128 getVectorRegister(int num) const;
3375 void setVectorRegister(int num, v128 value);
3376 static const char *getRegisterName(int num);
3377 void jumpto();
3378 static constexpr int lastDwarfRegNum() {
3379 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
3380 }
3381 static int getArch() { return REGISTERS_MIPS_NEWABI; }
3382
3383 uint64_t getSP() const { return _registers.__r[29]; }
3384 void setSP(uint64_t value) { _registers.__r[29] = value; }
3385 uint64_t getIP() const { return _registers.__pc; }
3386 void setIP(uint64_t value) { _registers.__pc = value; }
3387
3388private:
3389 struct mips_newabi_thread_state_t {
3390 uint64_t __r[32];
3391 uint64_t __pc;
3392 uint64_t __hi;
3393 uint64_t __lo;
3394 };
3395
3396 mips_newabi_thread_state_t _registers;
3397#ifdef __mips_hard_float
3398 double _floats[32];
3399#endif
3400};
3401
3402inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
3403 static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
3404 "mips_newabi registers do not fit into unw_context_t");
3405 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3406 sizeof(_registers));
3407}
3408
3409inline Registers_mips_newabi::Registers_mips_newabi() {
3410 memset(&_registers, 0, sizeof(_registers));
3411}
3412
3413inline bool Registers_mips_newabi::validRegister(int regNum) const {
3414 if (regNum == UNW_REG_IP)
3415 return true;
3416 if (regNum == UNW_REG_SP)
3417 return true;
3418 if (regNum < 0)
3419 return false;
3420 if (regNum <= UNW_MIPS_R31)
3421 return true;
3422#if __mips_isa_rev < 6
3423 if (regNum == UNW_MIPS_HI)
3424 return true;
3425 if (regNum == UNW_MIPS_LO)
3426 return true;
3427#endif
3428 // FIXME: Hard float, DSP accumulator registers, MSA registers
3429 return false;
3430}
3431
3432inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
3433 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
3434 return _registers.__r[regNum - UNW_MIPS_R0];
3435
3436 switch (regNum) {
3437 case UNW_REG_IP:
3438 return _registers.__pc;
3439 case UNW_REG_SP:
3440 return _registers.__r[29];
3441#if __mips_isa_rev < 6
3442 case UNW_MIPS_HI:
3443 return _registers.__hi;
3444 case UNW_MIPS_LO:
3445 return _registers.__lo;
3446#endif
3447 }
3448 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3449}
3450
3451inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
3452 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
3453 _registers.__r[regNum - UNW_MIPS_R0] = value;
3454 return;
3455 }
3456
3457 switch (regNum) {
3458 case UNW_REG_IP:
3459 _registers.__pc = value;
3460 return;
3461 case UNW_REG_SP:
3462 _registers.__r[29] = value;
3463 return;
3464#if __mips_isa_rev < 6
3465 case UNW_MIPS_HI:
3466 _registers.__hi = value;
3467 return;
3468 case UNW_MIPS_LO:
3469 _registers.__lo = value;
3470 return;
3471#endif
3472 }
3473 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3474}
3475
3476inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
3477#ifdef __mips_hard_float
3478 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3479 return true;
3480#else
3481 (void)regNum;
3482#endif
3483 return false;
3484}
3485
3486inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
3487#ifdef __mips_hard_float
3488 assert(validFloatRegister(regNum));
3489 return _floats[regNum - UNW_MIPS_F0];
3490#else
3491 (void)regNum;
3492 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3493#endif
3494}
3495
3496inline void Registers_mips_newabi::setFloatRegister(int regNum,
3497 double value) {
3498#ifdef __mips_hard_float
3499 assert(validFloatRegister(regNum));
3500 _floats[regNum - UNW_MIPS_F0] = value;
3501#else
3502 (void)regNum;
3503 (void)value;
3504 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3505#endif
3506}
3507
3508inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3509 return false;
3510}
3511
3512inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3513 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3514}
3515
3516inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
3517 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3518}
3519
3520inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
3521 switch (regNum) {
3522 case UNW_MIPS_R0:
3523 return "$0";
3524 case UNW_MIPS_R1:
3525 return "$1";
3526 case UNW_MIPS_R2:
3527 return "$2";
3528 case UNW_MIPS_R3:
3529 return "$3";
3530 case UNW_MIPS_R4:
3531 return "$4";
3532 case UNW_MIPS_R5:
3533 return "$5";
3534 case UNW_MIPS_R6:
3535 return "$6";
3536 case UNW_MIPS_R7:
3537 return "$7";
3538 case UNW_MIPS_R8:
3539 return "$8";
3540 case UNW_MIPS_R9:
3541 return "$9";
3542 case UNW_MIPS_R10:
3543 return "$10";
3544 case UNW_MIPS_R11:
3545 return "$11";
3546 case UNW_MIPS_R12:
3547 return "$12";
3548 case UNW_MIPS_R13:
3549 return "$13";
3550 case UNW_MIPS_R14:
3551 return "$14";
3552 case UNW_MIPS_R15:
3553 return "$15";
3554 case UNW_MIPS_R16:
3555 return "$16";
3556 case UNW_MIPS_R17:
3557 return "$17";
3558 case UNW_MIPS_R18:
3559 return "$18";
3560 case UNW_MIPS_R19:
3561 return "$19";
3562 case UNW_MIPS_R20:
3563 return "$20";
3564 case UNW_MIPS_R21:
3565 return "$21";
3566 case UNW_MIPS_R22:
3567 return "$22";
3568 case UNW_MIPS_R23:
3569 return "$23";
3570 case UNW_MIPS_R24:
3571 return "$24";
3572 case UNW_MIPS_R25:
3573 return "$25";
3574 case UNW_MIPS_R26:
3575 return "$26";
3576 case UNW_MIPS_R27:
3577 return "$27";
3578 case UNW_MIPS_R28:
3579 return "$28";
3580 case UNW_MIPS_R29:
3581 return "$29";
3582 case UNW_MIPS_R30:
3583 return "$30";
3584 case UNW_MIPS_R31:
3585 return "$31";
3586 case UNW_MIPS_F0:
3587 return "$f0";
3588 case UNW_MIPS_F1:
3589 return "$f1";
3590 case UNW_MIPS_F2:
3591 return "$f2";
3592 case UNW_MIPS_F3:
3593 return "$f3";
3594 case UNW_MIPS_F4:
3595 return "$f4";
3596 case UNW_MIPS_F5:
3597 return "$f5";
3598 case UNW_MIPS_F6:
3599 return "$f6";
3600 case UNW_MIPS_F7:
3601 return "$f7";
3602 case UNW_MIPS_F8:
3603 return "$f8";
3604 case UNW_MIPS_F9:
3605 return "$f9";
3606 case UNW_MIPS_F10:
3607 return "$f10";
3608 case UNW_MIPS_F11:
3609 return "$f11";
3610 case UNW_MIPS_F12:
3611 return "$f12";
3612 case UNW_MIPS_F13:
3613 return "$f13";
3614 case UNW_MIPS_F14:
3615 return "$f14";
3616 case UNW_MIPS_F15:
3617 return "$f15";
3618 case UNW_MIPS_F16:
3619 return "$f16";
3620 case UNW_MIPS_F17:
3621 return "$f17";
3622 case UNW_MIPS_F18:
3623 return "$f18";
3624 case UNW_MIPS_F19:
3625 return "$f19";
3626 case UNW_MIPS_F20:
3627 return "$f20";
3628 case UNW_MIPS_F21:
3629 return "$f21";
3630 case UNW_MIPS_F22:
3631 return "$f22";
3632 case UNW_MIPS_F23:
3633 return "$f23";
3634 case UNW_MIPS_F24:
3635 return "$f24";
3636 case UNW_MIPS_F25:
3637 return "$f25";
3638 case UNW_MIPS_F26:
3639 return "$f26";
3640 case UNW_MIPS_F27:
3641 return "$f27";
3642 case UNW_MIPS_F28:
3643 return "$f28";
3644 case UNW_MIPS_F29:
3645 return "$f29";
3646 case UNW_MIPS_F30:
3647 return "$f30";
3648 case UNW_MIPS_F31:
3649 return "$f31";
3650#if __mips_isa_rev < 6
3651 case UNW_MIPS_HI:
3652 return "$hi";
3653 case UNW_MIPS_LO:
3654 return "$lo";
3655#endif
3656 default:
3657 return "unknown register";
3658 }
3659}
3660#endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3661
3662#if defined(_LIBUNWIND_TARGET_SPARC)
3663/// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3664/// process.
3665class _LIBUNWIND_HIDDEN Registers_sparc {
3666public:
3667 Registers_sparc();
3668 Registers_sparc(const void *registers);
3669
3670 typedef uint32_t reg_t;
3671 typedef uint32_t link_reg_t;
3672 typedef const link_reg_t &link_hardened_reg_arg_t;
3673
3674 bool validRegister(int num) const;
3675 uint32_t getRegister(int num) const;
3676 void setRegister(int num, uint32_t value);
3677 bool validFloatRegister(int num) const;
3678 double getFloatRegister(int num) const;
3679 void setFloatRegister(int num, double value);
3680 bool validVectorRegister(int num) const;
3681 v128 getVectorRegister(int num) const;
3682 void setVectorRegister(int num, v128 value);
3683 static const char *getRegisterName(int num);
3684 void jumpto();
3685 static constexpr int lastDwarfRegNum() {
3686 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC;
3687 }
3688 static int getArch() { return REGISTERS_SPARC; }
3689
3690 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
3691 void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
3692 uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
3693 void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3694
3695private:
3696 struct sparc_thread_state_t {
3697 unsigned int __regs[32];
3698 };
3699
3700 sparc_thread_state_t _registers;
3701};
3702
3703inline Registers_sparc::Registers_sparc(const void *registers) {
3704 static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
3705 "sparc registers do not fit into unw_context_t");
3706 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3707 sizeof(_registers));
3708}
3709
3710inline Registers_sparc::Registers_sparc() {
3711 memset(&_registers, 0, sizeof(_registers));
3712}
3713
3714inline bool Registers_sparc::validRegister(int regNum) const {
3715 if (regNum == UNW_REG_IP)
3716 return true;
3717 if (regNum == UNW_REG_SP)
3718 return true;
3719 if (regNum < 0)
3720 return false;
3721 if (regNum <= UNW_SPARC_I7)
3722 return true;
3723 return false;
3724}
3725
3726inline uint32_t Registers_sparc::getRegister(int regNum) const {
3727 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3728 return _registers.__regs[regNum];
3729 }
3730
3731 switch (regNum) {
3732 case UNW_REG_IP:
3733 return _registers.__regs[UNW_SPARC_O7];
3734 case UNW_REG_SP:
3735 return _registers.__regs[UNW_SPARC_O6];
3736 }
3737 _LIBUNWIND_ABORT("unsupported sparc register");
3738}
3739
3740inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
3741 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3742 _registers.__regs[regNum] = value;
3743 return;
3744 }
3745
3746 switch (regNum) {
3747 case UNW_REG_IP:
3748 _registers.__regs[UNW_SPARC_O7] = value;
3749 return;
3750 case UNW_REG_SP:
3751 _registers.__regs[UNW_SPARC_O6] = value;
3752 return;
3753 }
3754 _LIBUNWIND_ABORT("unsupported sparc register");
3755}
3756
3757inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3758
3759inline double Registers_sparc::getFloatRegister(int) const {
3760 _LIBUNWIND_ABORT("no sparc float registers");
3761}
3762
3763inline void Registers_sparc::setFloatRegister(int, double) {
3764 _LIBUNWIND_ABORT("no sparc float registers");
3765}
3766
3767inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3768
3769inline v128 Registers_sparc::getVectorRegister(int) const {
3770 _LIBUNWIND_ABORT("no sparc vector registers");
3771}
3772
3773inline void Registers_sparc::setVectorRegister(int, v128) {
3774 _LIBUNWIND_ABORT("no sparc vector registers");
3775}
3776
3777inline const char *Registers_sparc::getRegisterName(int regNum) {
3778 switch (regNum) {
3779 case UNW_REG_IP:
3780 return "pc";
3781 case UNW_SPARC_G0:
3782 return "g0";
3783 case UNW_SPARC_G1:
3784 return "g1";
3785 case UNW_SPARC_G2:
3786 return "g2";
3787 case UNW_SPARC_G3:
3788 return "g3";
3789 case UNW_SPARC_G4:
3790 return "g4";
3791 case UNW_SPARC_G5:
3792 return "g5";
3793 case UNW_SPARC_G6:
3794 return "g6";
3795 case UNW_SPARC_G7:
3796 return "g7";
3797 case UNW_SPARC_O0:
3798 return "o0";
3799 case UNW_SPARC_O1:
3800 return "o1";
3801 case UNW_SPARC_O2:
3802 return "o2";
3803 case UNW_SPARC_O3:
3804 return "o3";
3805 case UNW_SPARC_O4:
3806 return "o4";
3807 case UNW_SPARC_O5:
3808 return "o5";
3809 case UNW_REG_SP:
3810 case UNW_SPARC_O6:
3811 return "sp";
3812 case UNW_SPARC_O7:
3813 return "o7";
3814 case UNW_SPARC_L0:
3815 return "l0";
3816 case UNW_SPARC_L1:
3817 return "l1";
3818 case UNW_SPARC_L2:
3819 return "l2";
3820 case UNW_SPARC_L3:
3821 return "l3";
3822 case UNW_SPARC_L4:
3823 return "l4";
3824 case UNW_SPARC_L5:
3825 return "l5";
3826 case UNW_SPARC_L6:
3827 return "l6";
3828 case UNW_SPARC_L7:
3829 return "l7";
3830 case UNW_SPARC_I0:
3831 return "i0";
3832 case UNW_SPARC_I1:
3833 return "i1";
3834 case UNW_SPARC_I2:
3835 return "i2";
3836 case UNW_SPARC_I3:
3837 return "i3";
3838 case UNW_SPARC_I4:
3839 return "i4";
3840 case UNW_SPARC_I5:
3841 return "i5";
3842 case UNW_SPARC_I6:
3843 return "fp";
3844 case UNW_SPARC_I7:
3845 return "i7";
3846 default:
3847 return "unknown register";
3848 }
3849}
3850#endif // _LIBUNWIND_TARGET_SPARC
3851
3852#if defined(_LIBUNWIND_TARGET_SPARC64)
3853/// Registers_sparc64 holds the register state of a thread in a 64-bit
3854/// sparc process.
3855class _LIBUNWIND_HIDDEN Registers_sparc64 {
3856public:
3857 Registers_sparc64() = default;
3858 Registers_sparc64(const void *registers);
3859
3860 typedef uint64_t reg_t;
3861 typedef uint64_t link_reg_t;
3862 typedef const link_reg_t &link_hardened_reg_arg_t;
3863
3864 bool validRegister(int num) const;
3865 uint64_t getRegister(int num) const;
3866 void setRegister(int num, uint64_t value);
3867 bool validFloatRegister(int num) const;
3868 double getFloatRegister(int num) const;
3869 void setFloatRegister(int num, double value);
3870 bool validVectorRegister(int num) const;
3871 v128 getVectorRegister(int num) const;
3872 void setVectorRegister(int num, v128 value);
3873 const char *getRegisterName(int num);
3874 void jumpto();
3875 static constexpr int lastDwarfRegNum() {
3876 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;
3877 }
3878 static int getArch() { return REGISTERS_SPARC64; }
3879
3880 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; }
3881 void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; }
3882 uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
3883 void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3884 uint64_t getWCookie() const { return _wcookie; }
3885
3886private:
3887 struct sparc64_thread_state_t {
3888 uint64_t __regs[32];
3889 };
3890
3891 sparc64_thread_state_t _registers{};
3892 uint64_t _wcookie = 0;
3893};
3894
3895inline Registers_sparc64::Registers_sparc64(const void *registers) {
3896 static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit),
3897 "sparc64 registers do not fit into unw_context_t");
3898 memcpy(&_registers, registers, sizeof(_registers));
3899 memcpy(&_wcookie,
3900 static_cast<const uint8_t *>(registers) + sizeof(_registers),
3901 sizeof(_wcookie));
3902}
3903
3904inline bool Registers_sparc64::validRegister(int regNum) const {
3905 if (regNum == UNW_REG_IP)
3906 return true;
3907 if (regNum == UNW_REG_SP)
3908 return true;
3909 if (regNum < 0)
3910 return false;
3911 if (regNum <= UNW_SPARC_I7)
3912 return true;
3913 return false;
3914}
3915
3916inline uint64_t Registers_sparc64::getRegister(int regNum) const {
3917 if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7)
3918 return _registers.__regs[regNum];
3919
3920 switch (regNum) {
3921 case UNW_REG_IP:
3922 return _registers.__regs[UNW_SPARC_O7];
3923 case UNW_REG_SP:
3924 return _registers.__regs[UNW_SPARC_O6] + 2047;
3925 }
3926 _LIBUNWIND_ABORT("unsupported sparc64 register");
3927}
3928
3929inline void Registers_sparc64::setRegister(int regNum, uint64_t value) {
3930 if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) {
3931 _registers.__regs[regNum] = value;
3932 return;
3933 }
3934
3935 switch (regNum) {
3936 case UNW_REG_IP:
3937 _registers.__regs[UNW_SPARC_O7] = value;
3938 return;
3939 case UNW_REG_SP:
3940 _registers.__regs[UNW_SPARC_O6] = value - 2047;
3941 return;
3942 }
3943 _LIBUNWIND_ABORT("unsupported sparc64 register");
3944}
3945
3946inline bool Registers_sparc64::validFloatRegister(int) const { return false; }
3947
3948inline double Registers_sparc64::getFloatRegister(int) const {
3949 _LIBUNWIND_ABORT("no sparc64 float registers");
3950}
3951
3952inline void Registers_sparc64::setFloatRegister(int, double) {
3953 _LIBUNWIND_ABORT("no sparc64 float registers");
3954}
3955
3956inline bool Registers_sparc64::validVectorRegister(int) const { return false; }
3957
3958inline v128 Registers_sparc64::getVectorRegister(int) const {
3959 _LIBUNWIND_ABORT("no sparc64 vector registers");
3960}
3961
3962inline void Registers_sparc64::setVectorRegister(int, v128) {
3963 _LIBUNWIND_ABORT("no sparc64 vector registers");
3964}
3965
3966inline const char *Registers_sparc64::getRegisterName(int regNum) {
3967 switch (regNum) {
3968 case UNW_REG_IP:
3969 return "pc";
3970 case UNW_SPARC_G0:
3971 return "g0";
3972 case UNW_SPARC_G1:
3973 return "g1";
3974 case UNW_SPARC_G2:
3975 return "g2";
3976 case UNW_SPARC_G3:
3977 return "g3";
3978 case UNW_SPARC_G4:
3979 return "g4";
3980 case UNW_SPARC_G5:
3981 return "g5";
3982 case UNW_SPARC_G6:
3983 return "g6";
3984 case UNW_SPARC_G7:
3985 return "g7";
3986 case UNW_SPARC_O0:
3987 return "o0";
3988 case UNW_SPARC_O1:
3989 return "o1";
3990 case UNW_SPARC_O2:
3991 return "o2";
3992 case UNW_SPARC_O3:
3993 return "o3";
3994 case UNW_SPARC_O4:
3995 return "o4";
3996 case UNW_SPARC_O5:
3997 return "o5";
3998 case UNW_REG_SP:
3999 case UNW_SPARC_O6:
4000 return "o6";
4001 case UNW_SPARC_O7:
4002 return "o7";
4003 case UNW_SPARC_L0:
4004 return "l0";
4005 case UNW_SPARC_L1:
4006 return "l1";
4007 case UNW_SPARC_L2:
4008 return "l2";
4009 case UNW_SPARC_L3:
4010 return "l3";
4011 case UNW_SPARC_L4:
4012 return "l4";
4013 case UNW_SPARC_L5:
4014 return "l5";
4015 case UNW_SPARC_L6:
4016 return "l6";
4017 case UNW_SPARC_L7:
4018 return "l7";
4019 case UNW_SPARC_I0:
4020 return "i0";
4021 case UNW_SPARC_I1:
4022 return "i1";
4023 case UNW_SPARC_I2:
4024 return "i2";
4025 case UNW_SPARC_I3:
4026 return "i3";
4027 case UNW_SPARC_I4:
4028 return "i4";
4029 case UNW_SPARC_I5:
4030 return "i5";
4031 case UNW_SPARC_I6:
4032 return "i6";
4033 case UNW_SPARC_I7:
4034 return "i7";
4035 default:
4036 return "unknown register";
4037 }
4038}
4039#endif // _LIBUNWIND_TARGET_SPARC64
4040
4041#if defined(_LIBUNWIND_TARGET_HEXAGON)
4042/// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
4043/// process.
4044class _LIBUNWIND_HIDDEN Registers_hexagon {
4045public:
4046 Registers_hexagon();
4047 Registers_hexagon(const void *registers);
4048
4049 typedef uint32_t reg_t;
4050 typedef uint32_t link_reg_t;
4051 typedef const link_reg_t &link_hardened_reg_arg_t;
4052
4053 bool validRegister(int num) const;
4054 uint32_t getRegister(int num) const;
4055 void setRegister(int num, uint32_t value);
4056 bool validFloatRegister(int num) const;
4057 double getFloatRegister(int num) const;
4058 void setFloatRegister(int num, double value);
4059 bool validVectorRegister(int num) const;
4060 v128 getVectorRegister(int num) const;
4061 void setVectorRegister(int num, v128 value);
4062 const char *getRegisterName(int num);
4063 void jumpto();
4064 static constexpr int lastDwarfRegNum() {
4065 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON;
4066 }
4067 static int getArch() { return REGISTERS_HEXAGON; }
4068
4069 uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }
4070 void setSP(uint32_t value) { _registers.__r[UNW_HEXAGON_R29] = value; }
4071 uint32_t getIP() const { return _registers.__r[UNW_HEXAGON_PC]; }
4072 void setIP(uint32_t value) { _registers.__r[UNW_HEXAGON_PC] = value; }
4073
4074private:
4075 struct hexagon_thread_state_t {
4076 unsigned int __r[35];
4077 };
4078
4079 hexagon_thread_state_t _registers;
4080};
4081
4082inline Registers_hexagon::Registers_hexagon(const void *registers) {
4083 static_assert((check_fit<Registers_hexagon, unw_context_t>::does_fit),
4084 "hexagon registers do not fit into unw_context_t");
4085 memcpy(&_registers, static_cast<const uint8_t *>(registers),
4086 sizeof(_registers));
4087}
4088
4089inline Registers_hexagon::Registers_hexagon() {
4090 memset(&_registers, 0, sizeof(_registers));
4091}
4092
4093inline bool Registers_hexagon::validRegister(int regNum) const {
4094 if (regNum <= UNW_HEXAGON_R31)
4095 return true;
4096 return false;
4097}
4098
4099inline uint32_t Registers_hexagon::getRegister(int regNum) const {
4100 if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31)
4101 return _registers.__r[regNum - UNW_HEXAGON_R0];
4102
4103 switch (regNum) {
4104 case UNW_REG_IP:
4105 return _registers.__r[UNW_HEXAGON_PC];
4106 case UNW_REG_SP:
4107 return _registers.__r[UNW_HEXAGON_R29];
4108 }
4109 _LIBUNWIND_ABORT("unsupported hexagon register");
4110}
4111
4112inline void Registers_hexagon::setRegister(int regNum, uint32_t value) {
4113 if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) {
4114 _registers.__r[regNum - UNW_HEXAGON_R0] = value;
4115 return;
4116 }
4117
4118 switch (regNum) {
4119 case UNW_REG_IP:
4120 _registers.__r[UNW_HEXAGON_PC] = value;
4121 return;
4122 case UNW_REG_SP:
4123 _registers.__r[UNW_HEXAGON_R29] = value;
4124 return;
4125 }
4126 _LIBUNWIND_ABORT("unsupported hexagon register");
4127}
4128
4129inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {
4130 return false;
4131}
4132
4133inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {
4134 _LIBUNWIND_ABORT("hexagon float support not implemented");
4135}
4136
4137inline void Registers_hexagon::setFloatRegister(int /* regNum */,
4138 double /* value */) {
4139 _LIBUNWIND_ABORT("hexagon float support not implemented");
4140}
4141
4142inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {
4143 return false;
4144}
4145
4146inline v128 Registers_hexagon::getVectorRegister(int /* regNum */) const {
4147 _LIBUNWIND_ABORT("hexagon vector support not implemented");
4148}
4149
4150inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128 /* value */) {
4151 _LIBUNWIND_ABORT("hexagon vector support not implemented");
4152}
4153
4154inline const char *Registers_hexagon::getRegisterName(int regNum) {
4155 switch (regNum) {
4156 case UNW_HEXAGON_R0:
4157 return "r0";
4158 case UNW_HEXAGON_R1:
4159 return "r1";
4160 case UNW_HEXAGON_R2:
4161 return "r2";
4162 case UNW_HEXAGON_R3:
4163 return "r3";
4164 case UNW_HEXAGON_R4:
4165 return "r4";
4166 case UNW_HEXAGON_R5:
4167 return "r5";
4168 case UNW_HEXAGON_R6:
4169 return "r6";
4170 case UNW_HEXAGON_R7:
4171 return "r7";
4172 case UNW_HEXAGON_R8:
4173 return "r8";
4174 case UNW_HEXAGON_R9:
4175 return "r9";
4176 case UNW_HEXAGON_R10:
4177 return "r10";
4178 case UNW_HEXAGON_R11:
4179 return "r11";
4180 case UNW_HEXAGON_R12:
4181 return "r12";
4182 case UNW_HEXAGON_R13:
4183 return "r13";
4184 case UNW_HEXAGON_R14:
4185 return "r14";
4186 case UNW_HEXAGON_R15:
4187 return "r15";
4188 case UNW_HEXAGON_R16:
4189 return "r16";
4190 case UNW_HEXAGON_R17:
4191 return "r17";
4192 case UNW_HEXAGON_R18:
4193 return "r18";
4194 case UNW_HEXAGON_R19:
4195 return "r19";
4196 case UNW_HEXAGON_R20:
4197 return "r20";
4198 case UNW_HEXAGON_R21:
4199 return "r21";
4200 case UNW_HEXAGON_R22:
4201 return "r22";
4202 case UNW_HEXAGON_R23:
4203 return "r23";
4204 case UNW_HEXAGON_R24:
4205 return "r24";
4206 case UNW_HEXAGON_R25:
4207 return "r25";
4208 case UNW_HEXAGON_R26:
4209 return "r26";
4210 case UNW_HEXAGON_R27:
4211 return "r27";
4212 case UNW_HEXAGON_R28:
4213 return "r28";
4214 case UNW_HEXAGON_R29:
4215 return "r29";
4216 case UNW_HEXAGON_R30:
4217 return "r30";
4218 case UNW_HEXAGON_R31:
4219 return "r31";
4220 default:
4221 return "unknown register";
4222 }
4223
4224}
4225#endif // _LIBUNWIND_TARGET_HEXAGON
4226
4227
4228#if defined(_LIBUNWIND_TARGET_RISCV)
4229/// Registers_riscv holds the register state of a thread in a RISC-V
4230/// process.
4231
4232// This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.
4233# ifdef __riscv
4234# if __riscv_xlen == 32
4235typedef uint32_t reg_t;
4236# elif __riscv_xlen == 64
4237typedef uint64_t reg_t;
4238# else
4239# error "Unsupported __riscv_xlen"
4240# endif
4241
4242# if defined(__riscv_flen)
4243# if __riscv_flen == 64
4244typedef double fp_t;
4245# elif __riscv_flen == 32
4246typedef float fp_t;
4247# else
4248# error "Unsupported __riscv_flen"
4249# endif
4250# else
4251// This is just for suppressing undeclared error of fp_t.
4252typedef double fp_t;
4253# endif
4254# else
4255// Use Max possible width when cross unwinding
4256typedef uint64_t reg_t;
4257typedef double fp_t;
4258# define __riscv_xlen 64
4259# define __riscv_flen 64
4260#endif
4261
4262/// Registers_riscv holds the register state of a thread.
4263class _LIBUNWIND_HIDDEN Registers_riscv {
4264public:
4265 Registers_riscv();
4266 Registers_riscv(const void *registers);
4267
4268 typedef ::libunwind::reg_t reg_t;
4269 typedef ::libunwind::reg_t link_reg_t;
4270 typedef const link_reg_t &link_hardened_reg_arg_t;
4271
4272 bool validRegister(int num) const;
4273 reg_t getRegister(int num) const;
4274 void setRegister(int num, reg_t value);
4275 bool validFloatRegister(int num) const;
4276 fp_t getFloatRegister(int num) const;
4277 void setFloatRegister(int num, fp_t value);
4278 bool validVectorRegister(int num) const;
4279 v128 getVectorRegister(int num) const;
4280 void setVectorRegister(int num, v128 value);
4281 static const char *getRegisterName(int num);
4282 void jumpto();
4283 static constexpr int lastDwarfRegNum() {
4284 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV;
4285 }
4286 static int getArch() { return REGISTERS_RISCV; }
4287
4288 reg_t getSP() const { return _registers[2]; }
4289 void setSP(reg_t value) { _registers[2] = value; }
4290 reg_t getIP() const { return _registers[0]; }
4291 void setIP(reg_t value) { _registers[0] = value; }
4292
4293private:
4294 // _registers[0] holds the pc
4295 reg_t _registers[32];
4296# if defined(__riscv_flen)
4297 fp_t _floats[32];
4298# endif
4299};
4300
4301inline Registers_riscv::Registers_riscv(const void *registers) {
4302 static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit),
4303 "riscv registers do not fit into unw_context_t");
4304 memcpy(&_registers, registers, sizeof(_registers));
4305# if __riscv_xlen == 32
4306 static_assert(sizeof(_registers) == 0x80,
4307 "expected float registers to be at offset 128");
4308# elif __riscv_xlen == 64
4309 static_assert(sizeof(_registers) == 0x100,
4310 "expected float registers to be at offset 256");
4311# else
4312# error "Unexpected float registers."
4313# endif
4314
4315# if defined(__riscv_flen)
4316 memcpy(_floats,
4317 static_cast<const uint8_t *>(registers) + sizeof(_registers),
4318 sizeof(_floats));
4319# endif
4320}
4321
4322inline Registers_riscv::Registers_riscv() {
4323 memset(&_registers, 0, sizeof(_registers));
4324# if defined(__riscv_flen)
4325 memset(&_floats, 0, sizeof(_floats));
4326# endif
4327}
4328
4329inline bool Registers_riscv::validRegister(int regNum) const {
4330 if (regNum == UNW_REG_IP)
4331 return true;
4332 if (regNum == UNW_REG_SP)
4333 return true;
4334 if (regNum < 0)
4335 return false;
4336 if (regNum == UNW_RISCV_VLENB)
4337 return true;
4338 if (regNum > UNW_RISCV_F31)
4339 return false;
4340 return true;
4341}
4342
4343inline reg_t Registers_riscv::getRegister(int regNum) const {
4344 if (regNum == UNW_REG_IP)
4345 return _registers[0];
4346 if (regNum == UNW_REG_SP)
4347 return _registers[2];
4348 if (regNum == UNW_RISCV_X0)
4349 return 0;
4350 if ((regNum > 0) && (regNum < 32))
4351 return _registers[regNum];
4352 if (regNum == UNW_RISCV_VLENB) {
4353 reg_t vlenb;
4354 __asm__ volatile("csrr %0, 0xC22" : "=r"(vlenb));
4355 return vlenb;
4356 }
4357 _LIBUNWIND_ABORT("unsupported riscv register");
4358}
4359
4360inline void Registers_riscv::setRegister(int regNum, reg_t value) {
4361 if (regNum == UNW_REG_IP)
4362 _registers[0] = value;
4363 else if (regNum == UNW_REG_SP)
4364 _registers[2] = value;
4365 else if (regNum == UNW_RISCV_X0)
4366 /* x0 is hardwired to zero */
4367 return;
4368 else if ((regNum > 0) && (regNum < 32))
4369 _registers[regNum] = value;
4370 else
4371 _LIBUNWIND_ABORT("unsupported riscv register");
4372}
4373
4374inline const char *Registers_riscv::getRegisterName(int regNum) {
4375 switch (regNum) {
4376 case UNW_REG_IP:
4377 return "pc";
4378 case UNW_REG_SP:
4379 return "sp";
4380 case UNW_RISCV_X0:
4381 return "zero";
4382 case UNW_RISCV_X1:
4383 return "ra";
4384 case UNW_RISCV_X2:
4385 return "sp";
4386 case UNW_RISCV_X3:
4387 return "gp";
4388 case UNW_RISCV_X4:
4389 return "tp";
4390 case UNW_RISCV_X5:
4391 return "t0";
4392 case UNW_RISCV_X6:
4393 return "t1";
4394 case UNW_RISCV_X7:
4395 return "t2";
4396 case UNW_RISCV_X8:
4397 return "s0";
4398 case UNW_RISCV_X9:
4399 return "s1";
4400 case UNW_RISCV_X10:
4401 return "a0";
4402 case UNW_RISCV_X11:
4403 return "a1";
4404 case UNW_RISCV_X12:
4405 return "a2";
4406 case UNW_RISCV_X13:
4407 return "a3";
4408 case UNW_RISCV_X14:
4409 return "a4";
4410 case UNW_RISCV_X15:
4411 return "a5";
4412 case UNW_RISCV_X16:
4413 return "a6";
4414 case UNW_RISCV_X17:
4415 return "a7";
4416 case UNW_RISCV_X18:
4417 return "s2";
4418 case UNW_RISCV_X19:
4419 return "s3";
4420 case UNW_RISCV_X20:
4421 return "s4";
4422 case UNW_RISCV_X21:
4423 return "s5";
4424 case UNW_RISCV_X22:
4425 return "s6";
4426 case UNW_RISCV_X23:
4427 return "s7";
4428 case UNW_RISCV_X24:
4429 return "s8";
4430 case UNW_RISCV_X25:
4431 return "s9";
4432 case UNW_RISCV_X26:
4433 return "s10";
4434 case UNW_RISCV_X27:
4435 return "s11";
4436 case UNW_RISCV_X28:
4437 return "t3";
4438 case UNW_RISCV_X29:
4439 return "t4";
4440 case UNW_RISCV_X30:
4441 return "t5";
4442 case UNW_RISCV_X31:
4443 return "t6";
4444 case UNW_RISCV_F0:
4445 return "ft0";
4446 case UNW_RISCV_F1:
4447 return "ft1";
4448 case UNW_RISCV_F2:
4449 return "ft2";
4450 case UNW_RISCV_F3:
4451 return "ft3";
4452 case UNW_RISCV_F4:
4453 return "ft4";
4454 case UNW_RISCV_F5:
4455 return "ft5";
4456 case UNW_RISCV_F6:
4457 return "ft6";
4458 case UNW_RISCV_F7:
4459 return "ft7";
4460 case UNW_RISCV_F8:
4461 return "fs0";
4462 case UNW_RISCV_F9:
4463 return "fs1";
4464 case UNW_RISCV_F10:
4465 return "fa0";
4466 case UNW_RISCV_F11:
4467 return "fa1";
4468 case UNW_RISCV_F12:
4469 return "fa2";
4470 case UNW_RISCV_F13:
4471 return "fa3";
4472 case UNW_RISCV_F14:
4473 return "fa4";
4474 case UNW_RISCV_F15:
4475 return "fa5";
4476 case UNW_RISCV_F16:
4477 return "fa6";
4478 case UNW_RISCV_F17:
4479 return "fa7";
4480 case UNW_RISCV_F18:
4481 return "fs2";
4482 case UNW_RISCV_F19:
4483 return "fs3";
4484 case UNW_RISCV_F20:
4485 return "fs4";
4486 case UNW_RISCV_F21:
4487 return "fs5";
4488 case UNW_RISCV_F22:
4489 return "fs6";
4490 case UNW_RISCV_F23:
4491 return "fs7";
4492 case UNW_RISCV_F24:
4493 return "fs8";
4494 case UNW_RISCV_F25:
4495 return "fs9";
4496 case UNW_RISCV_F26:
4497 return "fs10";
4498 case UNW_RISCV_F27:
4499 return "fs11";
4500 case UNW_RISCV_F28:
4501 return "ft8";
4502 case UNW_RISCV_F29:
4503 return "ft9";
4504 case UNW_RISCV_F30:
4505 return "ft10";
4506 case UNW_RISCV_F31:
4507 return "ft11";
4508 case UNW_RISCV_VLENB:
4509 return "vlenb";
4510 default:
4511 return "unknown register";
4512 }
4513}
4514
4515inline bool Registers_riscv::validFloatRegister(int regNum) const {
4516# if defined(__riscv_flen)
4517 if (regNum < UNW_RISCV_F0)
4518 return false;
4519 if (regNum > UNW_RISCV_F31)
4520 return false;
4521 return true;
4522# else
4523 (void)regNum;
4524 return false;
4525# endif
4526}
4527
4528inline fp_t Registers_riscv::getFloatRegister(int regNum) const {
4529# if defined(__riscv_flen)
4530 assert(validFloatRegister(regNum));
4531 return _floats[regNum - UNW_RISCV_F0];
4532# else
4533 (void)regNum;
4534 _LIBUNWIND_ABORT("libunwind not built with float support");
4535# endif
4536}
4537
4538inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) {
4539# if defined(__riscv_flen)
4540 assert(validFloatRegister(regNum));
4541 _floats[regNum - UNW_RISCV_F0] = value;
4542# else
4543 (void)regNum;
4544 (void)value;
4545 _LIBUNWIND_ABORT("libunwind not built with float support");
4546# endif
4547}
4548
4549inline bool Registers_riscv::validVectorRegister(int) const {
4550 return false;
4551}
4552
4553inline v128 Registers_riscv::getVectorRegister(int) const {
4554 _LIBUNWIND_ABORT("no riscv vector register support yet");
4555}
4556
4557inline void Registers_riscv::setVectorRegister(int, v128) {
4558 _LIBUNWIND_ABORT("no riscv vector register support yet");
4559}
4560#endif // _LIBUNWIND_TARGET_RISCV
4561
4562#if defined(_LIBUNWIND_TARGET_VE)
4563/// Registers_ve holds the register state of a thread in a VE process.
4564class _LIBUNWIND_HIDDEN Registers_ve {
4565public:
4566 Registers_ve();
4567 Registers_ve(const void *registers);
4568
4569 typedef uint64_t reg_t;
4570 typedef uint64_t link_reg_t;
4571 typedef const link_reg_t &link_hardened_reg_arg_t;
4572
4573 bool validRegister(int num) const;
4574 uint64_t getRegister(int num) const;
4575 void setRegister(int num, uint64_t value);
4576 bool validFloatRegister(int num) const;
4577 double getFloatRegister(int num) const;
4578 void setFloatRegister(int num, double value);
4579 bool validVectorRegister(int num) const;
4580 v128 getVectorRegister(int num) const;
4581 void setVectorRegister(int num, v128 value);
4582 static const char *getRegisterName(int num);
4583 void jumpto();
4584 static constexpr int lastDwarfRegNum() {
4585 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE;
4586 }
4587 static int getArch() { return REGISTERS_VE; }
4588
4589 uint64_t getSP() const { return _registers.__s[11]; }
4590 void setSP(uint64_t value) { _registers.__s[11] = value; }
4591 uint64_t getIP() const { return _registers.__ic; }
4592 void setIP(uint64_t value) { _registers.__ic = value; }
4593
4594private:
4595 // FIXME: Need to store not only scalar registers but also vector and vector
4596 // mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes
4597 // 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for
4598 // SjLj exception support only, so Registers_ve is not implemented completely.
4599 struct ve_thread_state_t {
4600 uint64_t __s[64]; // s0-s64
4601 uint64_t __ic; // Instruction counter (IC)
4602 uint64_t __vixr; // Vector Index Register
4603 uint64_t __vl; // Vector Length Register
4604 };
4605
4606 ve_thread_state_t _registers; // total 67 registers
4607
4608 // Currently no vector register is preserved.
4609};
4610
4611inline Registers_ve::Registers_ve(const void *registers) {
4612 static_assert((check_fit<Registers_ve, unw_context_t>::does_fit),
4613 "ve registers do not fit into unw_context_t");
4614 memcpy(&_registers, static_cast<const uint8_t *>(registers),
4615 sizeof(_registers));
4616 static_assert(sizeof(_registers) == 536,
4617 "expected vector register offset to be 536");
4618}
4619
4620inline Registers_ve::Registers_ve() {
4621 memset(&_registers, 0, sizeof(_registers));
4622}
4623
4624inline bool Registers_ve::validRegister(int regNum) const {
4625 if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
4626 return true;
4627
4628 switch (regNum) {
4629 case UNW_REG_IP:
4630 case UNW_REG_SP:
4631 case UNW_VE_VIXR:
4632 case UNW_VE_VL:
4633 return true;
4634 default:
4635 return false;
4636 }
4637}
4638
4639inline uint64_t Registers_ve::getRegister(int regNum) const {
4640 if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
4641 return _registers.__s[regNum - UNW_VE_S0];
4642
4643 switch (regNum) {
4644 case UNW_REG_IP:
4645 return _registers.__ic;
4646 case UNW_REG_SP:
4647 return _registers.__s[11];
4648 case UNW_VE_VIXR:
4649 return _registers.__vixr;
4650 case UNW_VE_VL:
4651 return _registers.__vl;
4652 }
4653 _LIBUNWIND_ABORT("unsupported ve register");
4654}
4655
4656inline void Registers_ve::setRegister(int regNum, uint64_t value) {
4657 if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) {
4658 _registers.__s[regNum - UNW_VE_S0] = value;
4659 return;
4660 }
4661
4662 switch (regNum) {
4663 case UNW_REG_IP:
4664 _registers.__ic = value;
4665 return;
4666 case UNW_REG_SP:
4667 _registers.__s[11] = value;
4668 return;
4669 case UNW_VE_VIXR:
4670 _registers.__vixr = value;
4671 return;
4672 case UNW_VE_VL:
4673 _registers.__vl = value;
4674 return;
4675 }
4676 _LIBUNWIND_ABORT("unsupported ve register");
4677}
4678
4679inline bool Registers_ve::validFloatRegister(int /* regNum */) const {
4680 return false;
4681}
4682
4683inline double Registers_ve::getFloatRegister(int /* regNum */) const {
4684 _LIBUNWIND_ABORT("VE doesn't have float registers");
4685}
4686
4687inline void Registers_ve::setFloatRegister(int /* regNum */,
4688 double /* value */) {
4689 _LIBUNWIND_ABORT("VE doesn't have float registers");
4690}
4691
4692inline bool Registers_ve::validVectorRegister(int /* regNum */) const {
4693 return false;
4694}
4695
4696inline v128 Registers_ve::getVectorRegister(int /* regNum */) const {
4697 _LIBUNWIND_ABORT("VE vector support not implemented");
4698}
4699
4700inline void Registers_ve::setVectorRegister(int /* regNum */,
4701 v128 /* value */) {
4702 _LIBUNWIND_ABORT("VE vector support not implemented");
4703}
4704
4705inline const char *Registers_ve::getRegisterName(int regNum) {
4706 switch (regNum) {
4707 case UNW_REG_IP:
4708 return "ip";
4709 case UNW_REG_SP:
4710 return "sp";
4711 case UNW_VE_VIXR:
4712 return "vixr";
4713 case UNW_VE_VL:
4714 return "vl";
4715 case UNW_VE_S0:
4716 return "s0";
4717 case UNW_VE_S1:
4718 return "s1";
4719 case UNW_VE_S2:
4720 return "s2";
4721 case UNW_VE_S3:
4722 return "s3";
4723 case UNW_VE_S4:
4724 return "s4";
4725 case UNW_VE_S5:
4726 return "s5";
4727 case UNW_VE_S6:
4728 return "s6";
4729 case UNW_VE_S7:
4730 return "s7";
4731 case UNW_VE_S8:
4732 return "s8";
4733 case UNW_VE_S9:
4734 return "s9";
4735 case UNW_VE_S10:
4736 return "s10";
4737 case UNW_VE_S11:
4738 return "s11";
4739 case UNW_VE_S12:
4740 return "s12";
4741 case UNW_VE_S13:
4742 return "s13";
4743 case UNW_VE_S14:
4744 return "s14";
4745 case UNW_VE_S15:
4746 return "s15";
4747 case UNW_VE_S16:
4748 return "s16";
4749 case UNW_VE_S17:
4750 return "s17";
4751 case UNW_VE_S18:
4752 return "s18";
4753 case UNW_VE_S19:
4754 return "s19";
4755 case UNW_VE_S20:
4756 return "s20";
4757 case UNW_VE_S21:
4758 return "s21";
4759 case UNW_VE_S22:
4760 return "s22";
4761 case UNW_VE_S23:
4762 return "s23";
4763 case UNW_VE_S24:
4764 return "s24";
4765 case UNW_VE_S25:
4766 return "s25";
4767 case UNW_VE_S26:
4768 return "s26";
4769 case UNW_VE_S27:
4770 return "s27";
4771 case UNW_VE_S28:
4772 return "s28";
4773 case UNW_VE_S29:
4774 return "s29";
4775 case UNW_VE_S30:
4776 return "s30";
4777 case UNW_VE_S31:
4778 return "s31";
4779 case UNW_VE_S32:
4780 return "s32";
4781 case UNW_VE_S33:
4782 return "s33";
4783 case UNW_VE_S34:
4784 return "s34";
4785 case UNW_VE_S35:
4786 return "s35";
4787 case UNW_VE_S36:
4788 return "s36";
4789 case UNW_VE_S37:
4790 return "s37";
4791 case UNW_VE_S38:
4792 return "s38";
4793 case UNW_VE_S39:
4794 return "s39";
4795 case UNW_VE_S40:
4796 return "s40";
4797 case UNW_VE_S41:
4798 return "s41";
4799 case UNW_VE_S42:
4800 return "s42";
4801 case UNW_VE_S43:
4802 return "s43";
4803 case UNW_VE_S44:
4804 return "s44";
4805 case UNW_VE_S45:
4806 return "s45";
4807 case UNW_VE_S46:
4808 return "s46";
4809 case UNW_VE_S47:
4810 return "s47";
4811 case UNW_VE_S48:
4812 return "s48";
4813 case UNW_VE_S49:
4814 return "s49";
4815 case UNW_VE_S50:
4816 return "s50";
4817 case UNW_VE_S51:
4818 return "s51";
4819 case UNW_VE_S52:
4820 return "s52";
4821 case UNW_VE_S53:
4822 return "s53";
4823 case UNW_VE_S54:
4824 return "s54";
4825 case UNW_VE_S55:
4826 return "s55";
4827 case UNW_VE_S56:
4828 return "s56";
4829 case UNW_VE_S57:
4830 return "s57";
4831 case UNW_VE_S58:
4832 return "s58";
4833 case UNW_VE_S59:
4834 return "s59";
4835 case UNW_VE_S60:
4836 return "s60";
4837 case UNW_VE_S61:
4838 return "s61";
4839 case UNW_VE_S62:
4840 return "s62";
4841 case UNW_VE_S63:
4842 return "s63";
4843 case UNW_VE_V0:
4844 return "v0";
4845 case UNW_VE_V1:
4846 return "v1";
4847 case UNW_VE_V2:
4848 return "v2";
4849 case UNW_VE_V3:
4850 return "v3";
4851 case UNW_VE_V4:
4852 return "v4";
4853 case UNW_VE_V5:
4854 return "v5";
4855 case UNW_VE_V6:
4856 return "v6";
4857 case UNW_VE_V7:
4858 return "v7";
4859 case UNW_VE_V8:
4860 return "v8";
4861 case UNW_VE_V9:
4862 return "v9";
4863 case UNW_VE_V10:
4864 return "v10";
4865 case UNW_VE_V11:
4866 return "v11";
4867 case UNW_VE_V12:
4868 return "v12";
4869 case UNW_VE_V13:
4870 return "v13";
4871 case UNW_VE_V14:
4872 return "v14";
4873 case UNW_VE_V15:
4874 return "v15";
4875 case UNW_VE_V16:
4876 return "v16";
4877 case UNW_VE_V17:
4878 return "v17";
4879 case UNW_VE_V18:
4880 return "v18";
4881 case UNW_VE_V19:
4882 return "v19";
4883 case UNW_VE_V20:
4884 return "v20";
4885 case UNW_VE_V21:
4886 return "v21";
4887 case UNW_VE_V22:
4888 return "v22";
4889 case UNW_VE_V23:
4890 return "v23";
4891 case UNW_VE_V24:
4892 return "v24";
4893 case UNW_VE_V25:
4894 return "v25";
4895 case UNW_VE_V26:
4896 return "v26";
4897 case UNW_VE_V27:
4898 return "v27";
4899 case UNW_VE_V28:
4900 return "v28";
4901 case UNW_VE_V29:
4902 return "v29";
4903 case UNW_VE_V30:
4904 return "v30";
4905 case UNW_VE_V31:
4906 return "v31";
4907 case UNW_VE_V32:
4908 return "v32";
4909 case UNW_VE_V33:
4910 return "v33";
4911 case UNW_VE_V34:
4912 return "v34";
4913 case UNW_VE_V35:
4914 return "v35";
4915 case UNW_VE_V36:
4916 return "v36";
4917 case UNW_VE_V37:
4918 return "v37";
4919 case UNW_VE_V38:
4920 return "v38";
4921 case UNW_VE_V39:
4922 return "v39";
4923 case UNW_VE_V40:
4924 return "v40";
4925 case UNW_VE_V41:
4926 return "v41";
4927 case UNW_VE_V42:
4928 return "v42";
4929 case UNW_VE_V43:
4930 return "v43";
4931 case UNW_VE_V44:
4932 return "v44";
4933 case UNW_VE_V45:
4934 return "v45";
4935 case UNW_VE_V46:
4936 return "v46";
4937 case UNW_VE_V47:
4938 return "v47";
4939 case UNW_VE_V48:
4940 return "v48";
4941 case UNW_VE_V49:
4942 return "v49";
4943 case UNW_VE_V50:
4944 return "v50";
4945 case UNW_VE_V51:
4946 return "v51";
4947 case UNW_VE_V52:
4948 return "v52";
4949 case UNW_VE_V53:
4950 return "v53";
4951 case UNW_VE_V54:
4952 return "v54";
4953 case UNW_VE_V55:
4954 return "v55";
4955 case UNW_VE_V56:
4956 return "v56";
4957 case UNW_VE_V57:
4958 return "v57";
4959 case UNW_VE_V58:
4960 return "v58";
4961 case UNW_VE_V59:
4962 return "v59";
4963 case UNW_VE_V60:
4964 return "v60";
4965 case UNW_VE_V61:
4966 return "v61";
4967 case UNW_VE_V62:
4968 return "v62";
4969 case UNW_VE_V63:
4970 return "v63";
4971 case UNW_VE_VM0:
4972 return "vm0";
4973 case UNW_VE_VM1:
4974 return "vm1";
4975 case UNW_VE_VM2:
4976 return "vm2";
4977 case UNW_VE_VM3:
4978 return "vm3";
4979 case UNW_VE_VM4:
4980 return "vm4";
4981 case UNW_VE_VM5:
4982 return "vm5";
4983 case UNW_VE_VM6:
4984 return "vm6";
4985 case UNW_VE_VM7:
4986 return "vm7";
4987 case UNW_VE_VM8:
4988 return "vm8";
4989 case UNW_VE_VM9:
4990 return "vm9";
4991 case UNW_VE_VM10:
4992 return "vm10";
4993 case UNW_VE_VM11:
4994 return "vm11";
4995 case UNW_VE_VM12:
4996 return "vm12";
4997 case UNW_VE_VM13:
4998 return "vm13";
4999 case UNW_VE_VM14:
5000 return "vm14";
5001 case UNW_VE_VM15:
5002 return "vm15";
5003 }
5004 return "unknown register";
5005}
5006#endif // _LIBUNWIND_TARGET_VE
5007
5008#if defined(_LIBUNWIND_TARGET_S390X)
5009/// Registers_s390x holds the register state of a thread in a
5010/// 64-bit Linux on IBM zSystems process.
5011class _LIBUNWIND_HIDDEN Registers_s390x {
5012public:
5013 Registers_s390x();
5014 Registers_s390x(const void *registers);
5015
5016 typedef uint64_t reg_t;
5017 typedef uint64_t link_reg_t;
5018 typedef const link_reg_t &link_hardened_reg_arg_t;
5019
5020 bool validRegister(int num) const;
5021 uint64_t getRegister(int num) const;
5022 void setRegister(int num, uint64_t value);
5023 bool validFloatRegister(int num) const;
5024 double getFloatRegister(int num) const;
5025 void setFloatRegister(int num, double value);
5026 bool validVectorRegister(int num) const;
5027 v128 getVectorRegister(int num) const;
5028 void setVectorRegister(int num, v128 value);
5029 static const char *getRegisterName(int num);
5030 void jumpto();
5031 static constexpr int lastDwarfRegNum() {
5032 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X;
5033 }
5034 static int getArch() { return REGISTERS_S390X; }
5035
5036 uint64_t getSP() const { return _registers.__gpr[15]; }
5037 void setSP(uint64_t value) { _registers.__gpr[15] = value; }
5038 uint64_t getIP() const { return _registers.__pswa; }
5039 void setIP(uint64_t value) { _registers.__pswa = value; }
5040
5041private:
5042 struct s390x_thread_state_t {
5043 uint64_t __pswm; // Problem Status Word: Mask
5044 uint64_t __pswa; // Problem Status Word: Address (PC)
5045 uint64_t __gpr[16]; // General Purpose Registers
5046 double __fpr[16]; // Floating-Point Registers
5047 };
5048
5049 s390x_thread_state_t _registers;
5050};
5051
5052inline Registers_s390x::Registers_s390x(const void *registers) {
5053 static_assert((check_fit<Registers_s390x, unw_context_t>::does_fit),
5054 "s390x registers do not fit into unw_context_t");
5055 memcpy(&_registers, static_cast<const uint8_t *>(registers),
5056 sizeof(_registers));
5057}
5058
5059inline Registers_s390x::Registers_s390x() {
5060 memset(&_registers, 0, sizeof(_registers));
5061}
5062
5063inline bool Registers_s390x::validRegister(int regNum) const {
5064 switch (regNum) {
5065 case UNW_S390X_PSWM:
5066 case UNW_S390X_PSWA:
5067 case UNW_REG_IP:
5068 case UNW_REG_SP:
5069 return true;
5070 }
5071
5072 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
5073 return true;
5074
5075 return false;
5076}
5077
5078inline uint64_t Registers_s390x::getRegister(int regNum) const {
5079 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
5080 return _registers.__gpr[regNum - UNW_S390X_R0];
5081
5082 switch (regNum) {
5083 case UNW_S390X_PSWM:
5084 return _registers.__pswm;
5085 case UNW_S390X_PSWA:
5086 case UNW_REG_IP:
5087 return _registers.__pswa;
5088 case UNW_REG_SP:
5089 return _registers.__gpr[15];
5090 }
5091 _LIBUNWIND_ABORT("unsupported s390x register");
5092}
5093
5094inline void Registers_s390x::setRegister(int regNum, uint64_t value) {
5095 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) {
5096 _registers.__gpr[regNum - UNW_S390X_R0] = value;
5097 return;
5098 }
5099
5100 switch (regNum) {
5101 case UNW_S390X_PSWM:
5102 _registers.__pswm = value;
5103 return;
5104 case UNW_S390X_PSWA:
5105 case UNW_REG_IP:
5106 _registers.__pswa = value;
5107 return;
5108 case UNW_REG_SP:
5109 _registers.__gpr[15] = value;
5110 return;
5111 }
5112 _LIBUNWIND_ABORT("unsupported s390x register");
5113}
5114
5115inline bool Registers_s390x::validFloatRegister(int regNum) const {
5116 return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15;
5117}
5118
5119inline double Registers_s390x::getFloatRegister(int regNum) const {
5120 // NOTE: FPR DWARF register numbers are not consecutive.
5121 switch (regNum) {
5122 case UNW_S390X_F0:
5123 return _registers.__fpr[0];
5124 case UNW_S390X_F1:
5125 return _registers.__fpr[1];
5126 case UNW_S390X_F2:
5127 return _registers.__fpr[2];
5128 case UNW_S390X_F3:
5129 return _registers.__fpr[3];
5130 case UNW_S390X_F4:
5131 return _registers.__fpr[4];
5132 case UNW_S390X_F5:
5133 return _registers.__fpr[5];
5134 case UNW_S390X_F6:
5135 return _registers.__fpr[6];
5136 case UNW_S390X_F7:
5137 return _registers.__fpr[7];
5138 case UNW_S390X_F8:
5139 return _registers.__fpr[8];
5140 case UNW_S390X_F9:
5141 return _registers.__fpr[9];
5142 case UNW_S390X_F10:
5143 return _registers.__fpr[10];
5144 case UNW_S390X_F11:
5145 return _registers.__fpr[11];
5146 case UNW_S390X_F12:
5147 return _registers.__fpr[12];
5148 case UNW_S390X_F13:
5149 return _registers.__fpr[13];
5150 case UNW_S390X_F14:
5151 return _registers.__fpr[14];
5152 case UNW_S390X_F15:
5153 return _registers.__fpr[15];
5154 }
5155 _LIBUNWIND_ABORT("unsupported s390x register");
5156}
5157
5158inline void Registers_s390x::setFloatRegister(int regNum, double value) {
5159 // NOTE: FPR DWARF register numbers are not consecutive.
5160 switch (regNum) {
5161 case UNW_S390X_F0:
5162 _registers.__fpr[0] = value;
5163 return;
5164 case UNW_S390X_F1:
5165 _registers.__fpr[1] = value;
5166 return;
5167 case UNW_S390X_F2:
5168 _registers.__fpr[2] = value;
5169 return;
5170 case UNW_S390X_F3:
5171 _registers.__fpr[3] = value;
5172 return;
5173 case UNW_S390X_F4:
5174 _registers.__fpr[4] = value;
5175 return;
5176 case UNW_S390X_F5:
5177 _registers.__fpr[5] = value;
5178 return;
5179 case UNW_S390X_F6:
5180 _registers.__fpr[6] = value;
5181 return;
5182 case UNW_S390X_F7:
5183 _registers.__fpr[7] = value;
5184 return;
5185 case UNW_S390X_F8:
5186 _registers.__fpr[8] = value;
5187 return;
5188 case UNW_S390X_F9:
5189 _registers.__fpr[9] = value;
5190 return;
5191 case UNW_S390X_F10:
5192 _registers.__fpr[10] = value;
5193 return;
5194 case UNW_S390X_F11:
5195 _registers.__fpr[11] = value;
5196 return;
5197 case UNW_S390X_F12:
5198 _registers.__fpr[12] = value;
5199 return;
5200 case UNW_S390X_F13:
5201 _registers.__fpr[13] = value;
5202 return;
5203 case UNW_S390X_F14:
5204 _registers.__fpr[14] = value;
5205 return;
5206 case UNW_S390X_F15:
5207 _registers.__fpr[15] = value;
5208 return;
5209 }
5210 _LIBUNWIND_ABORT("unsupported s390x register");
5211}
5212
5213inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
5214 return false;
5215}
5216
5217inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const {
5218 _LIBUNWIND_ABORT("s390x vector support not implemented");
5219}
5220
5221inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) {
5222 _LIBUNWIND_ABORT("s390x vector support not implemented");
5223}
5224
5225inline const char *Registers_s390x::getRegisterName(int regNum) {
5226 switch (regNum) {
5227 case UNW_REG_IP:
5228 return "ip";
5229 case UNW_REG_SP:
5230 return "sp";
5231 case UNW_S390X_R0:
5232 return "r0";
5233 case UNW_S390X_R1:
5234 return "r1";
5235 case UNW_S390X_R2:
5236 return "r2";
5237 case UNW_S390X_R3:
5238 return "r3";
5239 case UNW_S390X_R4:
5240 return "r4";
5241 case UNW_S390X_R5:
5242 return "r5";
5243 case UNW_S390X_R6:
5244 return "r6";
5245 case UNW_S390X_R7:
5246 return "r7";
5247 case UNW_S390X_R8:
5248 return "r8";
5249 case UNW_S390X_R9:
5250 return "r9";
5251 case UNW_S390X_R10:
5252 return "r10";
5253 case UNW_S390X_R11:
5254 return "r11";
5255 case UNW_S390X_R12:
5256 return "r12";
5257 case UNW_S390X_R13:
5258 return "r13";
5259 case UNW_S390X_R14:
5260 return "r14";
5261 case UNW_S390X_R15:
5262 return "r15";
5263 case UNW_S390X_F0:
5264 return "f0";
5265 case UNW_S390X_F1:
5266 return "f1";
5267 case UNW_S390X_F2:
5268 return "f2";
5269 case UNW_S390X_F3:
5270 return "f3";
5271 case UNW_S390X_F4:
5272 return "f4";
5273 case UNW_S390X_F5:
5274 return "f5";
5275 case UNW_S390X_F6:
5276 return "f6";
5277 case UNW_S390X_F7:
5278 return "f7";
5279 case UNW_S390X_F8:
5280 return "f8";
5281 case UNW_S390X_F9:
5282 return "f9";
5283 case UNW_S390X_F10:
5284 return "f10";
5285 case UNW_S390X_F11:
5286 return "f11";
5287 case UNW_S390X_F12:
5288 return "f12";
5289 case UNW_S390X_F13:
5290 return "f13";
5291 case UNW_S390X_F14:
5292 return "f14";
5293 case UNW_S390X_F15:
5294 return "f15";
5295 }
5296 return "unknown register";
5297}
5298#endif // _LIBUNWIND_TARGET_S390X
5299
5300#if defined(_LIBUNWIND_TARGET_LOONGARCH)
5301/// Registers_loongarch holds the register state of a thread in a 64-bit
5302/// LoongArch process.
5303class _LIBUNWIND_HIDDEN Registers_loongarch {
5304public:
5305 Registers_loongarch();
5306 Registers_loongarch(const void *registers);
5307
5308 typedef uint64_t reg_t;
5309 typedef uint64_t link_reg_t;
5310 typedef const link_reg_t &link_hardened_reg_arg_t;
5311
5312 bool validRegister(int num) const;
5313 uint64_t getRegister(int num) const;
5314 void setRegister(int num, uint64_t value);
5315 bool validFloatRegister(int num) const;
5316 double getFloatRegister(int num) const;
5317 void setFloatRegister(int num, double value);
5318 bool validVectorRegister(int num) const;
5319 v128 getVectorRegister(int num) const;
5320 void setVectorRegister(int num, v128 value);
5321 static const char *getRegisterName(int num);
5322 void jumpto();
5323 static constexpr int lastDwarfRegNum() {
5324 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH;
5325 }
5326 static int getArch() { return REGISTERS_LOONGARCH; }
5327
5328 uint64_t getSP() const { return _registers.__r[3]; }
5329 void setSP(uint64_t value) { _registers.__r[3] = value; }
5330 uint64_t getIP() const { return _registers.__pc; }
5331 void setIP(uint64_t value) { _registers.__pc = value; }
5332
5333private:
5334 struct loongarch_thread_state_t {
5335 uint64_t __r[32];
5336 uint64_t __pc;
5337 };
5338
5339 loongarch_thread_state_t _registers;
5340#if __loongarch_frlen == 64
5341 double _floats[32];
5342#endif
5343};
5344
5345inline Registers_loongarch::Registers_loongarch(const void *registers) {
5346 static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit),
5347 "loongarch registers do not fit into unw_context_t");
5348 memcpy(&_registers, registers, sizeof(_registers));
5349 static_assert(sizeof(_registers) == 0x108,
5350 "expected float registers to be at offset 264");
5351#if __loongarch_frlen == 64
5352 memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers),
5353 sizeof(_floats));
5354#endif
5355}
5356
5357inline Registers_loongarch::Registers_loongarch() {
5358 memset(&_registers, 0, sizeof(_registers));
5359#if __loongarch_frlen == 64
5360 memset(&_floats, 0, sizeof(_floats));
5361#endif
5362}
5363
5364inline bool Registers_loongarch::validRegister(int regNum) const {
5365 if (regNum == UNW_REG_IP || regNum == UNW_REG_SP)
5366 return true;
5367 if (regNum < 0 || regNum > UNW_LOONGARCH_F31)
5368 return false;
5369 return true;
5370}
5371
5372inline uint64_t Registers_loongarch::getRegister(int regNum) const {
5373 if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
5374 return _registers.__r[regNum - UNW_LOONGARCH_R0];
5375
5376 if (regNum == UNW_REG_IP)
5377 return _registers.__pc;
5378 if (regNum == UNW_REG_SP)
5379 return _registers.__r[3];
5380 _LIBUNWIND_ABORT("unsupported loongarch register");
5381}
5382
5383inline void Registers_loongarch::setRegister(int regNum, uint64_t value) {
5384 if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
5385 _registers.__r[regNum - UNW_LOONGARCH_R0] = value;
5386 else if (regNum == UNW_REG_IP)
5387 _registers.__pc = value;
5388 else if (regNum == UNW_REG_SP)
5389 _registers.__r[3] = value;
5390 else
5391 _LIBUNWIND_ABORT("unsupported loongarch register");
5392}
5393
5394inline const char *Registers_loongarch::getRegisterName(int regNum) {
5395 switch (regNum) {
5396 case UNW_REG_IP:
5397 return "$pc";
5398 case UNW_REG_SP:
5399 return "$sp";
5400 case UNW_LOONGARCH_R0:
5401 return "$r0";
5402 case UNW_LOONGARCH_R1:
5403 return "$r1";
5404 case UNW_LOONGARCH_R2:
5405 return "$r2";
5406 case UNW_LOONGARCH_R3:
5407 return "$r3";
5408 case UNW_LOONGARCH_R4:
5409 return "$r4";
5410 case UNW_LOONGARCH_R5:
5411 return "$r5";
5412 case UNW_LOONGARCH_R6:
5413 return "$r6";
5414 case UNW_LOONGARCH_R7:
5415 return "$r7";
5416 case UNW_LOONGARCH_R8:
5417 return "$r8";
5418 case UNW_LOONGARCH_R9:
5419 return "$r9";
5420 case UNW_LOONGARCH_R10:
5421 return "$r10";
5422 case UNW_LOONGARCH_R11:
5423 return "$r11";
5424 case UNW_LOONGARCH_R12:
5425 return "$r12";
5426 case UNW_LOONGARCH_R13:
5427 return "$r13";
5428 case UNW_LOONGARCH_R14:
5429 return "$r14";
5430 case UNW_LOONGARCH_R15:
5431 return "$r15";
5432 case UNW_LOONGARCH_R16:
5433 return "$r16";
5434 case UNW_LOONGARCH_R17:
5435 return "$r17";
5436 case UNW_LOONGARCH_R18:
5437 return "$r18";
5438 case UNW_LOONGARCH_R19:
5439 return "$r19";
5440 case UNW_LOONGARCH_R20:
5441 return "$r20";
5442 case UNW_LOONGARCH_R21:
5443 return "$r21";
5444 case UNW_LOONGARCH_R22:
5445 return "$r22";
5446 case UNW_LOONGARCH_R23:
5447 return "$r23";
5448 case UNW_LOONGARCH_R24:
5449 return "$r24";
5450 case UNW_LOONGARCH_R25:
5451 return "$r25";
5452 case UNW_LOONGARCH_R26:
5453 return "$r26";
5454 case UNW_LOONGARCH_R27:
5455 return "$r27";
5456 case UNW_LOONGARCH_R28:
5457 return "$r28";
5458 case UNW_LOONGARCH_R29:
5459 return "$r29";
5460 case UNW_LOONGARCH_R30:
5461 return "$r30";
5462 case UNW_LOONGARCH_R31:
5463 return "$r31";
5464 case UNW_LOONGARCH_F0:
5465 return "$f0";
5466 case UNW_LOONGARCH_F1:
5467 return "$f1";
5468 case UNW_LOONGARCH_F2:
5469 return "$f2";
5470 case UNW_LOONGARCH_F3:
5471 return "$f3";
5472 case UNW_LOONGARCH_F4:
5473 return "$f4";
5474 case UNW_LOONGARCH_F5:
5475 return "$f5";
5476 case UNW_LOONGARCH_F6:
5477 return "$f6";
5478 case UNW_LOONGARCH_F7:
5479 return "$f7";
5480 case UNW_LOONGARCH_F8:
5481 return "$f8";
5482 case UNW_LOONGARCH_F9:
5483 return "$f9";
5484 case UNW_LOONGARCH_F10:
5485 return "$f10";
5486 case UNW_LOONGARCH_F11:
5487 return "$f11";
5488 case UNW_LOONGARCH_F12:
5489 return "$f12";
5490 case UNW_LOONGARCH_F13:
5491 return "$f13";
5492 case UNW_LOONGARCH_F14:
5493 return "$f14";
5494 case UNW_LOONGARCH_F15:
5495 return "$f15";
5496 case UNW_LOONGARCH_F16:
5497 return "$f16";
5498 case UNW_LOONGARCH_F17:
5499 return "$f17";
5500 case UNW_LOONGARCH_F18:
5501 return "$f18";
5502 case UNW_LOONGARCH_F19:
5503 return "$f19";
5504 case UNW_LOONGARCH_F20:
5505 return "$f20";
5506 case UNW_LOONGARCH_F21:
5507 return "$f21";
5508 case UNW_LOONGARCH_F22:
5509 return "$f22";
5510 case UNW_LOONGARCH_F23:
5511 return "$f23";
5512 case UNW_LOONGARCH_F24:
5513 return "$f24";
5514 case UNW_LOONGARCH_F25:
5515 return "$f25";
5516 case UNW_LOONGARCH_F26:
5517 return "$f26";
5518 case UNW_LOONGARCH_F27:
5519 return "$f27";
5520 case UNW_LOONGARCH_F28:
5521 return "$f28";
5522 case UNW_LOONGARCH_F29:
5523 return "$f29";
5524 case UNW_LOONGARCH_F30:
5525 return "$f30";
5526 case UNW_LOONGARCH_F31:
5527 return "$f31";
5528 default:
5529 return "unknown register";
5530 }
5531}
5532
5533inline bool Registers_loongarch::validFloatRegister(int regNum) const {
5534 if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31)
5535 return false;
5536 return true;
5537}
5538
5539inline double Registers_loongarch::getFloatRegister(int regNum) const {
5540#if __loongarch_frlen == 64
5541 assert(validFloatRegister(regNum));
5542 return _floats[regNum - UNW_LOONGARCH_F0];
5543#else
5544 _LIBUNWIND_ABORT("libunwind not built with float support");
5545#endif
5546}
5547
5548inline void Registers_loongarch::setFloatRegister(int regNum, double value) {
5549#if __loongarch_frlen == 64
5550 assert(validFloatRegister(regNum));
5551 _floats[regNum - UNW_LOONGARCH_F0] = value;
5552#else
5553 _LIBUNWIND_ABORT("libunwind not built with float support");
5554#endif
5555}
5556
5557inline bool Registers_loongarch::validVectorRegister(int) const {
5558 return false;
5559}
5560
5561inline v128 Registers_loongarch::getVectorRegister(int) const {
5562 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5563}
5564
5565inline void Registers_loongarch::setVectorRegister(int, v128) {
5566 _LIBUNWIND_ABORT("loongarch vector support not implemented");
5567}
5568#endif //_LIBUNWIND_TARGET_LOONGARCH
5569
5570} // namespace libunwind
5571
5572#endif // __REGISTERS_HPP__
5573