1 //===----------------------------- Registers.hpp --------------------------===//
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 "libunwind.h"
19 #include "config.h"
20
21 namespace libunwind {
22
23 // For emulating 128-bit registers
24 struct v128 { uint32_t vec[4]; };
25
26 enum {
27 REGISTERS_X86,
28 REGISTERS_X86_64,
29 REGISTERS_PPC,
30 REGISTERS_PPC64,
31 REGISTERS_ARM64,
32 REGISTERS_ARM,
33 REGISTERS_OR1K,
34 REGISTERS_MIPS_O32,
35 REGISTERS_MIPS_NEWABI,
36 REGISTERS_SPARC,
37 REGISTERS_HEXAGON,
38 REGISTERS_RISCV,
39 };
40
41 #if defined(_LIBUNWIND_TARGET_I386)
42 class _LIBUNWIND_HIDDEN Registers_x86;
43 extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
44 /// Registers_x86 holds the register state of a thread in a 32-bit intel
45 /// process.
46 class _LIBUNWIND_HIDDEN Registers_x86 {
47 public:
48 Registers_x86();
49 Registers_x86(const void *registers);
50
51 bool validRegister(int num) const;
52 uint32_t getRegister(int num) const;
53 void setRegister(int num, uint32_t value);
validFloatRegister(int) const54 bool validFloatRegister(int) const { return false; }
55 double getFloatRegister(int num) const;
56 void setFloatRegister(int num, double value);
validVectorRegister(int) const57 bool validVectorRegister(int) const { return false; }
58 v128 getVectorRegister(int num) const;
59 void setVectorRegister(int num, v128 value);
60 static const char *getRegisterName(int num);
jumpto()61 void jumpto() { __libunwind_Registers_x86_jumpto(this); }
lastDwarfRegNum()62 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }
getArch()63 static int getArch() { return REGISTERS_X86; }
64
getSP() const65 uint32_t getSP() const { return _registers.__esp; }
setSP(uint32_t value)66 void setSP(uint32_t value) { _registers.__esp = value; }
getIP() const67 uint32_t getIP() const { return _registers.__eip; }
setIP(uint32_t value)68 void setIP(uint32_t value) { _registers.__eip = value; }
getEBP() const69 uint32_t getEBP() const { return _registers.__ebp; }
setEBP(uint32_t value)70 void setEBP(uint32_t value) { _registers.__ebp = value; }
getEBX() const71 uint32_t getEBX() const { return _registers.__ebx; }
setEBX(uint32_t value)72 void setEBX(uint32_t value) { _registers.__ebx = value; }
getECX() const73 uint32_t getECX() const { return _registers.__ecx; }
setECX(uint32_t value)74 void setECX(uint32_t value) { _registers.__ecx = value; }
getEDX() const75 uint32_t getEDX() const { return _registers.__edx; }
setEDX(uint32_t value)76 void setEDX(uint32_t value) { _registers.__edx = value; }
getESI() const77 uint32_t getESI() const { return _registers.__esi; }
setESI(uint32_t value)78 void setESI(uint32_t value) { _registers.__esi = value; }
getEDI() const79 uint32_t getEDI() const { return _registers.__edi; }
setEDI(uint32_t value)80 void setEDI(uint32_t value) { _registers.__edi = value; }
81
82 private:
83 struct GPRs {
84 unsigned int __eax;
85 unsigned int __ebx;
86 unsigned int __ecx;
87 unsigned int __edx;
88 unsigned int __edi;
89 unsigned int __esi;
90 unsigned int __ebp;
91 unsigned int __esp;
92 unsigned int __ss;
93 unsigned int __eflags;
94 unsigned int __eip;
95 unsigned int __cs;
96 unsigned int __ds;
97 unsigned int __es;
98 unsigned int __fs;
99 unsigned int __gs;
100 };
101
102 GPRs _registers;
103 };
104
Registers_x86(const void * registers)105 inline Registers_x86::Registers_x86(const void *registers) {
106 static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
107 "x86 registers do not fit into unw_context_t");
108 memcpy(&_registers, registers, sizeof(_registers));
109 }
110
Registers_x86()111 inline Registers_x86::Registers_x86() {
112 memset(&_registers, 0, sizeof(_registers));
113 }
114
validRegister(int regNum) const115 inline bool Registers_x86::validRegister(int regNum) const {
116 if (regNum == UNW_REG_IP)
117 return true;
118 if (regNum == UNW_REG_SP)
119 return true;
120 if (regNum < 0)
121 return false;
122 if (regNum > 7)
123 return false;
124 return true;
125 }
126
getRegister(int regNum) const127 inline uint32_t Registers_x86::getRegister(int regNum) const {
128 switch (regNum) {
129 case UNW_REG_IP:
130 return _registers.__eip;
131 case UNW_REG_SP:
132 return _registers.__esp;
133 case UNW_X86_EAX:
134 return _registers.__eax;
135 case UNW_X86_ECX:
136 return _registers.__ecx;
137 case UNW_X86_EDX:
138 return _registers.__edx;
139 case UNW_X86_EBX:
140 return _registers.__ebx;
141 #if !defined(__APPLE__)
142 case UNW_X86_ESP:
143 #else
144 case UNW_X86_EBP:
145 #endif
146 return _registers.__ebp;
147 #if !defined(__APPLE__)
148 case UNW_X86_EBP:
149 #else
150 case UNW_X86_ESP:
151 #endif
152 return _registers.__esp;
153 case UNW_X86_ESI:
154 return _registers.__esi;
155 case UNW_X86_EDI:
156 return _registers.__edi;
157 }
158 _LIBUNWIND_ABORT("unsupported x86 register");
159 }
160
setRegister(int regNum,uint32_t value)161 inline void Registers_x86::setRegister(int regNum, uint32_t value) {
162 switch (regNum) {
163 case UNW_REG_IP:
164 _registers.__eip = value;
165 return;
166 case UNW_REG_SP:
167 _registers.__esp = value;
168 return;
169 case UNW_X86_EAX:
170 _registers.__eax = value;
171 return;
172 case UNW_X86_ECX:
173 _registers.__ecx = value;
174 return;
175 case UNW_X86_EDX:
176 _registers.__edx = value;
177 return;
178 case UNW_X86_EBX:
179 _registers.__ebx = value;
180 return;
181 #if !defined(__APPLE__)
182 case UNW_X86_ESP:
183 #else
184 case UNW_X86_EBP:
185 #endif
186 _registers.__ebp = value;
187 return;
188 #if !defined(__APPLE__)
189 case UNW_X86_EBP:
190 #else
191 case UNW_X86_ESP:
192 #endif
193 _registers.__esp = value;
194 return;
195 case UNW_X86_ESI:
196 _registers.__esi = value;
197 return;
198 case UNW_X86_EDI:
199 _registers.__edi = value;
200 return;
201 }
202 _LIBUNWIND_ABORT("unsupported x86 register");
203 }
204
getRegisterName(int regNum)205 inline const char *Registers_x86::getRegisterName(int regNum) {
206 switch (regNum) {
207 case UNW_REG_IP:
208 return "ip";
209 case UNW_REG_SP:
210 return "esp";
211 case UNW_X86_EAX:
212 return "eax";
213 case UNW_X86_ECX:
214 return "ecx";
215 case UNW_X86_EDX:
216 return "edx";
217 case UNW_X86_EBX:
218 return "ebx";
219 case UNW_X86_EBP:
220 return "ebp";
221 case UNW_X86_ESP:
222 return "esp";
223 case UNW_X86_ESI:
224 return "esi";
225 case UNW_X86_EDI:
226 return "edi";
227 default:
228 return "unknown register";
229 }
230 }
231
getFloatRegister(int) const232 inline double Registers_x86::getFloatRegister(int) const {
233 _LIBUNWIND_ABORT("no x86 float registers");
234 }
235
setFloatRegister(int,double)236 inline void Registers_x86::setFloatRegister(int, double) {
237 _LIBUNWIND_ABORT("no x86 float registers");
238 }
239
getVectorRegister(int) const240 inline v128 Registers_x86::getVectorRegister(int) const {
241 _LIBUNWIND_ABORT("no x86 vector registers");
242 }
243
setVectorRegister(int,v128)244 inline void Registers_x86::setVectorRegister(int, v128) {
245 _LIBUNWIND_ABORT("no x86 vector registers");
246 }
247 #endif // _LIBUNWIND_TARGET_I386
248
249
250 #if defined(_LIBUNWIND_TARGET_X86_64)
251 /// Registers_x86_64 holds the register state of a thread in a 64-bit intel
252 /// process.
253 class _LIBUNWIND_HIDDEN Registers_x86_64;
254 extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
255 class _LIBUNWIND_HIDDEN Registers_x86_64 {
256 public:
257 Registers_x86_64();
258 Registers_x86_64(const void *registers);
259
260 bool validRegister(int num) const;
261 uint64_t getRegister(int num) const;
262 void setRegister(int num, uint64_t value);
validFloatRegister(int) const263 bool validFloatRegister(int) const { return false; }
264 double getFloatRegister(int num) const;
265 void setFloatRegister(int num, double value);
266 bool validVectorRegister(int) const;
267 v128 getVectorRegister(int num) const;
268 void setVectorRegister(int num, v128 value);
269 static const char *getRegisterName(int num);
jumpto()270 void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }
lastDwarfRegNum()271 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }
getArch()272 static int getArch() { return REGISTERS_X86_64; }
273
getSP() const274 uint64_t getSP() const { return _registers.__rsp; }
setSP(uint64_t value)275 void setSP(uint64_t value) { _registers.__rsp = value; }
getIP() const276 uint64_t getIP() const { return _registers.__rip; }
setIP(uint64_t value)277 void setIP(uint64_t value) { _registers.__rip = value; }
getRBP() const278 uint64_t getRBP() const { return _registers.__rbp; }
setRBP(uint64_t value)279 void setRBP(uint64_t value) { _registers.__rbp = value; }
getRBX() const280 uint64_t getRBX() const { return _registers.__rbx; }
setRBX(uint64_t value)281 void setRBX(uint64_t value) { _registers.__rbx = value; }
getR12() const282 uint64_t getR12() const { return _registers.__r12; }
setR12(uint64_t value)283 void setR12(uint64_t value) { _registers.__r12 = value; }
getR13() const284 uint64_t getR13() const { return _registers.__r13; }
setR13(uint64_t value)285 void setR13(uint64_t value) { _registers.__r13 = value; }
getR14() const286 uint64_t getR14() const { return _registers.__r14; }
setR14(uint64_t value)287 void setR14(uint64_t value) { _registers.__r14 = value; }
getR15() const288 uint64_t getR15() const { return _registers.__r15; }
setR15(uint64_t value)289 void setR15(uint64_t value) { _registers.__r15 = value; }
290
291 private:
292 struct GPRs {
293 uint64_t __rax;
294 uint64_t __rbx;
295 uint64_t __rcx;
296 uint64_t __rdx;
297 uint64_t __rdi;
298 uint64_t __rsi;
299 uint64_t __rbp;
300 uint64_t __rsp;
301 uint64_t __r8;
302 uint64_t __r9;
303 uint64_t __r10;
304 uint64_t __r11;
305 uint64_t __r12;
306 uint64_t __r13;
307 uint64_t __r14;
308 uint64_t __r15;
309 uint64_t __rip;
310 uint64_t __rflags;
311 uint64_t __cs;
312 uint64_t __fs;
313 uint64_t __gs;
314 #if defined(_WIN64)
315 uint64_t __padding; // 16-byte align
316 #endif
317 };
318 GPRs _registers;
319 #if defined(_WIN64)
320 v128 _xmm[16];
321 #endif
322 };
323
Registers_x86_64(const void * registers)324 inline Registers_x86_64::Registers_x86_64(const void *registers) {
325 static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
326 "x86_64 registers do not fit into unw_context_t");
327 memcpy(&_registers, registers, sizeof(_registers));
328 }
329
Registers_x86_64()330 inline Registers_x86_64::Registers_x86_64() {
331 memset(&_registers, 0, sizeof(_registers));
332 }
333
validRegister(int regNum) const334 inline bool Registers_x86_64::validRegister(int regNum) const {
335 if (regNum == UNW_REG_IP)
336 return true;
337 if (regNum == UNW_REG_SP)
338 return true;
339 if (regNum < 0)
340 return false;
341 if (regNum > 15)
342 return false;
343 return true;
344 }
345
getRegister(int regNum) const346 inline uint64_t Registers_x86_64::getRegister(int regNum) const {
347 switch (regNum) {
348 case UNW_REG_IP:
349 return _registers.__rip;
350 case UNW_REG_SP:
351 return _registers.__rsp;
352 case UNW_X86_64_RAX:
353 return _registers.__rax;
354 case UNW_X86_64_RDX:
355 return _registers.__rdx;
356 case UNW_X86_64_RCX:
357 return _registers.__rcx;
358 case UNW_X86_64_RBX:
359 return _registers.__rbx;
360 case UNW_X86_64_RSI:
361 return _registers.__rsi;
362 case UNW_X86_64_RDI:
363 return _registers.__rdi;
364 case UNW_X86_64_RBP:
365 return _registers.__rbp;
366 case UNW_X86_64_RSP:
367 return _registers.__rsp;
368 case UNW_X86_64_R8:
369 return _registers.__r8;
370 case UNW_X86_64_R9:
371 return _registers.__r9;
372 case UNW_X86_64_R10:
373 return _registers.__r10;
374 case UNW_X86_64_R11:
375 return _registers.__r11;
376 case UNW_X86_64_R12:
377 return _registers.__r12;
378 case UNW_X86_64_R13:
379 return _registers.__r13;
380 case UNW_X86_64_R14:
381 return _registers.__r14;
382 case UNW_X86_64_R15:
383 return _registers.__r15;
384 }
385 _LIBUNWIND_ABORT("unsupported x86_64 register");
386 }
387
setRegister(int regNum,uint64_t value)388 inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
389 switch (regNum) {
390 case UNW_REG_IP:
391 _registers.__rip = value;
392 return;
393 case UNW_REG_SP:
394 _registers.__rsp = value;
395 return;
396 case UNW_X86_64_RAX:
397 _registers.__rax = value;
398 return;
399 case UNW_X86_64_RDX:
400 _registers.__rdx = value;
401 return;
402 case UNW_X86_64_RCX:
403 _registers.__rcx = value;
404 return;
405 case UNW_X86_64_RBX:
406 _registers.__rbx = value;
407 return;
408 case UNW_X86_64_RSI:
409 _registers.__rsi = value;
410 return;
411 case UNW_X86_64_RDI:
412 _registers.__rdi = value;
413 return;
414 case UNW_X86_64_RBP:
415 _registers.__rbp = value;
416 return;
417 case UNW_X86_64_RSP:
418 _registers.__rsp = value;
419 return;
420 case UNW_X86_64_R8:
421 _registers.__r8 = value;
422 return;
423 case UNW_X86_64_R9:
424 _registers.__r9 = value;
425 return;
426 case UNW_X86_64_R10:
427 _registers.__r10 = value;
428 return;
429 case UNW_X86_64_R11:
430 _registers.__r11 = value;
431 return;
432 case UNW_X86_64_R12:
433 _registers.__r12 = value;
434 return;
435 case UNW_X86_64_R13:
436 _registers.__r13 = value;
437 return;
438 case UNW_X86_64_R14:
439 _registers.__r14 = value;
440 return;
441 case UNW_X86_64_R15:
442 _registers.__r15 = value;
443 return;
444 }
445 _LIBUNWIND_ABORT("unsupported x86_64 register");
446 }
447
getRegisterName(int regNum)448 inline const char *Registers_x86_64::getRegisterName(int regNum) {
449 switch (regNum) {
450 case UNW_REG_IP:
451 return "rip";
452 case UNW_REG_SP:
453 return "rsp";
454 case UNW_X86_64_RAX:
455 return "rax";
456 case UNW_X86_64_RDX:
457 return "rdx";
458 case UNW_X86_64_RCX:
459 return "rcx";
460 case UNW_X86_64_RBX:
461 return "rbx";
462 case UNW_X86_64_RSI:
463 return "rsi";
464 case UNW_X86_64_RDI:
465 return "rdi";
466 case UNW_X86_64_RBP:
467 return "rbp";
468 case UNW_X86_64_RSP:
469 return "rsp";
470 case UNW_X86_64_R8:
471 return "r8";
472 case UNW_X86_64_R9:
473 return "r9";
474 case UNW_X86_64_R10:
475 return "r10";
476 case UNW_X86_64_R11:
477 return "r11";
478 case UNW_X86_64_R12:
479 return "r12";
480 case UNW_X86_64_R13:
481 return "r13";
482 case UNW_X86_64_R14:
483 return "r14";
484 case UNW_X86_64_R15:
485 return "r15";
486 case UNW_X86_64_XMM0:
487 return "xmm0";
488 case UNW_X86_64_XMM1:
489 return "xmm1";
490 case UNW_X86_64_XMM2:
491 return "xmm2";
492 case UNW_X86_64_XMM3:
493 return "xmm3";
494 case UNW_X86_64_XMM4:
495 return "xmm4";
496 case UNW_X86_64_XMM5:
497 return "xmm5";
498 case UNW_X86_64_XMM6:
499 return "xmm6";
500 case UNW_X86_64_XMM7:
501 return "xmm7";
502 case UNW_X86_64_XMM8:
503 return "xmm8";
504 case UNW_X86_64_XMM9:
505 return "xmm9";
506 case UNW_X86_64_XMM10:
507 return "xmm10";
508 case UNW_X86_64_XMM11:
509 return "xmm11";
510 case UNW_X86_64_XMM12:
511 return "xmm12";
512 case UNW_X86_64_XMM13:
513 return "xmm13";
514 case UNW_X86_64_XMM14:
515 return "xmm14";
516 case UNW_X86_64_XMM15:
517 return "xmm15";
518 default:
519 return "unknown register";
520 }
521 }
522
getFloatRegister(int) const523 inline double Registers_x86_64::getFloatRegister(int) const {
524 _LIBUNWIND_ABORT("no x86_64 float registers");
525 }
526
setFloatRegister(int,double)527 inline void Registers_x86_64::setFloatRegister(int, double) {
528 _LIBUNWIND_ABORT("no x86_64 float registers");
529 }
530
validVectorRegister(int regNum) const531 inline bool Registers_x86_64::validVectorRegister(int regNum) const {
532 #if defined(_WIN64)
533 if (regNum < UNW_X86_64_XMM0)
534 return false;
535 if (regNum > UNW_X86_64_XMM15)
536 return false;
537 return true;
538 #else
539 (void)regNum; // suppress unused parameter warning
540 return false;
541 #endif
542 }
543
getVectorRegister(int regNum) const544 inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
545 #if defined(_WIN64)
546 assert(validVectorRegister(regNum));
547 return _xmm[regNum - UNW_X86_64_XMM0];
548 #else
549 (void)regNum; // suppress unused parameter warning
550 _LIBUNWIND_ABORT("no x86_64 vector registers");
551 #endif
552 }
553
setVectorRegister(int regNum,v128 value)554 inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
555 #if defined(_WIN64)
556 assert(validVectorRegister(regNum));
557 _xmm[regNum - UNW_X86_64_XMM0] = value;
558 #else
559 (void)regNum; (void)value; // suppress unused parameter warnings
560 _LIBUNWIND_ABORT("no x86_64 vector registers");
561 #endif
562 }
563 #endif // _LIBUNWIND_TARGET_X86_64
564
565
566 #if defined(_LIBUNWIND_TARGET_PPC)
567 /// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
568 /// process.
569 class _LIBUNWIND_HIDDEN Registers_ppc {
570 public:
571 Registers_ppc();
572 Registers_ppc(const void *registers);
573
574 bool validRegister(int num) const;
575 uint32_t getRegister(int num) const;
576 void setRegister(int num, uint32_t value);
577 bool validFloatRegister(int num) const;
578 double getFloatRegister(int num) const;
579 void setFloatRegister(int num, double value);
580 bool validVectorRegister(int num) const;
581 v128 getVectorRegister(int num) const;
582 void setVectorRegister(int num, v128 value);
583 static const char *getRegisterName(int num);
584 void jumpto();
lastDwarfRegNum()585 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; }
getArch()586 static int getArch() { return REGISTERS_PPC; }
587
getSP() const588 uint64_t getSP() const { return _registers.__r1; }
setSP(uint32_t value)589 void setSP(uint32_t value) { _registers.__r1 = value; }
getIP() const590 uint64_t getIP() const { return _registers.__srr0; }
setIP(uint32_t value)591 void setIP(uint32_t value) { _registers.__srr0 = value; }
592
593 private:
594 struct ppc_thread_state_t {
595 unsigned int __srr0; /* Instruction address register (PC) */
596 unsigned int __srr1; /* Machine state register (supervisor) */
597 unsigned int __r0;
598 unsigned int __r1;
599 unsigned int __r2;
600 unsigned int __r3;
601 unsigned int __r4;
602 unsigned int __r5;
603 unsigned int __r6;
604 unsigned int __r7;
605 unsigned int __r8;
606 unsigned int __r9;
607 unsigned int __r10;
608 unsigned int __r11;
609 unsigned int __r12;
610 unsigned int __r13;
611 unsigned int __r14;
612 unsigned int __r15;
613 unsigned int __r16;
614 unsigned int __r17;
615 unsigned int __r18;
616 unsigned int __r19;
617 unsigned int __r20;
618 unsigned int __r21;
619 unsigned int __r22;
620 unsigned int __r23;
621 unsigned int __r24;
622 unsigned int __r25;
623 unsigned int __r26;
624 unsigned int __r27;
625 unsigned int __r28;
626 unsigned int __r29;
627 unsigned int __r30;
628 unsigned int __r31;
629 unsigned int __cr; /* Condition register */
630 unsigned int __xer; /* User's integer exception register */
631 unsigned int __lr; /* Link register */
632 unsigned int __ctr; /* Count register */
633 unsigned int __mq; /* MQ register (601 only) */
634 unsigned int __vrsave; /* Vector Save Register */
635 };
636
637 struct ppc_float_state_t {
638 double __fpregs[32];
639
640 unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
641 unsigned int __fpscr; /* floating point status register */
642 };
643
644 ppc_thread_state_t _registers;
645 ppc_float_state_t _floatRegisters;
646 v128 _vectorRegisters[32]; // offset 424
647 };
648
Registers_ppc(const void * registers)649 inline Registers_ppc::Registers_ppc(const void *registers) {
650 static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
651 "ppc registers do not fit into unw_context_t");
652 memcpy(&_registers, static_cast<const uint8_t *>(registers),
653 sizeof(_registers));
654 static_assert(sizeof(ppc_thread_state_t) == 160,
655 "expected float register offset to be 160");
656 memcpy(&_floatRegisters,
657 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
658 sizeof(_floatRegisters));
659 static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
660 "expected vector register offset to be 424 bytes");
661 memcpy(_vectorRegisters,
662 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
663 sizeof(ppc_float_state_t),
664 sizeof(_vectorRegisters));
665 }
666
Registers_ppc()667 inline Registers_ppc::Registers_ppc() {
668 memset(&_registers, 0, sizeof(_registers));
669 memset(&_floatRegisters, 0, sizeof(_floatRegisters));
670 memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
671 }
672
validRegister(int regNum) const673 inline bool Registers_ppc::validRegister(int regNum) const {
674 if (regNum == UNW_REG_IP)
675 return true;
676 if (regNum == UNW_REG_SP)
677 return true;
678 if (regNum == UNW_PPC_VRSAVE)
679 return true;
680 if (regNum < 0)
681 return false;
682 if (regNum <= UNW_PPC_R31)
683 return true;
684 if (regNum == UNW_PPC_MQ)
685 return true;
686 if (regNum == UNW_PPC_LR)
687 return true;
688 if (regNum == UNW_PPC_CTR)
689 return true;
690 if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
691 return true;
692 return false;
693 }
694
getRegister(int regNum) const695 inline uint32_t Registers_ppc::getRegister(int regNum) const {
696 switch (regNum) {
697 case UNW_REG_IP:
698 return _registers.__srr0;
699 case UNW_REG_SP:
700 return _registers.__r1;
701 case UNW_PPC_R0:
702 return _registers.__r0;
703 case UNW_PPC_R1:
704 return _registers.__r1;
705 case UNW_PPC_R2:
706 return _registers.__r2;
707 case UNW_PPC_R3:
708 return _registers.__r3;
709 case UNW_PPC_R4:
710 return _registers.__r4;
711 case UNW_PPC_R5:
712 return _registers.__r5;
713 case UNW_PPC_R6:
714 return _registers.__r6;
715 case UNW_PPC_R7:
716 return _registers.__r7;
717 case UNW_PPC_R8:
718 return _registers.__r8;
719 case UNW_PPC_R9:
720 return _registers.__r9;
721 case UNW_PPC_R10:
722 return _registers.__r10;
723 case UNW_PPC_R11:
724 return _registers.__r11;
725 case UNW_PPC_R12:
726 return _registers.__r12;
727 case UNW_PPC_R13:
728 return _registers.__r13;
729 case UNW_PPC_R14:
730 return _registers.__r14;
731 case UNW_PPC_R15:
732 return _registers.__r15;
733 case UNW_PPC_R16:
734 return _registers.__r16;
735 case UNW_PPC_R17:
736 return _registers.__r17;
737 case UNW_PPC_R18:
738 return _registers.__r18;
739 case UNW_PPC_R19:
740 return _registers.__r19;
741 case UNW_PPC_R20:
742 return _registers.__r20;
743 case UNW_PPC_R21:
744 return _registers.__r21;
745 case UNW_PPC_R22:
746 return _registers.__r22;
747 case UNW_PPC_R23:
748 return _registers.__r23;
749 case UNW_PPC_R24:
750 return _registers.__r24;
751 case UNW_PPC_R25:
752 return _registers.__r25;
753 case UNW_PPC_R26:
754 return _registers.__r26;
755 case UNW_PPC_R27:
756 return _registers.__r27;
757 case UNW_PPC_R28:
758 return _registers.__r28;
759 case UNW_PPC_R29:
760 return _registers.__r29;
761 case UNW_PPC_R30:
762 return _registers.__r30;
763 case UNW_PPC_R31:
764 return _registers.__r31;
765 case UNW_PPC_LR:
766 return _registers.__lr;
767 case UNW_PPC_CR0:
768 return (_registers.__cr & 0xF0000000);
769 case UNW_PPC_CR1:
770 return (_registers.__cr & 0x0F000000);
771 case UNW_PPC_CR2:
772 return (_registers.__cr & 0x00F00000);
773 case UNW_PPC_CR3:
774 return (_registers.__cr & 0x000F0000);
775 case UNW_PPC_CR4:
776 return (_registers.__cr & 0x0000F000);
777 case UNW_PPC_CR5:
778 return (_registers.__cr & 0x00000F00);
779 case UNW_PPC_CR6:
780 return (_registers.__cr & 0x000000F0);
781 case UNW_PPC_CR7:
782 return (_registers.__cr & 0x0000000F);
783 case UNW_PPC_VRSAVE:
784 return _registers.__vrsave;
785 }
786 _LIBUNWIND_ABORT("unsupported ppc register");
787 }
788
setRegister(int regNum,uint32_t value)789 inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
790 //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
791 switch (regNum) {
792 case UNW_REG_IP:
793 _registers.__srr0 = value;
794 return;
795 case UNW_REG_SP:
796 _registers.__r1 = value;
797 return;
798 case UNW_PPC_R0:
799 _registers.__r0 = value;
800 return;
801 case UNW_PPC_R1:
802 _registers.__r1 = value;
803 return;
804 case UNW_PPC_R2:
805 _registers.__r2 = value;
806 return;
807 case UNW_PPC_R3:
808 _registers.__r3 = value;
809 return;
810 case UNW_PPC_R4:
811 _registers.__r4 = value;
812 return;
813 case UNW_PPC_R5:
814 _registers.__r5 = value;
815 return;
816 case UNW_PPC_R6:
817 _registers.__r6 = value;
818 return;
819 case UNW_PPC_R7:
820 _registers.__r7 = value;
821 return;
822 case UNW_PPC_R8:
823 _registers.__r8 = value;
824 return;
825 case UNW_PPC_R9:
826 _registers.__r9 = value;
827 return;
828 case UNW_PPC_R10:
829 _registers.__r10 = value;
830 return;
831 case UNW_PPC_R11:
832 _registers.__r11 = value;
833 return;
834 case UNW_PPC_R12:
835 _registers.__r12 = value;
836 return;
837 case UNW_PPC_R13:
838 _registers.__r13 = value;
839 return;
840 case UNW_PPC_R14:
841 _registers.__r14 = value;
842 return;
843 case UNW_PPC_R15:
844 _registers.__r15 = value;
845 return;
846 case UNW_PPC_R16:
847 _registers.__r16 = value;
848 return;
849 case UNW_PPC_R17:
850 _registers.__r17 = value;
851 return;
852 case UNW_PPC_R18:
853 _registers.__r18 = value;
854 return;
855 case UNW_PPC_R19:
856 _registers.__r19 = value;
857 return;
858 case UNW_PPC_R20:
859 _registers.__r20 = value;
860 return;
861 case UNW_PPC_R21:
862 _registers.__r21 = value;
863 return;
864 case UNW_PPC_R22:
865 _registers.__r22 = value;
866 return;
867 case UNW_PPC_R23:
868 _registers.__r23 = value;
869 return;
870 case UNW_PPC_R24:
871 _registers.__r24 = value;
872 return;
873 case UNW_PPC_R25:
874 _registers.__r25 = value;
875 return;
876 case UNW_PPC_R26:
877 _registers.__r26 = value;
878 return;
879 case UNW_PPC_R27:
880 _registers.__r27 = value;
881 return;
882 case UNW_PPC_R28:
883 _registers.__r28 = value;
884 return;
885 case UNW_PPC_R29:
886 _registers.__r29 = value;
887 return;
888 case UNW_PPC_R30:
889 _registers.__r30 = value;
890 return;
891 case UNW_PPC_R31:
892 _registers.__r31 = value;
893 return;
894 case UNW_PPC_MQ:
895 _registers.__mq = value;
896 return;
897 case UNW_PPC_LR:
898 _registers.__lr = value;
899 return;
900 case UNW_PPC_CTR:
901 _registers.__ctr = value;
902 return;
903 case UNW_PPC_CR0:
904 _registers.__cr &= 0x0FFFFFFF;
905 _registers.__cr |= (value & 0xF0000000);
906 return;
907 case UNW_PPC_CR1:
908 _registers.__cr &= 0xF0FFFFFF;
909 _registers.__cr |= (value & 0x0F000000);
910 return;
911 case UNW_PPC_CR2:
912 _registers.__cr &= 0xFF0FFFFF;
913 _registers.__cr |= (value & 0x00F00000);
914 return;
915 case UNW_PPC_CR3:
916 _registers.__cr &= 0xFFF0FFFF;
917 _registers.__cr |= (value & 0x000F0000);
918 return;
919 case UNW_PPC_CR4:
920 _registers.__cr &= 0xFFFF0FFF;
921 _registers.__cr |= (value & 0x0000F000);
922 return;
923 case UNW_PPC_CR5:
924 _registers.__cr &= 0xFFFFF0FF;
925 _registers.__cr |= (value & 0x00000F00);
926 return;
927 case UNW_PPC_CR6:
928 _registers.__cr &= 0xFFFFFF0F;
929 _registers.__cr |= (value & 0x000000F0);
930 return;
931 case UNW_PPC_CR7:
932 _registers.__cr &= 0xFFFFFFF0;
933 _registers.__cr |= (value & 0x0000000F);
934 return;
935 case UNW_PPC_VRSAVE:
936 _registers.__vrsave = value;
937 return;
938 // not saved
939 return;
940 case UNW_PPC_XER:
941 _registers.__xer = value;
942 return;
943 case UNW_PPC_AP:
944 case UNW_PPC_VSCR:
945 case UNW_PPC_SPEFSCR:
946 // not saved
947 return;
948 }
949 _LIBUNWIND_ABORT("unsupported ppc register");
950 }
951
validFloatRegister(int regNum) const952 inline bool Registers_ppc::validFloatRegister(int regNum) const {
953 if (regNum < UNW_PPC_F0)
954 return false;
955 if (regNum > UNW_PPC_F31)
956 return false;
957 return true;
958 }
959
getFloatRegister(int regNum) const960 inline double Registers_ppc::getFloatRegister(int regNum) const {
961 assert(validFloatRegister(regNum));
962 return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
963 }
964
setFloatRegister(int regNum,double value)965 inline void Registers_ppc::setFloatRegister(int regNum, double value) {
966 assert(validFloatRegister(regNum));
967 _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
968 }
969
validVectorRegister(int regNum) const970 inline bool Registers_ppc::validVectorRegister(int regNum) const {
971 if (regNum < UNW_PPC_V0)
972 return false;
973 if (regNum > UNW_PPC_V31)
974 return false;
975 return true;
976 }
977
getVectorRegister(int regNum) const978 inline v128 Registers_ppc::getVectorRegister(int regNum) const {
979 assert(validVectorRegister(regNum));
980 v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
981 return result;
982 }
983
setVectorRegister(int regNum,v128 value)984 inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
985 assert(validVectorRegister(regNum));
986 _vectorRegisters[regNum - UNW_PPC_V0] = value;
987 }
988
getRegisterName(int regNum)989 inline const char *Registers_ppc::getRegisterName(int regNum) {
990 switch (regNum) {
991 case UNW_REG_IP:
992 return "ip";
993 case UNW_REG_SP:
994 return "sp";
995 case UNW_PPC_R0:
996 return "r0";
997 case UNW_PPC_R1:
998 return "r1";
999 case UNW_PPC_R2:
1000 return "r2";
1001 case UNW_PPC_R3:
1002 return "r3";
1003 case UNW_PPC_R4:
1004 return "r4";
1005 case UNW_PPC_R5:
1006 return "r5";
1007 case UNW_PPC_R6:
1008 return "r6";
1009 case UNW_PPC_R7:
1010 return "r7";
1011 case UNW_PPC_R8:
1012 return "r8";
1013 case UNW_PPC_R9:
1014 return "r9";
1015 case UNW_PPC_R10:
1016 return "r10";
1017 case UNW_PPC_R11:
1018 return "r11";
1019 case UNW_PPC_R12:
1020 return "r12";
1021 case UNW_PPC_R13:
1022 return "r13";
1023 case UNW_PPC_R14:
1024 return "r14";
1025 case UNW_PPC_R15:
1026 return "r15";
1027 case UNW_PPC_R16:
1028 return "r16";
1029 case UNW_PPC_R17:
1030 return "r17";
1031 case UNW_PPC_R18:
1032 return "r18";
1033 case UNW_PPC_R19:
1034 return "r19";
1035 case UNW_PPC_R20:
1036 return "r20";
1037 case UNW_PPC_R21:
1038 return "r21";
1039 case UNW_PPC_R22:
1040 return "r22";
1041 case UNW_PPC_R23:
1042 return "r23";
1043 case UNW_PPC_R24:
1044 return "r24";
1045 case UNW_PPC_R25:
1046 return "r25";
1047 case UNW_PPC_R26:
1048 return "r26";
1049 case UNW_PPC_R27:
1050 return "r27";
1051 case UNW_PPC_R28:
1052 return "r28";
1053 case UNW_PPC_R29:
1054 return "r29";
1055 case UNW_PPC_R30:
1056 return "r30";
1057 case UNW_PPC_R31:
1058 return "r31";
1059 case UNW_PPC_F0:
1060 return "fp0";
1061 case UNW_PPC_F1:
1062 return "fp1";
1063 case UNW_PPC_F2:
1064 return "fp2";
1065 case UNW_PPC_F3:
1066 return "fp3";
1067 case UNW_PPC_F4:
1068 return "fp4";
1069 case UNW_PPC_F5:
1070 return "fp5";
1071 case UNW_PPC_F6:
1072 return "fp6";
1073 case UNW_PPC_F7:
1074 return "fp7";
1075 case UNW_PPC_F8:
1076 return "fp8";
1077 case UNW_PPC_F9:
1078 return "fp9";
1079 case UNW_PPC_F10:
1080 return "fp10";
1081 case UNW_PPC_F11:
1082 return "fp11";
1083 case UNW_PPC_F12:
1084 return "fp12";
1085 case UNW_PPC_F13:
1086 return "fp13";
1087 case UNW_PPC_F14:
1088 return "fp14";
1089 case UNW_PPC_F15:
1090 return "fp15";
1091 case UNW_PPC_F16:
1092 return "fp16";
1093 case UNW_PPC_F17:
1094 return "fp17";
1095 case UNW_PPC_F18:
1096 return "fp18";
1097 case UNW_PPC_F19:
1098 return "fp19";
1099 case UNW_PPC_F20:
1100 return "fp20";
1101 case UNW_PPC_F21:
1102 return "fp21";
1103 case UNW_PPC_F22:
1104 return "fp22";
1105 case UNW_PPC_F23:
1106 return "fp23";
1107 case UNW_PPC_F24:
1108 return "fp24";
1109 case UNW_PPC_F25:
1110 return "fp25";
1111 case UNW_PPC_F26:
1112 return "fp26";
1113 case UNW_PPC_F27:
1114 return "fp27";
1115 case UNW_PPC_F28:
1116 return "fp28";
1117 case UNW_PPC_F29:
1118 return "fp29";
1119 case UNW_PPC_F30:
1120 return "fp30";
1121 case UNW_PPC_F31:
1122 return "fp31";
1123 case UNW_PPC_LR:
1124 return "lr";
1125 default:
1126 return "unknown register";
1127 }
1128
1129 }
1130 #endif // _LIBUNWIND_TARGET_PPC
1131
1132 #if defined(_LIBUNWIND_TARGET_PPC64)
1133 /// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
1134 /// process.
1135 class _LIBUNWIND_HIDDEN Registers_ppc64 {
1136 public:
1137 Registers_ppc64();
1138 Registers_ppc64(const void *registers);
1139
1140 bool validRegister(int num) const;
1141 uint64_t getRegister(int num) const;
1142 void setRegister(int num, uint64_t value);
1143 bool validFloatRegister(int num) const;
1144 double getFloatRegister(int num) const;
1145 void setFloatRegister(int num, double value);
1146 bool validVectorRegister(int num) const;
1147 v128 getVectorRegister(int num) const;
1148 void setVectorRegister(int num, v128 value);
1149 static const char *getRegisterName(int num);
1150 void jumpto();
lastDwarfRegNum()1151 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; }
getArch()1152 static int getArch() { return REGISTERS_PPC64; }
1153
getSP() const1154 uint64_t getSP() const { return _registers.__r1; }
setSP(uint64_t value)1155 void setSP(uint64_t value) { _registers.__r1 = value; }
getIP() const1156 uint64_t getIP() const { return _registers.__srr0; }
setIP(uint64_t value)1157 void setIP(uint64_t value) { _registers.__srr0 = value; }
1158
1159 private:
1160 struct ppc64_thread_state_t {
1161 uint64_t __srr0; // Instruction address register (PC)
1162 uint64_t __srr1; // Machine state register (supervisor)
1163 uint64_t __r0;
1164 uint64_t __r1;
1165 uint64_t __r2;
1166 uint64_t __r3;
1167 uint64_t __r4;
1168 uint64_t __r5;
1169 uint64_t __r6;
1170 uint64_t __r7;
1171 uint64_t __r8;
1172 uint64_t __r9;
1173 uint64_t __r10;
1174 uint64_t __r11;
1175 uint64_t __r12;
1176 uint64_t __r13;
1177 uint64_t __r14;
1178 uint64_t __r15;
1179 uint64_t __r16;
1180 uint64_t __r17;
1181 uint64_t __r18;
1182 uint64_t __r19;
1183 uint64_t __r20;
1184 uint64_t __r21;
1185 uint64_t __r22;
1186 uint64_t __r23;
1187 uint64_t __r24;
1188 uint64_t __r25;
1189 uint64_t __r26;
1190 uint64_t __r27;
1191 uint64_t __r28;
1192 uint64_t __r29;
1193 uint64_t __r30;
1194 uint64_t __r31;
1195 uint64_t __cr; // Condition register
1196 uint64_t __xer; // User's integer exception register
1197 uint64_t __lr; // Link register
1198 uint64_t __ctr; // Count register
1199 uint64_t __vrsave; // Vector Save Register
1200 };
1201
1202 union ppc64_vsr_t {
1203 struct asfloat_s {
1204 double f;
1205 uint64_t v2;
1206 } asfloat;
1207 v128 v;
1208 };
1209
1210 ppc64_thread_state_t _registers;
1211 ppc64_vsr_t _vectorScalarRegisters[64];
1212
1213 static int getVectorRegNum(int num);
1214 };
1215
Registers_ppc64(const void * registers)1216 inline Registers_ppc64::Registers_ppc64(const void *registers) {
1217 static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),
1218 "ppc64 registers do not fit into unw_context_t");
1219 memcpy(&_registers, static_cast<const uint8_t *>(registers),
1220 sizeof(_registers));
1221 static_assert(sizeof(_registers) == 312,
1222 "expected vector scalar register offset to be 312");
1223 memcpy(&_vectorScalarRegisters,
1224 static_cast<const uint8_t *>(registers) + sizeof(_registers),
1225 sizeof(_vectorScalarRegisters));
1226 static_assert(sizeof(_registers) +
1227 sizeof(_vectorScalarRegisters) == 1336,
1228 "expected vector register offset to be 1336 bytes");
1229 }
1230
Registers_ppc64()1231 inline Registers_ppc64::Registers_ppc64() {
1232 memset(&_registers, 0, sizeof(_registers));
1233 memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
1234 }
1235
validRegister(int regNum) const1236 inline bool Registers_ppc64::validRegister(int regNum) const {
1237 switch (regNum) {
1238 case UNW_REG_IP:
1239 case UNW_REG_SP:
1240 case UNW_PPC64_XER:
1241 case UNW_PPC64_LR:
1242 case UNW_PPC64_CTR:
1243 case UNW_PPC64_VRSAVE:
1244 return true;
1245 }
1246
1247 if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
1248 return true;
1249 if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
1250 return true;
1251
1252 return false;
1253 }
1254
getRegister(int regNum) const1255 inline uint64_t Registers_ppc64::getRegister(int regNum) const {
1256 switch (regNum) {
1257 case UNW_REG_IP:
1258 return _registers.__srr0;
1259 case UNW_PPC64_R0:
1260 return _registers.__r0;
1261 case UNW_PPC64_R1:
1262 case UNW_REG_SP:
1263 return _registers.__r1;
1264 case UNW_PPC64_R2:
1265 return _registers.__r2;
1266 case UNW_PPC64_R3:
1267 return _registers.__r3;
1268 case UNW_PPC64_R4:
1269 return _registers.__r4;
1270 case UNW_PPC64_R5:
1271 return _registers.__r5;
1272 case UNW_PPC64_R6:
1273 return _registers.__r6;
1274 case UNW_PPC64_R7:
1275 return _registers.__r7;
1276 case UNW_PPC64_R8:
1277 return _registers.__r8;
1278 case UNW_PPC64_R9:
1279 return _registers.__r9;
1280 case UNW_PPC64_R10:
1281 return _registers.__r10;
1282 case UNW_PPC64_R11:
1283 return _registers.__r11;
1284 case UNW_PPC64_R12:
1285 return _registers.__r12;
1286 case UNW_PPC64_R13:
1287 return _registers.__r13;
1288 case UNW_PPC64_R14:
1289 return _registers.__r14;
1290 case UNW_PPC64_R15:
1291 return _registers.__r15;
1292 case UNW_PPC64_R16:
1293 return _registers.__r16;
1294 case UNW_PPC64_R17:
1295 return _registers.__r17;
1296 case UNW_PPC64_R18:
1297 return _registers.__r18;
1298 case UNW_PPC64_R19:
1299 return _registers.__r19;
1300 case UNW_PPC64_R20:
1301 return _registers.__r20;
1302 case UNW_PPC64_R21:
1303 return _registers.__r21;
1304 case UNW_PPC64_R22:
1305 return _registers.__r22;
1306 case UNW_PPC64_R23:
1307 return _registers.__r23;
1308 case UNW_PPC64_R24:
1309 return _registers.__r24;
1310 case UNW_PPC64_R25:
1311 return _registers.__r25;
1312 case UNW_PPC64_R26:
1313 return _registers.__r26;
1314 case UNW_PPC64_R27:
1315 return _registers.__r27;
1316 case UNW_PPC64_R28:
1317 return _registers.__r28;
1318 case UNW_PPC64_R29:
1319 return _registers.__r29;
1320 case UNW_PPC64_R30:
1321 return _registers.__r30;
1322 case UNW_PPC64_R31:
1323 return _registers.__r31;
1324 case UNW_PPC64_CR0:
1325 return (_registers.__cr & 0xF0000000);
1326 case UNW_PPC64_CR1:
1327 return (_registers.__cr & 0x0F000000);
1328 case UNW_PPC64_CR2:
1329 return (_registers.__cr & 0x00F00000);
1330 case UNW_PPC64_CR3:
1331 return (_registers.__cr & 0x000F0000);
1332 case UNW_PPC64_CR4:
1333 return (_registers.__cr & 0x0000F000);
1334 case UNW_PPC64_CR5:
1335 return (_registers.__cr & 0x00000F00);
1336 case UNW_PPC64_CR6:
1337 return (_registers.__cr & 0x000000F0);
1338 case UNW_PPC64_CR7:
1339 return (_registers.__cr & 0x0000000F);
1340 case UNW_PPC64_XER:
1341 return _registers.__xer;
1342 case UNW_PPC64_LR:
1343 return _registers.__lr;
1344 case UNW_PPC64_CTR:
1345 return _registers.__ctr;
1346 case UNW_PPC64_VRSAVE:
1347 return _registers.__vrsave;
1348 }
1349 _LIBUNWIND_ABORT("unsupported ppc64 register");
1350 }
1351
setRegister(int regNum,uint64_t value)1352 inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
1353 switch (regNum) {
1354 case UNW_REG_IP:
1355 _registers.__srr0 = value;
1356 return;
1357 case UNW_PPC64_R0:
1358 _registers.__r0 = value;
1359 return;
1360 case UNW_PPC64_R1:
1361 case UNW_REG_SP:
1362 _registers.__r1 = value;
1363 return;
1364 case UNW_PPC64_R2:
1365 _registers.__r2 = value;
1366 return;
1367 case UNW_PPC64_R3:
1368 _registers.__r3 = value;
1369 return;
1370 case UNW_PPC64_R4:
1371 _registers.__r4 = value;
1372 return;
1373 case UNW_PPC64_R5:
1374 _registers.__r5 = value;
1375 return;
1376 case UNW_PPC64_R6:
1377 _registers.__r6 = value;
1378 return;
1379 case UNW_PPC64_R7:
1380 _registers.__r7 = value;
1381 return;
1382 case UNW_PPC64_R8:
1383 _registers.__r8 = value;
1384 return;
1385 case UNW_PPC64_R9:
1386 _registers.__r9 = value;
1387 return;
1388 case UNW_PPC64_R10:
1389 _registers.__r10 = value;
1390 return;
1391 case UNW_PPC64_R11:
1392 _registers.__r11 = value;
1393 return;
1394 case UNW_PPC64_R12:
1395 _registers.__r12 = value;
1396 return;
1397 case UNW_PPC64_R13:
1398 _registers.__r13 = value;
1399 return;
1400 case UNW_PPC64_R14:
1401 _registers.__r14 = value;
1402 return;
1403 case UNW_PPC64_R15:
1404 _registers.__r15 = value;
1405 return;
1406 case UNW_PPC64_R16:
1407 _registers.__r16 = value;
1408 return;
1409 case UNW_PPC64_R17:
1410 _registers.__r17 = value;
1411 return;
1412 case UNW_PPC64_R18:
1413 _registers.__r18 = value;
1414 return;
1415 case UNW_PPC64_R19:
1416 _registers.__r19 = value;
1417 return;
1418 case UNW_PPC64_R20:
1419 _registers.__r20 = value;
1420 return;
1421 case UNW_PPC64_R21:
1422 _registers.__r21 = value;
1423 return;
1424 case UNW_PPC64_R22:
1425 _registers.__r22 = value;
1426 return;
1427 case UNW_PPC64_R23:
1428 _registers.__r23 = value;
1429 return;
1430 case UNW_PPC64_R24:
1431 _registers.__r24 = value;
1432 return;
1433 case UNW_PPC64_R25:
1434 _registers.__r25 = value;
1435 return;
1436 case UNW_PPC64_R26:
1437 _registers.__r26 = value;
1438 return;
1439 case UNW_PPC64_R27:
1440 _registers.__r27 = value;
1441 return;
1442 case UNW_PPC64_R28:
1443 _registers.__r28 = value;
1444 return;
1445 case UNW_PPC64_R29:
1446 _registers.__r29 = value;
1447 return;
1448 case UNW_PPC64_R30:
1449 _registers.__r30 = value;
1450 return;
1451 case UNW_PPC64_R31:
1452 _registers.__r31 = value;
1453 return;
1454 case UNW_PPC64_CR0:
1455 _registers.__cr &= 0x0FFFFFFF;
1456 _registers.__cr |= (value & 0xF0000000);
1457 return;
1458 case UNW_PPC64_CR1:
1459 _registers.__cr &= 0xF0FFFFFF;
1460 _registers.__cr |= (value & 0x0F000000);
1461 return;
1462 case UNW_PPC64_CR2:
1463 _registers.__cr &= 0xFF0FFFFF;
1464 _registers.__cr |= (value & 0x00F00000);
1465 return;
1466 case UNW_PPC64_CR3:
1467 _registers.__cr &= 0xFFF0FFFF;
1468 _registers.__cr |= (value & 0x000F0000);
1469 return;
1470 case UNW_PPC64_CR4:
1471 _registers.__cr &= 0xFFFF0FFF;
1472 _registers.__cr |= (value & 0x0000F000);
1473 return;
1474 case UNW_PPC64_CR5:
1475 _registers.__cr &= 0xFFFFF0FF;
1476 _registers.__cr |= (value & 0x00000F00);
1477 return;
1478 case UNW_PPC64_CR6:
1479 _registers.__cr &= 0xFFFFFF0F;
1480 _registers.__cr |= (value & 0x000000F0);
1481 return;
1482 case UNW_PPC64_CR7:
1483 _registers.__cr &= 0xFFFFFFF0;
1484 _registers.__cr |= (value & 0x0000000F);
1485 return;
1486 case UNW_PPC64_XER:
1487 _registers.__xer = value;
1488 return;
1489 case UNW_PPC64_LR:
1490 _registers.__lr = value;
1491 return;
1492 case UNW_PPC64_CTR:
1493 _registers.__ctr = value;
1494 return;
1495 case UNW_PPC64_VRSAVE:
1496 _registers.__vrsave = value;
1497 return;
1498 }
1499 _LIBUNWIND_ABORT("unsupported ppc64 register");
1500 }
1501
validFloatRegister(int regNum) const1502 inline bool Registers_ppc64::validFloatRegister(int regNum) const {
1503 return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
1504 }
1505
getFloatRegister(int regNum) const1506 inline double Registers_ppc64::getFloatRegister(int regNum) const {
1507 assert(validFloatRegister(regNum));
1508 return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
1509 }
1510
setFloatRegister(int regNum,double value)1511 inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
1512 assert(validFloatRegister(regNum));
1513 _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
1514 }
1515
validVectorRegister(int regNum) const1516 inline bool Registers_ppc64::validVectorRegister(int regNum) const {
1517 #if defined(__VSX__)
1518 if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
1519 return true;
1520 if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
1521 return true;
1522 #elif defined(__ALTIVEC__)
1523 if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
1524 return true;
1525 #endif
1526 return false;
1527 }
1528
getVectorRegNum(int num)1529 inline int Registers_ppc64::getVectorRegNum(int num)
1530 {
1531 if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
1532 return num - UNW_PPC64_VS0;
1533 else
1534 return num - UNW_PPC64_VS32 + 32;
1535 }
1536
getVectorRegister(int regNum) const1537 inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
1538 assert(validVectorRegister(regNum));
1539 return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
1540 }
1541
setVectorRegister(int regNum,v128 value)1542 inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
1543 assert(validVectorRegister(regNum));
1544 _vectorScalarRegisters[getVectorRegNum(regNum)].v = value;
1545 }
1546
getRegisterName(int regNum)1547 inline const char *Registers_ppc64::getRegisterName(int regNum) {
1548 switch (regNum) {
1549 case UNW_REG_IP:
1550 return "ip";
1551 case UNW_REG_SP:
1552 return "sp";
1553 case UNW_PPC64_R0:
1554 return "r0";
1555 case UNW_PPC64_R1:
1556 return "r1";
1557 case UNW_PPC64_R2:
1558 return "r2";
1559 case UNW_PPC64_R3:
1560 return "r3";
1561 case UNW_PPC64_R4:
1562 return "r4";
1563 case UNW_PPC64_R5:
1564 return "r5";
1565 case UNW_PPC64_R6:
1566 return "r6";
1567 case UNW_PPC64_R7:
1568 return "r7";
1569 case UNW_PPC64_R8:
1570 return "r8";
1571 case UNW_PPC64_R9:
1572 return "r9";
1573 case UNW_PPC64_R10:
1574 return "r10";
1575 case UNW_PPC64_R11:
1576 return "r11";
1577 case UNW_PPC64_R12:
1578 return "r12";
1579 case UNW_PPC64_R13:
1580 return "r13";
1581 case UNW_PPC64_R14:
1582 return "r14";
1583 case UNW_PPC64_R15:
1584 return "r15";
1585 case UNW_PPC64_R16:
1586 return "r16";
1587 case UNW_PPC64_R17:
1588 return "r17";
1589 case UNW_PPC64_R18:
1590 return "r18";
1591 case UNW_PPC64_R19:
1592 return "r19";
1593 case UNW_PPC64_R20:
1594 return "r20";
1595 case UNW_PPC64_R21:
1596 return "r21";
1597 case UNW_PPC64_R22:
1598 return "r22";
1599 case UNW_PPC64_R23:
1600 return "r23";
1601 case UNW_PPC64_R24:
1602 return "r24";
1603 case UNW_PPC64_R25:
1604 return "r25";
1605 case UNW_PPC64_R26:
1606 return "r26";
1607 case UNW_PPC64_R27:
1608 return "r27";
1609 case UNW_PPC64_R28:
1610 return "r28";
1611 case UNW_PPC64_R29:
1612 return "r29";
1613 case UNW_PPC64_R30:
1614 return "r30";
1615 case UNW_PPC64_R31:
1616 return "r31";
1617 case UNW_PPC64_CR0:
1618 return "cr0";
1619 case UNW_PPC64_CR1:
1620 return "cr1";
1621 case UNW_PPC64_CR2:
1622 return "cr2";
1623 case UNW_PPC64_CR3:
1624 return "cr3";
1625 case UNW_PPC64_CR4:
1626 return "cr4";
1627 case UNW_PPC64_CR5:
1628 return "cr5";
1629 case UNW_PPC64_CR6:
1630 return "cr6";
1631 case UNW_PPC64_CR7:
1632 return "cr7";
1633 case UNW_PPC64_XER:
1634 return "xer";
1635 case UNW_PPC64_LR:
1636 return "lr";
1637 case UNW_PPC64_CTR:
1638 return "ctr";
1639 case UNW_PPC64_VRSAVE:
1640 return "vrsave";
1641 case UNW_PPC64_F0:
1642 return "fp0";
1643 case UNW_PPC64_F1:
1644 return "fp1";
1645 case UNW_PPC64_F2:
1646 return "fp2";
1647 case UNW_PPC64_F3:
1648 return "fp3";
1649 case UNW_PPC64_F4:
1650 return "fp4";
1651 case UNW_PPC64_F5:
1652 return "fp5";
1653 case UNW_PPC64_F6:
1654 return "fp6";
1655 case UNW_PPC64_F7:
1656 return "fp7";
1657 case UNW_PPC64_F8:
1658 return "fp8";
1659 case UNW_PPC64_F9:
1660 return "fp9";
1661 case UNW_PPC64_F10:
1662 return "fp10";
1663 case UNW_PPC64_F11:
1664 return "fp11";
1665 case UNW_PPC64_F12:
1666 return "fp12";
1667 case UNW_PPC64_F13:
1668 return "fp13";
1669 case UNW_PPC64_F14:
1670 return "fp14";
1671 case UNW_PPC64_F15:
1672 return "fp15";
1673 case UNW_PPC64_F16:
1674 return "fp16";
1675 case UNW_PPC64_F17:
1676 return "fp17";
1677 case UNW_PPC64_F18:
1678 return "fp18";
1679 case UNW_PPC64_F19:
1680 return "fp19";
1681 case UNW_PPC64_F20:
1682 return "fp20";
1683 case UNW_PPC64_F21:
1684 return "fp21";
1685 case UNW_PPC64_F22:
1686 return "fp22";
1687 case UNW_PPC64_F23:
1688 return "fp23";
1689 case UNW_PPC64_F24:
1690 return "fp24";
1691 case UNW_PPC64_F25:
1692 return "fp25";
1693 case UNW_PPC64_F26:
1694 return "fp26";
1695 case UNW_PPC64_F27:
1696 return "fp27";
1697 case UNW_PPC64_F28:
1698 return "fp28";
1699 case UNW_PPC64_F29:
1700 return "fp29";
1701 case UNW_PPC64_F30:
1702 return "fp30";
1703 case UNW_PPC64_F31:
1704 return "fp31";
1705 case UNW_PPC64_V0:
1706 return "v0";
1707 case UNW_PPC64_V1:
1708 return "v1";
1709 case UNW_PPC64_V2:
1710 return "v2";
1711 case UNW_PPC64_V3:
1712 return "v3";
1713 case UNW_PPC64_V4:
1714 return "v4";
1715 case UNW_PPC64_V5:
1716 return "v5";
1717 case UNW_PPC64_V6:
1718 return "v6";
1719 case UNW_PPC64_V7:
1720 return "v7";
1721 case UNW_PPC64_V8:
1722 return "v8";
1723 case UNW_PPC64_V9:
1724 return "v9";
1725 case UNW_PPC64_V10:
1726 return "v10";
1727 case UNW_PPC64_V11:
1728 return "v11";
1729 case UNW_PPC64_V12:
1730 return "v12";
1731 case UNW_PPC64_V13:
1732 return "v13";
1733 case UNW_PPC64_V14:
1734 return "v14";
1735 case UNW_PPC64_V15:
1736 return "v15";
1737 case UNW_PPC64_V16:
1738 return "v16";
1739 case UNW_PPC64_V17:
1740 return "v17";
1741 case UNW_PPC64_V18:
1742 return "v18";
1743 case UNW_PPC64_V19:
1744 return "v19";
1745 case UNW_PPC64_V20:
1746 return "v20";
1747 case UNW_PPC64_V21:
1748 return "v21";
1749 case UNW_PPC64_V22:
1750 return "v22";
1751 case UNW_PPC64_V23:
1752 return "v23";
1753 case UNW_PPC64_V24:
1754 return "v24";
1755 case UNW_PPC64_V25:
1756 return "v25";
1757 case UNW_PPC64_V26:
1758 return "v26";
1759 case UNW_PPC64_V27:
1760 return "v27";
1761 case UNW_PPC64_V28:
1762 return "v28";
1763 case UNW_PPC64_V29:
1764 return "v29";
1765 case UNW_PPC64_V30:
1766 return "v30";
1767 case UNW_PPC64_V31:
1768 return "v31";
1769 }
1770 return "unknown register";
1771 }
1772 #endif // _LIBUNWIND_TARGET_PPC64
1773
1774
1775 #if defined(_LIBUNWIND_TARGET_AARCH64)
1776 /// Registers_arm64 holds the register state of a thread in a 64-bit arm
1777 /// process.
1778 class _LIBUNWIND_HIDDEN Registers_arm64;
1779 extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
1780 class _LIBUNWIND_HIDDEN Registers_arm64 {
1781 public:
1782 Registers_arm64();
1783 Registers_arm64(const void *registers);
1784
1785 bool validRegister(int num) const;
1786 uint64_t getRegister(int num) const;
1787 void setRegister(int num, uint64_t value);
1788 bool validFloatRegister(int num) const;
1789 double getFloatRegister(int num) const;
1790 void setFloatRegister(int num, double value);
1791 bool validVectorRegister(int num) const;
1792 v128 getVectorRegister(int num) const;
1793 void setVectorRegister(int num, v128 value);
1794 static const char *getRegisterName(int num);
jumpto()1795 void jumpto() { __libunwind_Registers_arm64_jumpto(this); }
lastDwarfRegNum()1796 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }
getArch()1797 static int getArch() { return REGISTERS_ARM64; }
1798
getSP() const1799 uint64_t getSP() const { return _registers.__sp; }
setSP(uint64_t value)1800 void setSP(uint64_t value) { _registers.__sp = value; }
getIP() const1801 uint64_t getIP() const { return _registers.__pc; }
setIP(uint64_t value)1802 void setIP(uint64_t value) { _registers.__pc = value; }
getFP() const1803 uint64_t getFP() const { return _registers.__fp; }
setFP(uint64_t value)1804 void setFP(uint64_t value) { _registers.__fp = value; }
1805
1806 private:
1807 struct GPRs {
1808 uint64_t __x[29]; // x0-x28
1809 uint64_t __fp; // Frame pointer x29
1810 uint64_t __lr; // Link register x30
1811 uint64_t __sp; // Stack pointer x31
1812 uint64_t __pc; // Program counter
1813 uint64_t __ra_sign_state; // RA sign state register
1814 };
1815
1816 GPRs _registers;
1817 double _vectorHalfRegisters[32];
1818 // Currently only the lower double in 128-bit vectore registers
1819 // is perserved during unwinding. We could define new register
1820 // numbers (> 96) which mean whole vector registers, then this
1821 // struct would need to change to contain whole vector registers.
1822 };
1823
Registers_arm64(const void * registers)1824 inline Registers_arm64::Registers_arm64(const void *registers) {
1825 static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
1826 "arm64 registers do not fit into unw_context_t");
1827 memcpy(&_registers, registers, sizeof(_registers));
1828 static_assert(sizeof(GPRs) == 0x110,
1829 "expected VFP registers to be at offset 272");
1830 memcpy(_vectorHalfRegisters,
1831 static_cast<const uint8_t *>(registers) + sizeof(GPRs),
1832 sizeof(_vectorHalfRegisters));
1833 }
1834
Registers_arm64()1835 inline Registers_arm64::Registers_arm64() {
1836 memset(&_registers, 0, sizeof(_registers));
1837 memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
1838 }
1839
validRegister(int regNum) const1840 inline bool Registers_arm64::validRegister(int regNum) const {
1841 if (regNum == UNW_REG_IP)
1842 return true;
1843 if (regNum == UNW_REG_SP)
1844 return true;
1845 if (regNum < 0)
1846 return false;
1847 if (regNum > 95)
1848 return false;
1849 if (regNum == UNW_ARM64_RA_SIGN_STATE)
1850 return true;
1851 if ((regNum > 31) && (regNum < 64))
1852 return false;
1853 return true;
1854 }
1855
getRegister(int regNum) const1856 inline uint64_t Registers_arm64::getRegister(int regNum) const {
1857 if (regNum == UNW_REG_IP)
1858 return _registers.__pc;
1859 if (regNum == UNW_REG_SP)
1860 return _registers.__sp;
1861 if (regNum == UNW_ARM64_RA_SIGN_STATE)
1862 return _registers.__ra_sign_state;
1863 if ((regNum >= 0) && (regNum < 32))
1864 return _registers.__x[regNum];
1865 _LIBUNWIND_ABORT("unsupported arm64 register");
1866 }
1867
setRegister(int regNum,uint64_t value)1868 inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1869 if (regNum == UNW_REG_IP)
1870 _registers.__pc = value;
1871 else if (regNum == UNW_REG_SP)
1872 _registers.__sp = value;
1873 else if (regNum == UNW_ARM64_RA_SIGN_STATE)
1874 _registers.__ra_sign_state = value;
1875 else if ((regNum >= 0) && (regNum < 32))
1876 _registers.__x[regNum] = value;
1877 else
1878 _LIBUNWIND_ABORT("unsupported arm64 register");
1879 }
1880
getRegisterName(int regNum)1881 inline const char *Registers_arm64::getRegisterName(int regNum) {
1882 switch (regNum) {
1883 case UNW_REG_IP:
1884 return "pc";
1885 case UNW_REG_SP:
1886 return "sp";
1887 case UNW_ARM64_X0:
1888 return "x0";
1889 case UNW_ARM64_X1:
1890 return "x1";
1891 case UNW_ARM64_X2:
1892 return "x2";
1893 case UNW_ARM64_X3:
1894 return "x3";
1895 case UNW_ARM64_X4:
1896 return "x4";
1897 case UNW_ARM64_X5:
1898 return "x5";
1899 case UNW_ARM64_X6:
1900 return "x6";
1901 case UNW_ARM64_X7:
1902 return "x7";
1903 case UNW_ARM64_X8:
1904 return "x8";
1905 case UNW_ARM64_X9:
1906 return "x9";
1907 case UNW_ARM64_X10:
1908 return "x10";
1909 case UNW_ARM64_X11:
1910 return "x11";
1911 case UNW_ARM64_X12:
1912 return "x12";
1913 case UNW_ARM64_X13:
1914 return "x13";
1915 case UNW_ARM64_X14:
1916 return "x14";
1917 case UNW_ARM64_X15:
1918 return "x15";
1919 case UNW_ARM64_X16:
1920 return "x16";
1921 case UNW_ARM64_X17:
1922 return "x17";
1923 case UNW_ARM64_X18:
1924 return "x18";
1925 case UNW_ARM64_X19:
1926 return "x19";
1927 case UNW_ARM64_X20:
1928 return "x20";
1929 case UNW_ARM64_X21:
1930 return "x21";
1931 case UNW_ARM64_X22:
1932 return "x22";
1933 case UNW_ARM64_X23:
1934 return "x23";
1935 case UNW_ARM64_X24:
1936 return "x24";
1937 case UNW_ARM64_X25:
1938 return "x25";
1939 case UNW_ARM64_X26:
1940 return "x26";
1941 case UNW_ARM64_X27:
1942 return "x27";
1943 case UNW_ARM64_X28:
1944 return "x28";
1945 case UNW_ARM64_X29:
1946 return "fp";
1947 case UNW_ARM64_X30:
1948 return "lr";
1949 case UNW_ARM64_X31:
1950 return "sp";
1951 case UNW_ARM64_D0:
1952 return "d0";
1953 case UNW_ARM64_D1:
1954 return "d1";
1955 case UNW_ARM64_D2:
1956 return "d2";
1957 case UNW_ARM64_D3:
1958 return "d3";
1959 case UNW_ARM64_D4:
1960 return "d4";
1961 case UNW_ARM64_D5:
1962 return "d5";
1963 case UNW_ARM64_D6:
1964 return "d6";
1965 case UNW_ARM64_D7:
1966 return "d7";
1967 case UNW_ARM64_D8:
1968 return "d8";
1969 case UNW_ARM64_D9:
1970 return "d9";
1971 case UNW_ARM64_D10:
1972 return "d10";
1973 case UNW_ARM64_D11:
1974 return "d11";
1975 case UNW_ARM64_D12:
1976 return "d12";
1977 case UNW_ARM64_D13:
1978 return "d13";
1979 case UNW_ARM64_D14:
1980 return "d14";
1981 case UNW_ARM64_D15:
1982 return "d15";
1983 case UNW_ARM64_D16:
1984 return "d16";
1985 case UNW_ARM64_D17:
1986 return "d17";
1987 case UNW_ARM64_D18:
1988 return "d18";
1989 case UNW_ARM64_D19:
1990 return "d19";
1991 case UNW_ARM64_D20:
1992 return "d20";
1993 case UNW_ARM64_D21:
1994 return "d21";
1995 case UNW_ARM64_D22:
1996 return "d22";
1997 case UNW_ARM64_D23:
1998 return "d23";
1999 case UNW_ARM64_D24:
2000 return "d24";
2001 case UNW_ARM64_D25:
2002 return "d25";
2003 case UNW_ARM64_D26:
2004 return "d26";
2005 case UNW_ARM64_D27:
2006 return "d27";
2007 case UNW_ARM64_D28:
2008 return "d28";
2009 case UNW_ARM64_D29:
2010 return "d29";
2011 case UNW_ARM64_D30:
2012 return "d30";
2013 case UNW_ARM64_D31:
2014 return "d31";
2015 default:
2016 return "unknown register";
2017 }
2018 }
2019
validFloatRegister(int regNum) const2020 inline bool Registers_arm64::validFloatRegister(int regNum) const {
2021 if (regNum < UNW_ARM64_D0)
2022 return false;
2023 if (regNum > UNW_ARM64_D31)
2024 return false;
2025 return true;
2026 }
2027
getFloatRegister(int regNum) const2028 inline double Registers_arm64::getFloatRegister(int regNum) const {
2029 assert(validFloatRegister(regNum));
2030 return _vectorHalfRegisters[regNum - UNW_ARM64_D0];
2031 }
2032
setFloatRegister(int regNum,double value)2033 inline void Registers_arm64::setFloatRegister(int regNum, double value) {
2034 assert(validFloatRegister(regNum));
2035 _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value;
2036 }
2037
validVectorRegister(int) const2038 inline bool Registers_arm64::validVectorRegister(int) const {
2039 return false;
2040 }
2041
getVectorRegister(int) const2042 inline v128 Registers_arm64::getVectorRegister(int) const {
2043 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2044 }
2045
setVectorRegister(int,v128)2046 inline void Registers_arm64::setVectorRegister(int, v128) {
2047 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2048 }
2049 #endif // _LIBUNWIND_TARGET_AARCH64
2050
2051 #if defined(_LIBUNWIND_TARGET_ARM)
2052 /// Registers_arm holds the register state of a thread in a 32-bit arm
2053 /// process.
2054 ///
2055 /// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2056 /// this uses more memory than required.
2057 class _LIBUNWIND_HIDDEN Registers_arm {
2058 public:
2059 Registers_arm();
2060 Registers_arm(const void *registers);
2061
2062 bool validRegister(int num) const;
2063 uint32_t getRegister(int num) const;
2064 void setRegister(int num, uint32_t value);
2065 bool validFloatRegister(int num) const;
2066 unw_fpreg_t getFloatRegister(int num);
2067 void setFloatRegister(int num, unw_fpreg_t value);
2068 bool validVectorRegister(int num) const;
2069 v128 getVectorRegister(int num) const;
2070 void setVectorRegister(int num, v128 value);
2071 static const char *getRegisterName(int num);
jumpto()2072 void jumpto() {
2073 restoreSavedFloatRegisters();
2074 restoreCoreAndJumpTo();
2075 }
lastDwarfRegNum()2076 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; }
getArch()2077 static int getArch() { return REGISTERS_ARM; }
2078
getSP() const2079 uint32_t getSP() const { return _registers.__sp; }
setSP(uint32_t value)2080 void setSP(uint32_t value) { _registers.__sp = value; }
getIP() const2081 uint32_t getIP() const { return _registers.__pc; }
setIP(uint32_t value)2082 void setIP(uint32_t value) { _registers.__pc = value; }
2083
saveVFPAsX()2084 void saveVFPAsX() {
2085 assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
2086 _use_X_for_vfp_save = true;
2087 }
2088
restoreSavedFloatRegisters()2089 void restoreSavedFloatRegisters() {
2090 if (_saved_vfp_d0_d15) {
2091 if (_use_X_for_vfp_save)
2092 restoreVFPWithFLDMX(_vfp_d0_d15_pad);
2093 else
2094 restoreVFPWithFLDMD(_vfp_d0_d15_pad);
2095 }
2096 if (_saved_vfp_d16_d31)
2097 restoreVFPv3(_vfp_d16_d31);
2098 #if defined(__ARM_WMMX)
2099 if (_saved_iwmmx)
2100 restoreiWMMX(_iwmmx);
2101 if (_saved_iwmmx_control)
2102 restoreiWMMXControl(_iwmmx_control);
2103 #endif
2104 }
2105
2106 private:
2107 struct GPRs {
2108 uint32_t __r[13]; // r0-r12
2109 uint32_t __sp; // Stack pointer r13
2110 uint32_t __lr; // Link register r14
2111 uint32_t __pc; // Program counter r15
2112 };
2113
2114 static void saveVFPWithFSTMD(void*);
2115 static void saveVFPWithFSTMX(void*);
2116 static void saveVFPv3(void*);
2117 static void restoreVFPWithFLDMD(void*);
2118 static void restoreVFPWithFLDMX(void*);
2119 static void restoreVFPv3(void*);
2120 #if defined(__ARM_WMMX)
2121 static void saveiWMMX(void*);
2122 static void saveiWMMXControl(uint32_t*);
2123 static void restoreiWMMX(void*);
2124 static void restoreiWMMXControl(uint32_t*);
2125 #endif
2126 void restoreCoreAndJumpTo();
2127
2128 // ARM registers
2129 GPRs _registers;
2130
2131 // We save floating point registers lazily because we can't know ahead of
2132 // time which ones are used. See EHABI #4.7.
2133
2134 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2135 //
2136 // See EHABI #7.5 that explains how matching instruction sequences for load
2137 // and store need to be used to correctly restore the exact register bits.
2138 bool _use_X_for_vfp_save;
2139 // Whether VFP D0-D15 are saved.
2140 bool _saved_vfp_d0_d15;
2141 // Whether VFPv3 D16-D31 are saved.
2142 bool _saved_vfp_d16_d31;
2143 // VFP registers D0-D15, + padding if saved using FSTMX
2144 unw_fpreg_t _vfp_d0_d15_pad[17];
2145 // VFPv3 registers D16-D31, always saved using FSTMD
2146 unw_fpreg_t _vfp_d16_d31[16];
2147 #if defined(__ARM_WMMX)
2148 // Whether iWMMX data registers are saved.
2149 bool _saved_iwmmx;
2150 // Whether iWMMX control registers are saved.
2151 mutable bool _saved_iwmmx_control;
2152 // iWMMX registers
2153 unw_fpreg_t _iwmmx[16];
2154 // iWMMX control registers
2155 mutable uint32_t _iwmmx_control[4];
2156 #endif
2157 };
2158
Registers_arm(const void * registers)2159 inline Registers_arm::Registers_arm(const void *registers)
2160 : _use_X_for_vfp_save(false),
2161 _saved_vfp_d0_d15(false),
2162 _saved_vfp_d16_d31(false) {
2163 static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
2164 "arm registers do not fit into unw_context_t");
2165 // See __unw_getcontext() note about data.
2166 memcpy(&_registers, registers, sizeof(_registers));
2167 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2168 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2169 #if defined(__ARM_WMMX)
2170 _saved_iwmmx = false;
2171 _saved_iwmmx_control = false;
2172 memset(&_iwmmx, 0, sizeof(_iwmmx));
2173 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2174 #endif
2175 }
2176
Registers_arm()2177 inline Registers_arm::Registers_arm()
2178 : _use_X_for_vfp_save(false),
2179 _saved_vfp_d0_d15(false),
2180 _saved_vfp_d16_d31(false) {
2181 memset(&_registers, 0, sizeof(_registers));
2182 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2183 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2184 #if defined(__ARM_WMMX)
2185 _saved_iwmmx = false;
2186 _saved_iwmmx_control = false;
2187 memset(&_iwmmx, 0, sizeof(_iwmmx));
2188 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2189 #endif
2190 }
2191
validRegister(int regNum) const2192 inline bool Registers_arm::validRegister(int regNum) const {
2193 // Returns true for all non-VFP registers supported by the EHABI
2194 // virtual register set (VRS).
2195 if (regNum == UNW_REG_IP)
2196 return true;
2197
2198 if (regNum == UNW_REG_SP)
2199 return true;
2200
2201 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
2202 return true;
2203
2204 #if defined(__ARM_WMMX)
2205 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
2206 return true;
2207 #endif
2208
2209 return false;
2210 }
2211
getRegister(int regNum) const2212 inline uint32_t Registers_arm::getRegister(int regNum) const {
2213 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
2214 return _registers.__sp;
2215
2216 if (regNum == UNW_ARM_LR)
2217 return _registers.__lr;
2218
2219 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
2220 return _registers.__pc;
2221
2222 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
2223 return _registers.__r[regNum];
2224
2225 #if defined(__ARM_WMMX)
2226 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2227 if (!_saved_iwmmx_control) {
2228 _saved_iwmmx_control = true;
2229 saveiWMMXControl(_iwmmx_control);
2230 }
2231 return _iwmmx_control[regNum - UNW_ARM_WC0];
2232 }
2233 #endif
2234
2235 _LIBUNWIND_ABORT("unsupported arm register");
2236 }
2237
setRegister(int regNum,uint32_t value)2238 inline void Registers_arm::setRegister(int regNum, uint32_t value) {
2239 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
2240 _registers.__sp = value;
2241 return;
2242 }
2243
2244 if (regNum == UNW_ARM_LR) {
2245 _registers.__lr = value;
2246 return;
2247 }
2248
2249 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
2250 _registers.__pc = value;
2251 return;
2252 }
2253
2254 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
2255 _registers.__r[regNum] = value;
2256 return;
2257 }
2258
2259 #if defined(__ARM_WMMX)
2260 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2261 if (!_saved_iwmmx_control) {
2262 _saved_iwmmx_control = true;
2263 saveiWMMXControl(_iwmmx_control);
2264 }
2265 _iwmmx_control[regNum - UNW_ARM_WC0] = value;
2266 return;
2267 }
2268 #endif
2269
2270 _LIBUNWIND_ABORT("unsupported arm register");
2271 }
2272
getRegisterName(int regNum)2273 inline const char *Registers_arm::getRegisterName(int regNum) {
2274 switch (regNum) {
2275 case UNW_REG_IP:
2276 case UNW_ARM_IP: // UNW_ARM_R15 is alias
2277 return "pc";
2278 case UNW_ARM_LR: // UNW_ARM_R14 is alias
2279 return "lr";
2280 case UNW_REG_SP:
2281 case UNW_ARM_SP: // UNW_ARM_R13 is alias
2282 return "sp";
2283 case UNW_ARM_R0:
2284 return "r0";
2285 case UNW_ARM_R1:
2286 return "r1";
2287 case UNW_ARM_R2:
2288 return "r2";
2289 case UNW_ARM_R3:
2290 return "r3";
2291 case UNW_ARM_R4:
2292 return "r4";
2293 case UNW_ARM_R5:
2294 return "r5";
2295 case UNW_ARM_R6:
2296 return "r6";
2297 case UNW_ARM_R7:
2298 return "r7";
2299 case UNW_ARM_R8:
2300 return "r8";
2301 case UNW_ARM_R9:
2302 return "r9";
2303 case UNW_ARM_R10:
2304 return "r10";
2305 case UNW_ARM_R11:
2306 return "r11";
2307 case UNW_ARM_R12:
2308 return "r12";
2309 case UNW_ARM_S0:
2310 return "s0";
2311 case UNW_ARM_S1:
2312 return "s1";
2313 case UNW_ARM_S2:
2314 return "s2";
2315 case UNW_ARM_S3:
2316 return "s3";
2317 case UNW_ARM_S4:
2318 return "s4";
2319 case UNW_ARM_S5:
2320 return "s5";
2321 case UNW_ARM_S6:
2322 return "s6";
2323 case UNW_ARM_S7:
2324 return "s7";
2325 case UNW_ARM_S8:
2326 return "s8";
2327 case UNW_ARM_S9:
2328 return "s9";
2329 case UNW_ARM_S10:
2330 return "s10";
2331 case UNW_ARM_S11:
2332 return "s11";
2333 case UNW_ARM_S12:
2334 return "s12";
2335 case UNW_ARM_S13:
2336 return "s13";
2337 case UNW_ARM_S14:
2338 return "s14";
2339 case UNW_ARM_S15:
2340 return "s15";
2341 case UNW_ARM_S16:
2342 return "s16";
2343 case UNW_ARM_S17:
2344 return "s17";
2345 case UNW_ARM_S18:
2346 return "s18";
2347 case UNW_ARM_S19:
2348 return "s19";
2349 case UNW_ARM_S20:
2350 return "s20";
2351 case UNW_ARM_S21:
2352 return "s21";
2353 case UNW_ARM_S22:
2354 return "s22";
2355 case UNW_ARM_S23:
2356 return "s23";
2357 case UNW_ARM_S24:
2358 return "s24";
2359 case UNW_ARM_S25:
2360 return "s25";
2361 case UNW_ARM_S26:
2362 return "s26";
2363 case UNW_ARM_S27:
2364 return "s27";
2365 case UNW_ARM_S28:
2366 return "s28";
2367 case UNW_ARM_S29:
2368 return "s29";
2369 case UNW_ARM_S30:
2370 return "s30";
2371 case UNW_ARM_S31:
2372 return "s31";
2373 case UNW_ARM_D0:
2374 return "d0";
2375 case UNW_ARM_D1:
2376 return "d1";
2377 case UNW_ARM_D2:
2378 return "d2";
2379 case UNW_ARM_D3:
2380 return "d3";
2381 case UNW_ARM_D4:
2382 return "d4";
2383 case UNW_ARM_D5:
2384 return "d5";
2385 case UNW_ARM_D6:
2386 return "d6";
2387 case UNW_ARM_D7:
2388 return "d7";
2389 case UNW_ARM_D8:
2390 return "d8";
2391 case UNW_ARM_D9:
2392 return "d9";
2393 case UNW_ARM_D10:
2394 return "d10";
2395 case UNW_ARM_D11:
2396 return "d11";
2397 case UNW_ARM_D12:
2398 return "d12";
2399 case UNW_ARM_D13:
2400 return "d13";
2401 case UNW_ARM_D14:
2402 return "d14";
2403 case UNW_ARM_D15:
2404 return "d15";
2405 case UNW_ARM_D16:
2406 return "d16";
2407 case UNW_ARM_D17:
2408 return "d17";
2409 case UNW_ARM_D18:
2410 return "d18";
2411 case UNW_ARM_D19:
2412 return "d19";
2413 case UNW_ARM_D20:
2414 return "d20";
2415 case UNW_ARM_D21:
2416 return "d21";
2417 case UNW_ARM_D22:
2418 return "d22";
2419 case UNW_ARM_D23:
2420 return "d23";
2421 case UNW_ARM_D24:
2422 return "d24";
2423 case UNW_ARM_D25:
2424 return "d25";
2425 case UNW_ARM_D26:
2426 return "d26";
2427 case UNW_ARM_D27:
2428 return "d27";
2429 case UNW_ARM_D28:
2430 return "d28";
2431 case UNW_ARM_D29:
2432 return "d29";
2433 case UNW_ARM_D30:
2434 return "d30";
2435 case UNW_ARM_D31:
2436 return "d31";
2437 default:
2438 return "unknown register";
2439 }
2440 }
2441
validFloatRegister(int regNum) const2442 inline bool Registers_arm::validFloatRegister(int regNum) const {
2443 // NOTE: Consider the intel MMX registers floating points so the
2444 // __unw_get_fpreg can be used to transmit the 64-bit data back.
2445 return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
2446 #if defined(__ARM_WMMX)
2447 || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
2448 #endif
2449 ;
2450 }
2451
getFloatRegister(int regNum)2452 inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
2453 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2454 if (!_saved_vfp_d0_d15) {
2455 _saved_vfp_d0_d15 = true;
2456 if (_use_X_for_vfp_save)
2457 saveVFPWithFSTMX(_vfp_d0_d15_pad);
2458 else
2459 saveVFPWithFSTMD(_vfp_d0_d15_pad);
2460 }
2461 return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
2462 }
2463
2464 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2465 if (!_saved_vfp_d16_d31) {
2466 _saved_vfp_d16_d31 = true;
2467 saveVFPv3(_vfp_d16_d31);
2468 }
2469 return _vfp_d16_d31[regNum - UNW_ARM_D16];
2470 }
2471
2472 #if defined(__ARM_WMMX)
2473 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2474 if (!_saved_iwmmx) {
2475 _saved_iwmmx = true;
2476 saveiWMMX(_iwmmx);
2477 }
2478 return _iwmmx[regNum - UNW_ARM_WR0];
2479 }
2480 #endif
2481
2482 _LIBUNWIND_ABORT("Unknown ARM float register");
2483 }
2484
setFloatRegister(int regNum,unw_fpreg_t value)2485 inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
2486 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2487 if (!_saved_vfp_d0_d15) {
2488 _saved_vfp_d0_d15 = true;
2489 if (_use_X_for_vfp_save)
2490 saveVFPWithFSTMX(_vfp_d0_d15_pad);
2491 else
2492 saveVFPWithFSTMD(_vfp_d0_d15_pad);
2493 }
2494 _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
2495 return;
2496 }
2497
2498 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2499 if (!_saved_vfp_d16_d31) {
2500 _saved_vfp_d16_d31 = true;
2501 saveVFPv3(_vfp_d16_d31);
2502 }
2503 _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
2504 return;
2505 }
2506
2507 #if defined(__ARM_WMMX)
2508 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2509 if (!_saved_iwmmx) {
2510 _saved_iwmmx = true;
2511 saveiWMMX(_iwmmx);
2512 }
2513 _iwmmx[regNum - UNW_ARM_WR0] = value;
2514 return;
2515 }
2516 #endif
2517
2518 _LIBUNWIND_ABORT("Unknown ARM float register");
2519 }
2520
validVectorRegister(int) const2521 inline bool Registers_arm::validVectorRegister(int) const {
2522 return false;
2523 }
2524
getVectorRegister(int) const2525 inline v128 Registers_arm::getVectorRegister(int) const {
2526 _LIBUNWIND_ABORT("ARM vector support not implemented");
2527 }
2528
setVectorRegister(int,v128)2529 inline void Registers_arm::setVectorRegister(int, v128) {
2530 _LIBUNWIND_ABORT("ARM vector support not implemented");
2531 }
2532 #endif // _LIBUNWIND_TARGET_ARM
2533
2534
2535 #if defined(_LIBUNWIND_TARGET_OR1K)
2536 /// Registers_or1k holds the register state of a thread in an OpenRISC1000
2537 /// process.
2538 class _LIBUNWIND_HIDDEN Registers_or1k {
2539 public:
2540 Registers_or1k();
2541 Registers_or1k(const void *registers);
2542
2543 bool validRegister(int num) const;
2544 uint32_t getRegister(int num) const;
2545 void setRegister(int num, uint32_t value);
2546 bool validFloatRegister(int num) const;
2547 double getFloatRegister(int num) const;
2548 void setFloatRegister(int num, double value);
2549 bool validVectorRegister(int num) const;
2550 v128 getVectorRegister(int num) const;
2551 void setVectorRegister(int num, v128 value);
2552 static const char *getRegisterName(int num);
2553 void jumpto();
lastDwarfRegNum()2554 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; }
getArch()2555 static int getArch() { return REGISTERS_OR1K; }
2556
getSP() const2557 uint64_t getSP() const { return _registers.__r[1]; }
setSP(uint32_t value)2558 void setSP(uint32_t value) { _registers.__r[1] = value; }
getIP() const2559 uint64_t getIP() const { return _registers.__pc; }
setIP(uint32_t value)2560 void setIP(uint32_t value) { _registers.__pc = value; }
2561
2562 private:
2563 struct or1k_thread_state_t {
2564 unsigned int __r[32]; // r0-r31
2565 unsigned int __pc; // Program counter
2566 unsigned int __epcr; // Program counter at exception
2567 };
2568
2569 or1k_thread_state_t _registers;
2570 };
2571
Registers_or1k(const void * registers)2572 inline Registers_or1k::Registers_or1k(const void *registers) {
2573 static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
2574 "or1k registers do not fit into unw_context_t");
2575 memcpy(&_registers, static_cast<const uint8_t *>(registers),
2576 sizeof(_registers));
2577 }
2578
Registers_or1k()2579 inline Registers_or1k::Registers_or1k() {
2580 memset(&_registers, 0, sizeof(_registers));
2581 }
2582
validRegister(int regNum) const2583 inline bool Registers_or1k::validRegister(int regNum) const {
2584 if (regNum == UNW_REG_IP)
2585 return true;
2586 if (regNum == UNW_REG_SP)
2587 return true;
2588 if (regNum < 0)
2589 return false;
2590 if (regNum <= UNW_OR1K_R31)
2591 return true;
2592 if (regNum == UNW_OR1K_EPCR)
2593 return true;
2594 return false;
2595 }
2596
getRegister(int regNum) const2597 inline uint32_t Registers_or1k::getRegister(int regNum) const {
2598 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
2599 return _registers.__r[regNum - UNW_OR1K_R0];
2600
2601 switch (regNum) {
2602 case UNW_REG_IP:
2603 return _registers.__pc;
2604 case UNW_REG_SP:
2605 return _registers.__r[1];
2606 case UNW_OR1K_EPCR:
2607 return _registers.__epcr;
2608 }
2609 _LIBUNWIND_ABORT("unsupported or1k register");
2610 }
2611
setRegister(int regNum,uint32_t value)2612 inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
2613 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
2614 _registers.__r[regNum - UNW_OR1K_R0] = value;
2615 return;
2616 }
2617
2618 switch (regNum) {
2619 case UNW_REG_IP:
2620 _registers.__pc = value;
2621 return;
2622 case UNW_REG_SP:
2623 _registers.__r[1] = value;
2624 return;
2625 case UNW_OR1K_EPCR:
2626 _registers.__epcr = value;
2627 return;
2628 }
2629 _LIBUNWIND_ABORT("unsupported or1k register");
2630 }
2631
validFloatRegister(int) const2632 inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2633 return false;
2634 }
2635
getFloatRegister(int) const2636 inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2637 _LIBUNWIND_ABORT("or1k float support not implemented");
2638 }
2639
setFloatRegister(int,double)2640 inline void Registers_or1k::setFloatRegister(int /* regNum */,
2641 double /* value */) {
2642 _LIBUNWIND_ABORT("or1k float support not implemented");
2643 }
2644
validVectorRegister(int) const2645 inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2646 return false;
2647 }
2648
getVectorRegister(int) const2649 inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
2650 _LIBUNWIND_ABORT("or1k vector support not implemented");
2651 }
2652
setVectorRegister(int,v128)2653 inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
2654 _LIBUNWIND_ABORT("or1k vector support not implemented");
2655 }
2656
getRegisterName(int regNum)2657 inline const char *Registers_or1k::getRegisterName(int regNum) {
2658 switch (regNum) {
2659 case UNW_OR1K_R0:
2660 return "r0";
2661 case UNW_OR1K_R1:
2662 return "r1";
2663 case UNW_OR1K_R2:
2664 return "r2";
2665 case UNW_OR1K_R3:
2666 return "r3";
2667 case UNW_OR1K_R4:
2668 return "r4";
2669 case UNW_OR1K_R5:
2670 return "r5";
2671 case UNW_OR1K_R6:
2672 return "r6";
2673 case UNW_OR1K_R7:
2674 return "r7";
2675 case UNW_OR1K_R8:
2676 return "r8";
2677 case UNW_OR1K_R9:
2678 return "r9";
2679 case UNW_OR1K_R10:
2680 return "r10";
2681 case UNW_OR1K_R11:
2682 return "r11";
2683 case UNW_OR1K_R12:
2684 return "r12";
2685 case UNW_OR1K_R13:
2686 return "r13";
2687 case UNW_OR1K_R14:
2688 return "r14";
2689 case UNW_OR1K_R15:
2690 return "r15";
2691 case UNW_OR1K_R16:
2692 return "r16";
2693 case UNW_OR1K_R17:
2694 return "r17";
2695 case UNW_OR1K_R18:
2696 return "r18";
2697 case UNW_OR1K_R19:
2698 return "r19";
2699 case UNW_OR1K_R20:
2700 return "r20";
2701 case UNW_OR1K_R21:
2702 return "r21";
2703 case UNW_OR1K_R22:
2704 return "r22";
2705 case UNW_OR1K_R23:
2706 return "r23";
2707 case UNW_OR1K_R24:
2708 return "r24";
2709 case UNW_OR1K_R25:
2710 return "r25";
2711 case UNW_OR1K_R26:
2712 return "r26";
2713 case UNW_OR1K_R27:
2714 return "r27";
2715 case UNW_OR1K_R28:
2716 return "r28";
2717 case UNW_OR1K_R29:
2718 return "r29";
2719 case UNW_OR1K_R30:
2720 return "r30";
2721 case UNW_OR1K_R31:
2722 return "r31";
2723 case UNW_OR1K_EPCR:
2724 return "EPCR";
2725 default:
2726 return "unknown register";
2727 }
2728
2729 }
2730 #endif // _LIBUNWIND_TARGET_OR1K
2731
2732 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
2733 /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2734 /// process.
2735 class _LIBUNWIND_HIDDEN Registers_mips_o32 {
2736 public:
2737 Registers_mips_o32();
2738 Registers_mips_o32(const void *registers);
2739
2740 bool validRegister(int num) const;
2741 uint32_t getRegister(int num) const;
2742 void setRegister(int num, uint32_t value);
2743 bool validFloatRegister(int num) const;
2744 double getFloatRegister(int num) const;
2745 void setFloatRegister(int num, double value);
2746 bool validVectorRegister(int num) const;
2747 v128 getVectorRegister(int num) const;
2748 void setVectorRegister(int num, v128 value);
2749 static const char *getRegisterName(int num);
2750 void jumpto();
lastDwarfRegNum()2751 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
getArch()2752 static int getArch() { return REGISTERS_MIPS_O32; }
2753
getSP() const2754 uint32_t getSP() const { return _registers.__r[29]; }
setSP(uint32_t value)2755 void setSP(uint32_t value) { _registers.__r[29] = value; }
getIP() const2756 uint32_t getIP() const { return _registers.__pc; }
setIP(uint32_t value)2757 void setIP(uint32_t value) { _registers.__pc = value; }
2758
2759 private:
2760 struct mips_o32_thread_state_t {
2761 uint32_t __r[32];
2762 uint32_t __pc;
2763 uint32_t __hi;
2764 uint32_t __lo;
2765 };
2766
2767 mips_o32_thread_state_t _registers;
2768 #ifdef __mips_hard_float
2769 /// O32 with 32-bit floating point registers only uses half of this
2770 /// space. However, using the same layout for 32-bit vs 64-bit
2771 /// floating point registers results in a single context size for
2772 /// O32 with hard float.
2773 uint32_t _padding;
2774 double _floats[32];
2775 #endif
2776 };
2777
Registers_mips_o32(const void * registers)2778 inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
2779 static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
2780 "mips_o32 registers do not fit into unw_context_t");
2781 memcpy(&_registers, static_cast<const uint8_t *>(registers),
2782 sizeof(_registers));
2783 }
2784
Registers_mips_o32()2785 inline Registers_mips_o32::Registers_mips_o32() {
2786 memset(&_registers, 0, sizeof(_registers));
2787 }
2788
validRegister(int regNum) const2789 inline bool Registers_mips_o32::validRegister(int regNum) const {
2790 if (regNum == UNW_REG_IP)
2791 return true;
2792 if (regNum == UNW_REG_SP)
2793 return true;
2794 if (regNum < 0)
2795 return false;
2796 if (regNum <= UNW_MIPS_R31)
2797 return true;
2798 #if __mips_isa_rev != 6
2799 if (regNum == UNW_MIPS_HI)
2800 return true;
2801 if (regNum == UNW_MIPS_LO)
2802 return true;
2803 #endif
2804 #if defined(__mips_hard_float) && __mips_fpr == 32
2805 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2806 return true;
2807 #endif
2808 // FIXME: DSP accumulator registers, MSA registers
2809 return false;
2810 }
2811
getRegister(int regNum) const2812 inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
2813 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
2814 return _registers.__r[regNum - UNW_MIPS_R0];
2815 #if defined(__mips_hard_float) && __mips_fpr == 32
2816 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2817 uint32_t *p;
2818
2819 if (regNum % 2 == 0)
2820 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2821 else
2822 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2823 return *p;
2824 }
2825 #endif
2826
2827 switch (regNum) {
2828 case UNW_REG_IP:
2829 return _registers.__pc;
2830 case UNW_REG_SP:
2831 return _registers.__r[29];
2832 case UNW_MIPS_HI:
2833 return _registers.__hi;
2834 case UNW_MIPS_LO:
2835 return _registers.__lo;
2836 }
2837 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2838 }
2839
setRegister(int regNum,uint32_t value)2840 inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
2841 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
2842 _registers.__r[regNum - UNW_MIPS_R0] = value;
2843 return;
2844 }
2845 #if defined(__mips_hard_float) && __mips_fpr == 32
2846 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2847 uint32_t *p;
2848
2849 if (regNum % 2 == 0)
2850 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2851 else
2852 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2853 *p = value;
2854 return;
2855 }
2856 #endif
2857
2858 switch (regNum) {
2859 case UNW_REG_IP:
2860 _registers.__pc = value;
2861 return;
2862 case UNW_REG_SP:
2863 _registers.__r[29] = value;
2864 return;
2865 case UNW_MIPS_HI:
2866 _registers.__hi = value;
2867 return;
2868 case UNW_MIPS_LO:
2869 _registers.__lo = value;
2870 return;
2871 }
2872 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2873 }
2874
validFloatRegister(int regNum) const2875 inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
2876 #if defined(__mips_hard_float) && __mips_fpr == 64
2877 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2878 return true;
2879 #else
2880 (void)regNum;
2881 #endif
2882 return false;
2883 }
2884
getFloatRegister(int regNum) const2885 inline double Registers_mips_o32::getFloatRegister(int regNum) const {
2886 #if defined(__mips_hard_float) && __mips_fpr == 64
2887 assert(validFloatRegister(regNum));
2888 return _floats[regNum - UNW_MIPS_F0];
2889 #else
2890 (void)regNum;
2891 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2892 #endif
2893 }
2894
setFloatRegister(int regNum,double value)2895 inline void Registers_mips_o32::setFloatRegister(int regNum,
2896 double value) {
2897 #if defined(__mips_hard_float) && __mips_fpr == 64
2898 assert(validFloatRegister(regNum));
2899 _floats[regNum - UNW_MIPS_F0] = value;
2900 #else
2901 (void)regNum;
2902 (void)value;
2903 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2904 #endif
2905 }
2906
validVectorRegister(int) const2907 inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
2908 return false;
2909 }
2910
getVectorRegister(int) const2911 inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
2912 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2913 }
2914
setVectorRegister(int,v128)2915 inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
2916 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2917 }
2918
getRegisterName(int regNum)2919 inline const char *Registers_mips_o32::getRegisterName(int regNum) {
2920 switch (regNum) {
2921 case UNW_MIPS_R0:
2922 return "$0";
2923 case UNW_MIPS_R1:
2924 return "$1";
2925 case UNW_MIPS_R2:
2926 return "$2";
2927 case UNW_MIPS_R3:
2928 return "$3";
2929 case UNW_MIPS_R4:
2930 return "$4";
2931 case UNW_MIPS_R5:
2932 return "$5";
2933 case UNW_MIPS_R6:
2934 return "$6";
2935 case UNW_MIPS_R7:
2936 return "$7";
2937 case UNW_MIPS_R8:
2938 return "$8";
2939 case UNW_MIPS_R9:
2940 return "$9";
2941 case UNW_MIPS_R10:
2942 return "$10";
2943 case UNW_MIPS_R11:
2944 return "$11";
2945 case UNW_MIPS_R12:
2946 return "$12";
2947 case UNW_MIPS_R13:
2948 return "$13";
2949 case UNW_MIPS_R14:
2950 return "$14";
2951 case UNW_MIPS_R15:
2952 return "$15";
2953 case UNW_MIPS_R16:
2954 return "$16";
2955 case UNW_MIPS_R17:
2956 return "$17";
2957 case UNW_MIPS_R18:
2958 return "$18";
2959 case UNW_MIPS_R19:
2960 return "$19";
2961 case UNW_MIPS_R20:
2962 return "$20";
2963 case UNW_MIPS_R21:
2964 return "$21";
2965 case UNW_MIPS_R22:
2966 return "$22";
2967 case UNW_MIPS_R23:
2968 return "$23";
2969 case UNW_MIPS_R24:
2970 return "$24";
2971 case UNW_MIPS_R25:
2972 return "$25";
2973 case UNW_MIPS_R26:
2974 return "$26";
2975 case UNW_MIPS_R27:
2976 return "$27";
2977 case UNW_MIPS_R28:
2978 return "$28";
2979 case UNW_MIPS_R29:
2980 return "$29";
2981 case UNW_MIPS_R30:
2982 return "$30";
2983 case UNW_MIPS_R31:
2984 return "$31";
2985 case UNW_MIPS_F0:
2986 return "$f0";
2987 case UNW_MIPS_F1:
2988 return "$f1";
2989 case UNW_MIPS_F2:
2990 return "$f2";
2991 case UNW_MIPS_F3:
2992 return "$f3";
2993 case UNW_MIPS_F4:
2994 return "$f4";
2995 case UNW_MIPS_F5:
2996 return "$f5";
2997 case UNW_MIPS_F6:
2998 return "$f6";
2999 case UNW_MIPS_F7:
3000 return "$f7";
3001 case UNW_MIPS_F8:
3002 return "$f8";
3003 case UNW_MIPS_F9:
3004 return "$f9";
3005 case UNW_MIPS_F10:
3006 return "$f10";
3007 case UNW_MIPS_F11:
3008 return "$f11";
3009 case UNW_MIPS_F12:
3010 return "$f12";
3011 case UNW_MIPS_F13:
3012 return "$f13";
3013 case UNW_MIPS_F14:
3014 return "$f14";
3015 case UNW_MIPS_F15:
3016 return "$f15";
3017 case UNW_MIPS_F16:
3018 return "$f16";
3019 case UNW_MIPS_F17:
3020 return "$f17";
3021 case UNW_MIPS_F18:
3022 return "$f18";
3023 case UNW_MIPS_F19:
3024 return "$f19";
3025 case UNW_MIPS_F20:
3026 return "$f20";
3027 case UNW_MIPS_F21:
3028 return "$f21";
3029 case UNW_MIPS_F22:
3030 return "$f22";
3031 case UNW_MIPS_F23:
3032 return "$f23";
3033 case UNW_MIPS_F24:
3034 return "$f24";
3035 case UNW_MIPS_F25:
3036 return "$f25";
3037 case UNW_MIPS_F26:
3038 return "$f26";
3039 case UNW_MIPS_F27:
3040 return "$f27";
3041 case UNW_MIPS_F28:
3042 return "$f28";
3043 case UNW_MIPS_F29:
3044 return "$f29";
3045 case UNW_MIPS_F30:
3046 return "$f30";
3047 case UNW_MIPS_F31:
3048 return "$f31";
3049 case UNW_MIPS_HI:
3050 return "$hi";
3051 case UNW_MIPS_LO:
3052 return "$lo";
3053 default:
3054 return "unknown register";
3055 }
3056 }
3057 #endif // _LIBUNWIND_TARGET_MIPS_O32
3058
3059 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3060 /// Registers_mips_newabi holds the register state of a thread in a
3061 /// MIPS process using NEWABI (the N32 or N64 ABIs).
3062 class _LIBUNWIND_HIDDEN Registers_mips_newabi {
3063 public:
3064 Registers_mips_newabi();
3065 Registers_mips_newabi(const void *registers);
3066
3067 bool validRegister(int num) const;
3068 uint64_t getRegister(int num) const;
3069 void setRegister(int num, uint64_t value);
3070 bool validFloatRegister(int num) const;
3071 double getFloatRegister(int num) const;
3072 void setFloatRegister(int num, double value);
3073 bool validVectorRegister(int num) const;
3074 v128 getVectorRegister(int num) const;
3075 void setVectorRegister(int num, v128 value);
3076 static const char *getRegisterName(int num);
3077 void jumpto();
lastDwarfRegNum()3078 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
getArch()3079 static int getArch() { return REGISTERS_MIPS_NEWABI; }
3080
getSP() const3081 uint64_t getSP() const { return _registers.__r[29]; }
setSP(uint64_t value)3082 void setSP(uint64_t value) { _registers.__r[29] = value; }
getIP() const3083 uint64_t getIP() const { return _registers.__pc; }
setIP(uint64_t value)3084 void setIP(uint64_t value) { _registers.__pc = value; }
3085
3086 private:
3087 struct mips_newabi_thread_state_t {
3088 uint64_t __r[32];
3089 uint64_t __pc;
3090 uint64_t __hi;
3091 uint64_t __lo;
3092 };
3093
3094 mips_newabi_thread_state_t _registers;
3095 #ifdef __mips_hard_float
3096 double _floats[32];
3097 #endif
3098 };
3099
Registers_mips_newabi(const void * registers)3100 inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
3101 static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
3102 "mips_newabi registers do not fit into unw_context_t");
3103 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3104 sizeof(_registers));
3105 }
3106
Registers_mips_newabi()3107 inline Registers_mips_newabi::Registers_mips_newabi() {
3108 memset(&_registers, 0, sizeof(_registers));
3109 }
3110
validRegister(int regNum) const3111 inline bool Registers_mips_newabi::validRegister(int regNum) const {
3112 if (regNum == UNW_REG_IP)
3113 return true;
3114 if (regNum == UNW_REG_SP)
3115 return true;
3116 if (regNum < 0)
3117 return false;
3118 if (regNum <= UNW_MIPS_R31)
3119 return true;
3120 #if __mips_isa_rev != 6
3121 if (regNum == UNW_MIPS_HI)
3122 return true;
3123 if (regNum == UNW_MIPS_LO)
3124 return true;
3125 #endif
3126 // FIXME: Hard float, DSP accumulator registers, MSA registers
3127 return false;
3128 }
3129
getRegister(int regNum) const3130 inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
3131 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
3132 return _registers.__r[regNum - UNW_MIPS_R0];
3133
3134 switch (regNum) {
3135 case UNW_REG_IP:
3136 return _registers.__pc;
3137 case UNW_REG_SP:
3138 return _registers.__r[29];
3139 case UNW_MIPS_HI:
3140 return _registers.__hi;
3141 case UNW_MIPS_LO:
3142 return _registers.__lo;
3143 }
3144 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3145 }
3146
setRegister(int regNum,uint64_t value)3147 inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
3148 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
3149 _registers.__r[regNum - UNW_MIPS_R0] = value;
3150 return;
3151 }
3152
3153 switch (regNum) {
3154 case UNW_REG_IP:
3155 _registers.__pc = value;
3156 return;
3157 case UNW_REG_SP:
3158 _registers.__r[29] = value;
3159 return;
3160 case UNW_MIPS_HI:
3161 _registers.__hi = value;
3162 return;
3163 case UNW_MIPS_LO:
3164 _registers.__lo = value;
3165 return;
3166 }
3167 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3168 }
3169
validFloatRegister(int regNum) const3170 inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
3171 #ifdef __mips_hard_float
3172 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3173 return true;
3174 #else
3175 (void)regNum;
3176 #endif
3177 return false;
3178 }
3179
getFloatRegister(int regNum) const3180 inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
3181 #ifdef __mips_hard_float
3182 assert(validFloatRegister(regNum));
3183 return _floats[regNum - UNW_MIPS_F0];
3184 #else
3185 (void)regNum;
3186 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3187 #endif
3188 }
3189
setFloatRegister(int regNum,double value)3190 inline void Registers_mips_newabi::setFloatRegister(int regNum,
3191 double value) {
3192 #ifdef __mips_hard_float
3193 assert(validFloatRegister(regNum));
3194 _floats[regNum - UNW_MIPS_F0] = value;
3195 #else
3196 (void)regNum;
3197 (void)value;
3198 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3199 #endif
3200 }
3201
validVectorRegister(int) const3202 inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3203 return false;
3204 }
3205
getVectorRegister(int) const3206 inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3207 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3208 }
3209
setVectorRegister(int,v128)3210 inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
3211 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3212 }
3213
getRegisterName(int regNum)3214 inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
3215 switch (regNum) {
3216 case UNW_MIPS_R0:
3217 return "$0";
3218 case UNW_MIPS_R1:
3219 return "$1";
3220 case UNW_MIPS_R2:
3221 return "$2";
3222 case UNW_MIPS_R3:
3223 return "$3";
3224 case UNW_MIPS_R4:
3225 return "$4";
3226 case UNW_MIPS_R5:
3227 return "$5";
3228 case UNW_MIPS_R6:
3229 return "$6";
3230 case UNW_MIPS_R7:
3231 return "$7";
3232 case UNW_MIPS_R8:
3233 return "$8";
3234 case UNW_MIPS_R9:
3235 return "$9";
3236 case UNW_MIPS_R10:
3237 return "$10";
3238 case UNW_MIPS_R11:
3239 return "$11";
3240 case UNW_MIPS_R12:
3241 return "$12";
3242 case UNW_MIPS_R13:
3243 return "$13";
3244 case UNW_MIPS_R14:
3245 return "$14";
3246 case UNW_MIPS_R15:
3247 return "$15";
3248 case UNW_MIPS_R16:
3249 return "$16";
3250 case UNW_MIPS_R17:
3251 return "$17";
3252 case UNW_MIPS_R18:
3253 return "$18";
3254 case UNW_MIPS_R19:
3255 return "$19";
3256 case UNW_MIPS_R20:
3257 return "$20";
3258 case UNW_MIPS_R21:
3259 return "$21";
3260 case UNW_MIPS_R22:
3261 return "$22";
3262 case UNW_MIPS_R23:
3263 return "$23";
3264 case UNW_MIPS_R24:
3265 return "$24";
3266 case UNW_MIPS_R25:
3267 return "$25";
3268 case UNW_MIPS_R26:
3269 return "$26";
3270 case UNW_MIPS_R27:
3271 return "$27";
3272 case UNW_MIPS_R28:
3273 return "$28";
3274 case UNW_MIPS_R29:
3275 return "$29";
3276 case UNW_MIPS_R30:
3277 return "$30";
3278 case UNW_MIPS_R31:
3279 return "$31";
3280 case UNW_MIPS_F0:
3281 return "$f0";
3282 case UNW_MIPS_F1:
3283 return "$f1";
3284 case UNW_MIPS_F2:
3285 return "$f2";
3286 case UNW_MIPS_F3:
3287 return "$f3";
3288 case UNW_MIPS_F4:
3289 return "$f4";
3290 case UNW_MIPS_F5:
3291 return "$f5";
3292 case UNW_MIPS_F6:
3293 return "$f6";
3294 case UNW_MIPS_F7:
3295 return "$f7";
3296 case UNW_MIPS_F8:
3297 return "$f8";
3298 case UNW_MIPS_F9:
3299 return "$f9";
3300 case UNW_MIPS_F10:
3301 return "$f10";
3302 case UNW_MIPS_F11:
3303 return "$f11";
3304 case UNW_MIPS_F12:
3305 return "$f12";
3306 case UNW_MIPS_F13:
3307 return "$f13";
3308 case UNW_MIPS_F14:
3309 return "$f14";
3310 case UNW_MIPS_F15:
3311 return "$f15";
3312 case UNW_MIPS_F16:
3313 return "$f16";
3314 case UNW_MIPS_F17:
3315 return "$f17";
3316 case UNW_MIPS_F18:
3317 return "$f18";
3318 case UNW_MIPS_F19:
3319 return "$f19";
3320 case UNW_MIPS_F20:
3321 return "$f20";
3322 case UNW_MIPS_F21:
3323 return "$f21";
3324 case UNW_MIPS_F22:
3325 return "$f22";
3326 case UNW_MIPS_F23:
3327 return "$f23";
3328 case UNW_MIPS_F24:
3329 return "$f24";
3330 case UNW_MIPS_F25:
3331 return "$f25";
3332 case UNW_MIPS_F26:
3333 return "$f26";
3334 case UNW_MIPS_F27:
3335 return "$f27";
3336 case UNW_MIPS_F28:
3337 return "$f28";
3338 case UNW_MIPS_F29:
3339 return "$f29";
3340 case UNW_MIPS_F30:
3341 return "$f30";
3342 case UNW_MIPS_F31:
3343 return "$f31";
3344 case UNW_MIPS_HI:
3345 return "$hi";
3346 case UNW_MIPS_LO:
3347 return "$lo";
3348 default:
3349 return "unknown register";
3350 }
3351 }
3352 #endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3353
3354 #if defined(_LIBUNWIND_TARGET_SPARC)
3355 /// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3356 /// process.
3357 class _LIBUNWIND_HIDDEN Registers_sparc {
3358 public:
3359 Registers_sparc();
3360 Registers_sparc(const void *registers);
3361
3362 bool validRegister(int num) const;
3363 uint32_t getRegister(int num) const;
3364 void setRegister(int num, uint32_t value);
3365 bool validFloatRegister(int num) const;
3366 double getFloatRegister(int num) const;
3367 void setFloatRegister(int num, double value);
3368 bool validVectorRegister(int num) const;
3369 v128 getVectorRegister(int num) const;
3370 void setVectorRegister(int num, v128 value);
3371 static const char *getRegisterName(int num);
3372 void jumpto();
lastDwarfRegNum()3373 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; }
getArch()3374 static int getArch() { return REGISTERS_SPARC; }
3375
getSP() const3376 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
setSP(uint32_t value)3377 void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
getIP() const3378 uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
setIP(uint32_t value)3379 void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3380
3381 private:
3382 struct sparc_thread_state_t {
3383 unsigned int __regs[32];
3384 };
3385
3386 sparc_thread_state_t _registers;
3387 };
3388
Registers_sparc(const void * registers)3389 inline Registers_sparc::Registers_sparc(const void *registers) {
3390 static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
3391 "sparc registers do not fit into unw_context_t");
3392 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3393 sizeof(_registers));
3394 }
3395
Registers_sparc()3396 inline Registers_sparc::Registers_sparc() {
3397 memset(&_registers, 0, sizeof(_registers));
3398 }
3399
validRegister(int regNum) const3400 inline bool Registers_sparc::validRegister(int regNum) const {
3401 if (regNum == UNW_REG_IP)
3402 return true;
3403 if (regNum == UNW_REG_SP)
3404 return true;
3405 if (regNum < 0)
3406 return false;
3407 if (regNum <= UNW_SPARC_I7)
3408 return true;
3409 return false;
3410 }
3411
getRegister(int regNum) const3412 inline uint32_t Registers_sparc::getRegister(int regNum) const {
3413 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3414 return _registers.__regs[regNum];
3415 }
3416
3417 switch (regNum) {
3418 case UNW_REG_IP:
3419 return _registers.__regs[UNW_SPARC_O7];
3420 case UNW_REG_SP:
3421 return _registers.__regs[UNW_SPARC_O6];
3422 }
3423 _LIBUNWIND_ABORT("unsupported sparc register");
3424 }
3425
setRegister(int regNum,uint32_t value)3426 inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
3427 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3428 _registers.__regs[regNum] = value;
3429 return;
3430 }
3431
3432 switch (regNum) {
3433 case UNW_REG_IP:
3434 _registers.__regs[UNW_SPARC_O7] = value;
3435 return;
3436 case UNW_REG_SP:
3437 _registers.__regs[UNW_SPARC_O6] = value;
3438 return;
3439 }
3440 _LIBUNWIND_ABORT("unsupported sparc register");
3441 }
3442
validFloatRegister(int) const3443 inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3444
getFloatRegister(int) const3445 inline double Registers_sparc::getFloatRegister(int) const {
3446 _LIBUNWIND_ABORT("no Sparc float registers");
3447 }
3448
setFloatRegister(int,double)3449 inline void Registers_sparc::setFloatRegister(int, double) {
3450 _LIBUNWIND_ABORT("no Sparc float registers");
3451 }
3452
validVectorRegister(int) const3453 inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3454
getVectorRegister(int) const3455 inline v128 Registers_sparc::getVectorRegister(int) const {
3456 _LIBUNWIND_ABORT("no Sparc vector registers");
3457 }
3458
setVectorRegister(int,v128)3459 inline void Registers_sparc::setVectorRegister(int, v128) {
3460 _LIBUNWIND_ABORT("no Sparc vector registers");
3461 }
3462
getRegisterName(int regNum)3463 inline const char *Registers_sparc::getRegisterName(int regNum) {
3464 switch (regNum) {
3465 case UNW_REG_IP:
3466 return "pc";
3467 case UNW_SPARC_G0:
3468 return "g0";
3469 case UNW_SPARC_G1:
3470 return "g1";
3471 case UNW_SPARC_G2:
3472 return "g2";
3473 case UNW_SPARC_G3:
3474 return "g3";
3475 case UNW_SPARC_G4:
3476 return "g4";
3477 case UNW_SPARC_G5:
3478 return "g5";
3479 case UNW_SPARC_G6:
3480 return "g6";
3481 case UNW_SPARC_G7:
3482 return "g7";
3483 case UNW_SPARC_O0:
3484 return "o0";
3485 case UNW_SPARC_O1:
3486 return "o1";
3487 case UNW_SPARC_O2:
3488 return "o2";
3489 case UNW_SPARC_O3:
3490 return "o3";
3491 case UNW_SPARC_O4:
3492 return "o4";
3493 case UNW_SPARC_O5:
3494 return "o5";
3495 case UNW_REG_SP:
3496 case UNW_SPARC_O6:
3497 return "sp";
3498 case UNW_SPARC_O7:
3499 return "o7";
3500 case UNW_SPARC_L0:
3501 return "l0";
3502 case UNW_SPARC_L1:
3503 return "l1";
3504 case UNW_SPARC_L2:
3505 return "l2";
3506 case UNW_SPARC_L3:
3507 return "l3";
3508 case UNW_SPARC_L4:
3509 return "l4";
3510 case UNW_SPARC_L5:
3511 return "l5";
3512 case UNW_SPARC_L6:
3513 return "l6";
3514 case UNW_SPARC_L7:
3515 return "l7";
3516 case UNW_SPARC_I0:
3517 return "i0";
3518 case UNW_SPARC_I1:
3519 return "i1";
3520 case UNW_SPARC_I2:
3521 return "i2";
3522 case UNW_SPARC_I3:
3523 return "i3";
3524 case UNW_SPARC_I4:
3525 return "i4";
3526 case UNW_SPARC_I5:
3527 return "i5";
3528 case UNW_SPARC_I6:
3529 return "fp";
3530 case UNW_SPARC_I7:
3531 return "i7";
3532 default:
3533 return "unknown register";
3534 }
3535 }
3536 #endif // _LIBUNWIND_TARGET_SPARC
3537
3538 #if defined(_LIBUNWIND_TARGET_HEXAGON)
3539 /// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
3540 /// process.
3541 class _LIBUNWIND_HIDDEN Registers_hexagon {
3542 public:
3543 Registers_hexagon();
3544 Registers_hexagon(const void *registers);
3545
3546 bool validRegister(int num) const;
3547 uint32_t getRegister(int num) const;
3548 void setRegister(int num, uint32_t value);
3549 bool validFloatRegister(int num) const;
3550 double getFloatRegister(int num) const;
3551 void setFloatRegister(int num, double value);
3552 bool validVectorRegister(int num) const;
3553 v128 getVectorRegister(int num) const;
3554 void setVectorRegister(int num, v128 value);
3555 const char *getRegisterName(int num);
3556 void jumpto();
lastDwarfRegNum()3557 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON; }
getArch()3558 static int getArch() { return REGISTERS_HEXAGON; }
3559
getSP() const3560 uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }
setSP(uint32_t value)3561 void setSP(uint32_t value) { _registers.__r[UNW_HEXAGON_R29] = value; }
getIP() const3562 uint32_t getIP() const { return _registers.__r[UNW_HEXAGON_PC]; }
setIP(uint32_t value)3563 void setIP(uint32_t value) { _registers.__r[UNW_HEXAGON_PC] = value; }
3564
3565 private:
3566 struct hexagon_thread_state_t {
3567 unsigned int __r[35];
3568 };
3569
3570 hexagon_thread_state_t _registers;
3571 };
3572
Registers_hexagon(const void * registers)3573 inline Registers_hexagon::Registers_hexagon(const void *registers) {
3574 static_assert((check_fit<Registers_hexagon, unw_context_t>::does_fit),
3575 "hexagon registers do not fit into unw_context_t");
3576 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3577 sizeof(_registers));
3578 }
3579
Registers_hexagon()3580 inline Registers_hexagon::Registers_hexagon() {
3581 memset(&_registers, 0, sizeof(_registers));
3582 }
3583
validRegister(int regNum) const3584 inline bool Registers_hexagon::validRegister(int regNum) const {
3585 if (regNum <= UNW_HEXAGON_R31)
3586 return true;
3587 return false;
3588 }
3589
getRegister(int regNum) const3590 inline uint32_t Registers_hexagon::getRegister(int regNum) const {
3591 if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31)
3592 return _registers.__r[regNum - UNW_HEXAGON_R0];
3593
3594 switch (regNum) {
3595 case UNW_REG_IP:
3596 return _registers.__r[UNW_HEXAGON_PC];
3597 case UNW_REG_SP:
3598 return _registers.__r[UNW_HEXAGON_R29];
3599 }
3600 _LIBUNWIND_ABORT("unsupported hexagon register");
3601 }
3602
setRegister(int regNum,uint32_t value)3603 inline void Registers_hexagon::setRegister(int regNum, uint32_t value) {
3604 if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) {
3605 _registers.__r[regNum - UNW_HEXAGON_R0] = value;
3606 return;
3607 }
3608
3609 switch (regNum) {
3610 case UNW_REG_IP:
3611 _registers.__r[UNW_HEXAGON_PC] = value;
3612 return;
3613 case UNW_REG_SP:
3614 _registers.__r[UNW_HEXAGON_R29] = value;
3615 return;
3616 }
3617 _LIBUNWIND_ABORT("unsupported hexagon register");
3618 }
3619
validFloatRegister(int) const3620 inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {
3621 return false;
3622 }
3623
getFloatRegister(int) const3624 inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {
3625 _LIBUNWIND_ABORT("hexagon float support not implemented");
3626 }
3627
setFloatRegister(int,double)3628 inline void Registers_hexagon::setFloatRegister(int /* regNum */,
3629 double /* value */) {
3630 _LIBUNWIND_ABORT("hexagon float support not implemented");
3631 }
3632
validVectorRegister(int) const3633 inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {
3634 return false;
3635 }
3636
getVectorRegister(int) const3637 inline v128 Registers_hexagon::getVectorRegister(int /* regNum */) const {
3638 _LIBUNWIND_ABORT("hexagon vector support not implemented");
3639 }
3640
setVectorRegister(int,v128)3641 inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128 /* value */) {
3642 _LIBUNWIND_ABORT("hexagon vector support not implemented");
3643 }
3644
getRegisterName(int regNum)3645 inline const char *Registers_hexagon::getRegisterName(int regNum) {
3646 switch (regNum) {
3647 case UNW_HEXAGON_R0:
3648 return "r0";
3649 case UNW_HEXAGON_R1:
3650 return "r1";
3651 case UNW_HEXAGON_R2:
3652 return "r2";
3653 case UNW_HEXAGON_R3:
3654 return "r3";
3655 case UNW_HEXAGON_R4:
3656 return "r4";
3657 case UNW_HEXAGON_R5:
3658 return "r5";
3659 case UNW_HEXAGON_R6:
3660 return "r6";
3661 case UNW_HEXAGON_R7:
3662 return "r7";
3663 case UNW_HEXAGON_R8:
3664 return "r8";
3665 case UNW_HEXAGON_R9:
3666 return "r9";
3667 case UNW_HEXAGON_R10:
3668 return "r10";
3669 case UNW_HEXAGON_R11:
3670 return "r11";
3671 case UNW_HEXAGON_R12:
3672 return "r12";
3673 case UNW_HEXAGON_R13:
3674 return "r13";
3675 case UNW_HEXAGON_R14:
3676 return "r14";
3677 case UNW_HEXAGON_R15:
3678 return "r15";
3679 case UNW_HEXAGON_R16:
3680 return "r16";
3681 case UNW_HEXAGON_R17:
3682 return "r17";
3683 case UNW_HEXAGON_R18:
3684 return "r18";
3685 case UNW_HEXAGON_R19:
3686 return "r19";
3687 case UNW_HEXAGON_R20:
3688 return "r20";
3689 case UNW_HEXAGON_R21:
3690 return "r21";
3691 case UNW_HEXAGON_R22:
3692 return "r22";
3693 case UNW_HEXAGON_R23:
3694 return "r23";
3695 case UNW_HEXAGON_R24:
3696 return "r24";
3697 case UNW_HEXAGON_R25:
3698 return "r25";
3699 case UNW_HEXAGON_R26:
3700 return "r26";
3701 case UNW_HEXAGON_R27:
3702 return "r27";
3703 case UNW_HEXAGON_R28:
3704 return "r28";
3705 case UNW_HEXAGON_R29:
3706 return "r29";
3707 case UNW_HEXAGON_R30:
3708 return "r30";
3709 case UNW_HEXAGON_R31:
3710 return "r31";
3711 default:
3712 return "unknown register";
3713 }
3714
3715 }
3716 #endif // _LIBUNWIND_TARGET_HEXAGON
3717
3718
3719 #if defined(_LIBUNWIND_TARGET_RISCV)
3720 /// Registers_riscv holds the register state of a thread in a 64-bit RISC-V
3721 /// process.
3722 class _LIBUNWIND_HIDDEN Registers_riscv {
3723 public:
3724 Registers_riscv();
3725 Registers_riscv(const void *registers);
3726
3727 bool validRegister(int num) const;
3728 uint64_t getRegister(int num) const;
3729 void setRegister(int num, uint64_t value);
3730 bool validFloatRegister(int num) const;
3731 double getFloatRegister(int num) const;
3732 void setFloatRegister(int num, double value);
3733 bool validVectorRegister(int num) const;
3734 v128 getVectorRegister(int num) const;
3735 void setVectorRegister(int num, v128 value);
3736 static const char *getRegisterName(int num);
3737 void jumpto();
lastDwarfRegNum()3738 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; }
getArch()3739 static int getArch() { return REGISTERS_RISCV; }
3740
getSP() const3741 uint64_t getSP() const { return _registers[2]; }
setSP(uint64_t value)3742 void setSP(uint64_t value) { _registers[2] = value; }
getIP() const3743 uint64_t getIP() const { return _registers[0]; }
setIP(uint64_t value)3744 void setIP(uint64_t value) { _registers[0] = value; }
3745
3746 private:
3747 // _registers[0] holds the pc
3748 uint64_t _registers[32];
3749 double _floats[32];
3750 };
3751
Registers_riscv(const void * registers)3752 inline Registers_riscv::Registers_riscv(const void *registers) {
3753 static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit),
3754 "riscv registers do not fit into unw_context_t");
3755 memcpy(&_registers, registers, sizeof(_registers));
3756 static_assert(sizeof(_registers) == 0x100,
3757 "expected float registers to be at offset 256");
3758 memcpy(_floats,
3759 static_cast<const uint8_t *>(registers) + sizeof(_registers),
3760 sizeof(_floats));
3761 }
3762
Registers_riscv()3763 inline Registers_riscv::Registers_riscv() {
3764 memset(&_registers, 0, sizeof(_registers));
3765 memset(&_floats, 0, sizeof(_floats));
3766 }
3767
validRegister(int regNum) const3768 inline bool Registers_riscv::validRegister(int regNum) const {
3769 if (regNum == UNW_REG_IP)
3770 return true;
3771 if (regNum == UNW_REG_SP)
3772 return true;
3773 if (regNum < 0)
3774 return false;
3775 if (regNum > UNW_RISCV_F31)
3776 return false;
3777 return true;
3778 }
3779
getRegister(int regNum) const3780 inline uint64_t Registers_riscv::getRegister(int regNum) const {
3781 if (regNum == UNW_REG_IP)
3782 return _registers[0];
3783 if (regNum == UNW_REG_SP)
3784 return _registers[2];
3785 if (regNum == UNW_RISCV_X0)
3786 return 0;
3787 if ((regNum > 0) && (regNum < 32))
3788 return _registers[regNum];
3789 _LIBUNWIND_ABORT("unsupported riscv register");
3790 }
3791
setRegister(int regNum,uint64_t value)3792 inline void Registers_riscv::setRegister(int regNum, uint64_t value) {
3793 if (regNum == UNW_REG_IP)
3794 _registers[0] = value;
3795 else if (regNum == UNW_REG_SP)
3796 _registers[2] = value;
3797 else if (regNum == UNW_RISCV_X0)
3798 /* x0 is hardwired to zero */
3799 return;
3800 else if ((regNum > 0) && (regNum < 32))
3801 _registers[regNum] = value;
3802 else
3803 _LIBUNWIND_ABORT("unsupported riscv register");
3804 }
3805
getRegisterName(int regNum)3806 inline const char *Registers_riscv::getRegisterName(int regNum) {
3807 switch (regNum) {
3808 case UNW_REG_IP:
3809 return "pc";
3810 case UNW_REG_SP:
3811 return "sp";
3812 case UNW_RISCV_X0:
3813 return "zero";
3814 case UNW_RISCV_X1:
3815 return "ra";
3816 case UNW_RISCV_X2:
3817 return "sp";
3818 case UNW_RISCV_X3:
3819 return "gp";
3820 case UNW_RISCV_X4:
3821 return "tp";
3822 case UNW_RISCV_X5:
3823 return "t0";
3824 case UNW_RISCV_X6:
3825 return "t1";
3826 case UNW_RISCV_X7:
3827 return "t2";
3828 case UNW_RISCV_X8:
3829 return "s0";
3830 case UNW_RISCV_X9:
3831 return "s1";
3832 case UNW_RISCV_X10:
3833 return "a0";
3834 case UNW_RISCV_X11:
3835 return "a1";
3836 case UNW_RISCV_X12:
3837 return "a2";
3838 case UNW_RISCV_X13:
3839 return "a3";
3840 case UNW_RISCV_X14:
3841 return "a4";
3842 case UNW_RISCV_X15:
3843 return "a5";
3844 case UNW_RISCV_X16:
3845 return "a6";
3846 case UNW_RISCV_X17:
3847 return "a7";
3848 case UNW_RISCV_X18:
3849 return "s2";
3850 case UNW_RISCV_X19:
3851 return "s3";
3852 case UNW_RISCV_X20:
3853 return "s4";
3854 case UNW_RISCV_X21:
3855 return "s5";
3856 case UNW_RISCV_X22:
3857 return "s6";
3858 case UNW_RISCV_X23:
3859 return "s7";
3860 case UNW_RISCV_X24:
3861 return "s8";
3862 case UNW_RISCV_X25:
3863 return "s9";
3864 case UNW_RISCV_X26:
3865 return "s10";
3866 case UNW_RISCV_X27:
3867 return "s11";
3868 case UNW_RISCV_X28:
3869 return "t3";
3870 case UNW_RISCV_X29:
3871 return "t4";
3872 case UNW_RISCV_X30:
3873 return "t5";
3874 case UNW_RISCV_X31:
3875 return "t6";
3876 case UNW_RISCV_F0:
3877 return "ft0";
3878 case UNW_RISCV_F1:
3879 return "ft1";
3880 case UNW_RISCV_F2:
3881 return "ft2";
3882 case UNW_RISCV_F3:
3883 return "ft3";
3884 case UNW_RISCV_F4:
3885 return "ft4";
3886 case UNW_RISCV_F5:
3887 return "ft5";
3888 case UNW_RISCV_F6:
3889 return "ft6";
3890 case UNW_RISCV_F7:
3891 return "ft7";
3892 case UNW_RISCV_F8:
3893 return "fs0";
3894 case UNW_RISCV_F9:
3895 return "fs1";
3896 case UNW_RISCV_F10:
3897 return "fa0";
3898 case UNW_RISCV_F11:
3899 return "fa1";
3900 case UNW_RISCV_F12:
3901 return "fa2";
3902 case UNW_RISCV_F13:
3903 return "fa3";
3904 case UNW_RISCV_F14:
3905 return "fa4";
3906 case UNW_RISCV_F15:
3907 return "fa5";
3908 case UNW_RISCV_F16:
3909 return "fa6";
3910 case UNW_RISCV_F17:
3911 return "fa7";
3912 case UNW_RISCV_F18:
3913 return "fs2";
3914 case UNW_RISCV_F19:
3915 return "fs3";
3916 case UNW_RISCV_F20:
3917 return "fs4";
3918 case UNW_RISCV_F21:
3919 return "fs5";
3920 case UNW_RISCV_F22:
3921 return "fs6";
3922 case UNW_RISCV_F23:
3923 return "fs7";
3924 case UNW_RISCV_F24:
3925 return "fs8";
3926 case UNW_RISCV_F25:
3927 return "fs9";
3928 case UNW_RISCV_F26:
3929 return "fs10";
3930 case UNW_RISCV_F27:
3931 return "fs11";
3932 case UNW_RISCV_F28:
3933 return "ft8";
3934 case UNW_RISCV_F29:
3935 return "ft9";
3936 case UNW_RISCV_F30:
3937 return "ft10";
3938 case UNW_RISCV_F31:
3939 return "ft11";
3940 default:
3941 return "unknown register";
3942 }
3943 }
3944
validFloatRegister(int regNum) const3945 inline bool Registers_riscv::validFloatRegister(int regNum) const {
3946 if (regNum < UNW_RISCV_F0)
3947 return false;
3948 if (regNum > UNW_RISCV_F31)
3949 return false;
3950 return true;
3951 }
3952
getFloatRegister(int regNum) const3953 inline double Registers_riscv::getFloatRegister(int regNum) const {
3954 #if defined(__riscv_flen) && __riscv_flen == 64
3955 assert(validFloatRegister(regNum));
3956 return _floats[regNum - UNW_RISCV_F0];
3957 #else
3958 (void)regNum;
3959 _LIBUNWIND_ABORT("libunwind not built with float support");
3960 #endif
3961 }
3962
setFloatRegister(int regNum,double value)3963 inline void Registers_riscv::setFloatRegister(int regNum, double value) {
3964 #if defined(__riscv_flen) && __riscv_flen == 64
3965 assert(validFloatRegister(regNum));
3966 _floats[regNum - UNW_RISCV_F0] = value;
3967 #else
3968 (void)regNum;
3969 (void)value;
3970 _LIBUNWIND_ABORT("libunwind not built with float support");
3971 #endif
3972 }
3973
validVectorRegister(int) const3974 inline bool Registers_riscv::validVectorRegister(int) const {
3975 return false;
3976 }
3977
getVectorRegister(int) const3978 inline v128 Registers_riscv::getVectorRegister(int) const {
3979 _LIBUNWIND_ABORT("no riscv vector register support yet");
3980 }
3981
setVectorRegister(int,v128)3982 inline void Registers_riscv::setVectorRegister(int, v128) {
3983 _LIBUNWIND_ABORT("no riscv vector register support yet");
3984 }
3985 #endif // _LIBUNWIND_TARGET_RISCV
3986 } // namespace libunwind
3987
3988 #endif // __REGISTERS_HPP__
3989