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