blob: 18bdffff538defe45abb236eb0d27f90c2c1cb67 [file] [log] [blame]
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001//===----------------------------- Registers.hpp --------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Models register sets for supported processors.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef __REGISTERS_HPP__
14#define __REGISTERS_HPP__
15
16#include <stdint.h>
Saleem Abdulrasool675df582015-04-24 19:39:17 +000017#include <string.h>
18
19#include "libunwind.h"
20#include "config.h"
21
22namespace libunwind {
23
24// For emulating 128-bit registers
25struct v128 { uint32_t vec[4]; };
26
27
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000028#if defined(_LIBUNWIND_TARGET_I386)
Saleem Abdulrasool675df582015-04-24 19:39:17 +000029/// Registers_x86 holds the register state of a thread in a 32-bit intel
30/// process.
31class _LIBUNWIND_HIDDEN Registers_x86 {
32public:
33 Registers_x86();
34 Registers_x86(const void *registers);
35
36 bool validRegister(int num) const;
37 uint32_t getRegister(int num) const;
38 void setRegister(int num, uint32_t value);
39 bool validFloatRegister(int) const { return false; }
40 double getFloatRegister(int num) const;
41 void setFloatRegister(int num, double value);
42 bool validVectorRegister(int) const { return false; }
43 v128 getVectorRegister(int num) const;
44 void setVectorRegister(int num, v128 value);
45 const char *getRegisterName(int num);
46 void jumpto();
47 static int lastDwarfRegNum() { return 8; }
48
49 uint32_t getSP() const { return _registers.__esp; }
50 void setSP(uint32_t value) { _registers.__esp = value; }
51 uint32_t getIP() const { return _registers.__eip; }
52 void setIP(uint32_t value) { _registers.__eip = value; }
53 uint32_t getEBP() const { return _registers.__ebp; }
54 void setEBP(uint32_t value) { _registers.__ebp = value; }
55 uint32_t getEBX() const { return _registers.__ebx; }
56 void setEBX(uint32_t value) { _registers.__ebx = value; }
57 uint32_t getECX() const { return _registers.__ecx; }
58 void setECX(uint32_t value) { _registers.__ecx = value; }
59 uint32_t getEDX() const { return _registers.__edx; }
60 void setEDX(uint32_t value) { _registers.__edx = value; }
61 uint32_t getESI() const { return _registers.__esi; }
62 void setESI(uint32_t value) { _registers.__esi = value; }
63 uint32_t getEDI() const { return _registers.__edi; }
64 void setEDI(uint32_t value) { _registers.__edi = value; }
65
66private:
67 struct GPRs {
68 unsigned int __eax;
69 unsigned int __ebx;
70 unsigned int __ecx;
71 unsigned int __edx;
72 unsigned int __edi;
73 unsigned int __esi;
74 unsigned int __ebp;
75 unsigned int __esp;
76 unsigned int __ss;
77 unsigned int __eflags;
78 unsigned int __eip;
79 unsigned int __cs;
80 unsigned int __ds;
81 unsigned int __es;
82 unsigned int __fs;
83 unsigned int __gs;
84 };
85
86 GPRs _registers;
87};
88
89inline Registers_x86::Registers_x86(const void *registers) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +000090 static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000091 "x86 registers do not fit into unw_context_t");
Saleem Abdulrasool675df582015-04-24 19:39:17 +000092 memcpy(&_registers, registers, sizeof(_registers));
93}
94
95inline Registers_x86::Registers_x86() {
96 memset(&_registers, 0, sizeof(_registers));
97}
98
99inline bool Registers_x86::validRegister(int regNum) const {
100 if (regNum == UNW_REG_IP)
101 return true;
102 if (regNum == UNW_REG_SP)
103 return true;
104 if (regNum < 0)
105 return false;
106 if (regNum > 7)
107 return false;
108 return true;
109}
110
111inline uint32_t Registers_x86::getRegister(int regNum) const {
112 switch (regNum) {
113 case UNW_REG_IP:
114 return _registers.__eip;
115 case UNW_REG_SP:
116 return _registers.__esp;
117 case UNW_X86_EAX:
118 return _registers.__eax;
119 case UNW_X86_ECX:
120 return _registers.__ecx;
121 case UNW_X86_EDX:
122 return _registers.__edx;
123 case UNW_X86_EBX:
124 return _registers.__ebx;
125 case UNW_X86_EBP:
126 return _registers.__ebp;
127 case UNW_X86_ESP:
128 return _registers.__esp;
129 case UNW_X86_ESI:
130 return _registers.__esi;
131 case UNW_X86_EDI:
132 return _registers.__edi;
133 }
134 _LIBUNWIND_ABORT("unsupported x86 register");
135}
136
137inline void Registers_x86::setRegister(int regNum, uint32_t value) {
138 switch (regNum) {
139 case UNW_REG_IP:
140 _registers.__eip = value;
141 return;
142 case UNW_REG_SP:
143 _registers.__esp = value;
144 return;
145 case UNW_X86_EAX:
146 _registers.__eax = value;
147 return;
148 case UNW_X86_ECX:
149 _registers.__ecx = value;
150 return;
151 case UNW_X86_EDX:
152 _registers.__edx = value;
153 return;
154 case UNW_X86_EBX:
155 _registers.__ebx = value;
156 return;
157 case UNW_X86_EBP:
158 _registers.__ebp = value;
159 return;
160 case UNW_X86_ESP:
161 _registers.__esp = value;
162 return;
163 case UNW_X86_ESI:
164 _registers.__esi = value;
165 return;
166 case UNW_X86_EDI:
167 _registers.__edi = value;
168 return;
169 }
170 _LIBUNWIND_ABORT("unsupported x86 register");
171}
172
173inline const char *Registers_x86::getRegisterName(int regNum) {
174 switch (regNum) {
175 case UNW_REG_IP:
176 return "ip";
177 case UNW_REG_SP:
178 return "esp";
179 case UNW_X86_EAX:
180 return "eax";
181 case UNW_X86_ECX:
182 return "ecx";
183 case UNW_X86_EDX:
184 return "edx";
185 case UNW_X86_EBX:
186 return "ebx";
187 case UNW_X86_EBP:
188 return "ebp";
189 case UNW_X86_ESP:
190 return "esp";
191 case UNW_X86_ESI:
192 return "esi";
193 case UNW_X86_EDI:
194 return "edi";
195 default:
196 return "unknown register";
197 }
198}
199
200inline double Registers_x86::getFloatRegister(int) const {
201 _LIBUNWIND_ABORT("no x86 float registers");
202}
203
204inline void Registers_x86::setFloatRegister(int, double) {
205 _LIBUNWIND_ABORT("no x86 float registers");
206}
207
208inline v128 Registers_x86::getVectorRegister(int) const {
209 _LIBUNWIND_ABORT("no x86 vector registers");
210}
211
212inline void Registers_x86::setVectorRegister(int, v128) {
213 _LIBUNWIND_ABORT("no x86 vector registers");
214}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000215#endif // _LIBUNWIND_TARGET_I386
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000216
217
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000218#if defined(_LIBUNWIND_TARGET_X86_64)
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000219/// Registers_x86_64 holds the register state of a thread in a 64-bit intel
220/// process.
221class _LIBUNWIND_HIDDEN Registers_x86_64 {
222public:
223 Registers_x86_64();
224 Registers_x86_64(const void *registers);
225
226 bool validRegister(int num) const;
227 uint64_t getRegister(int num) const;
228 void setRegister(int num, uint64_t value);
229 bool validFloatRegister(int) const { return false; }
230 double getFloatRegister(int num) const;
231 void setFloatRegister(int num, double value);
232 bool validVectorRegister(int) const { return false; }
233 v128 getVectorRegister(int num) const;
234 void setVectorRegister(int num, v128 value);
235 const char *getRegisterName(int num);
236 void jumpto();
237 static int lastDwarfRegNum() { return 16; }
238
239 uint64_t getSP() const { return _registers.__rsp; }
240 void setSP(uint64_t value) { _registers.__rsp = value; }
241 uint64_t getIP() const { return _registers.__rip; }
242 void setIP(uint64_t value) { _registers.__rip = value; }
243 uint64_t getRBP() const { return _registers.__rbp; }
244 void setRBP(uint64_t value) { _registers.__rbp = value; }
245 uint64_t getRBX() const { return _registers.__rbx; }
246 void setRBX(uint64_t value) { _registers.__rbx = value; }
247 uint64_t getR12() const { return _registers.__r12; }
248 void setR12(uint64_t value) { _registers.__r12 = value; }
249 uint64_t getR13() const { return _registers.__r13; }
250 void setR13(uint64_t value) { _registers.__r13 = value; }
251 uint64_t getR14() const { return _registers.__r14; }
252 void setR14(uint64_t value) { _registers.__r14 = value; }
253 uint64_t getR15() const { return _registers.__r15; }
254 void setR15(uint64_t value) { _registers.__r15 = value; }
255
256private:
257 struct GPRs {
258 uint64_t __rax;
259 uint64_t __rbx;
260 uint64_t __rcx;
261 uint64_t __rdx;
262 uint64_t __rdi;
263 uint64_t __rsi;
264 uint64_t __rbp;
265 uint64_t __rsp;
266 uint64_t __r8;
267 uint64_t __r9;
268 uint64_t __r10;
269 uint64_t __r11;
270 uint64_t __r12;
271 uint64_t __r13;
272 uint64_t __r14;
273 uint64_t __r15;
274 uint64_t __rip;
275 uint64_t __rflags;
276 uint64_t __cs;
277 uint64_t __fs;
278 uint64_t __gs;
279 };
280 GPRs _registers;
281};
282
283inline Registers_x86_64::Registers_x86_64(const void *registers) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +0000284 static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000285 "x86_64 registers do not fit into unw_context_t");
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000286 memcpy(&_registers, registers, sizeof(_registers));
287}
288
289inline Registers_x86_64::Registers_x86_64() {
290 memset(&_registers, 0, sizeof(_registers));
291}
292
293inline bool Registers_x86_64::validRegister(int regNum) const {
294 if (regNum == UNW_REG_IP)
295 return true;
296 if (regNum == UNW_REG_SP)
297 return true;
298 if (regNum < 0)
299 return false;
300 if (regNum > 15)
301 return false;
302 return true;
303}
304
305inline uint64_t Registers_x86_64::getRegister(int regNum) const {
306 switch (regNum) {
307 case UNW_REG_IP:
308 return _registers.__rip;
309 case UNW_REG_SP:
310 return _registers.__rsp;
311 case UNW_X86_64_RAX:
312 return _registers.__rax;
313 case UNW_X86_64_RDX:
314 return _registers.__rdx;
315 case UNW_X86_64_RCX:
316 return _registers.__rcx;
317 case UNW_X86_64_RBX:
318 return _registers.__rbx;
319 case UNW_X86_64_RSI:
320 return _registers.__rsi;
321 case UNW_X86_64_RDI:
322 return _registers.__rdi;
323 case UNW_X86_64_RBP:
324 return _registers.__rbp;
325 case UNW_X86_64_RSP:
326 return _registers.__rsp;
327 case UNW_X86_64_R8:
328 return _registers.__r8;
329 case UNW_X86_64_R9:
330 return _registers.__r9;
331 case UNW_X86_64_R10:
332 return _registers.__r10;
333 case UNW_X86_64_R11:
334 return _registers.__r11;
335 case UNW_X86_64_R12:
336 return _registers.__r12;
337 case UNW_X86_64_R13:
338 return _registers.__r13;
339 case UNW_X86_64_R14:
340 return _registers.__r14;
341 case UNW_X86_64_R15:
342 return _registers.__r15;
343 }
344 _LIBUNWIND_ABORT("unsupported x86_64 register");
345}
346
347inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
348 switch (regNum) {
349 case UNW_REG_IP:
350 _registers.__rip = value;
351 return;
352 case UNW_REG_SP:
353 _registers.__rsp = value;
354 return;
355 case UNW_X86_64_RAX:
356 _registers.__rax = value;
357 return;
358 case UNW_X86_64_RDX:
359 _registers.__rdx = value;
360 return;
361 case UNW_X86_64_RCX:
362 _registers.__rcx = value;
363 return;
364 case UNW_X86_64_RBX:
365 _registers.__rbx = value;
366 return;
367 case UNW_X86_64_RSI:
368 _registers.__rsi = value;
369 return;
370 case UNW_X86_64_RDI:
371 _registers.__rdi = value;
372 return;
373 case UNW_X86_64_RBP:
374 _registers.__rbp = value;
375 return;
376 case UNW_X86_64_RSP:
377 _registers.__rsp = value;
378 return;
379 case UNW_X86_64_R8:
380 _registers.__r8 = value;
381 return;
382 case UNW_X86_64_R9:
383 _registers.__r9 = value;
384 return;
385 case UNW_X86_64_R10:
386 _registers.__r10 = value;
387 return;
388 case UNW_X86_64_R11:
389 _registers.__r11 = value;
390 return;
391 case UNW_X86_64_R12:
392 _registers.__r12 = value;
393 return;
394 case UNW_X86_64_R13:
395 _registers.__r13 = value;
396 return;
397 case UNW_X86_64_R14:
398 _registers.__r14 = value;
399 return;
400 case UNW_X86_64_R15:
401 _registers.__r15 = value;
402 return;
403 }
404 _LIBUNWIND_ABORT("unsupported x86_64 register");
405}
406
407inline const char *Registers_x86_64::getRegisterName(int regNum) {
408 switch (regNum) {
409 case UNW_REG_IP:
410 return "rip";
411 case UNW_REG_SP:
412 return "rsp";
413 case UNW_X86_64_RAX:
414 return "rax";
415 case UNW_X86_64_RDX:
416 return "rdx";
417 case UNW_X86_64_RCX:
418 return "rcx";
419 case UNW_X86_64_RBX:
420 return "rbx";
421 case UNW_X86_64_RSI:
422 return "rsi";
423 case UNW_X86_64_RDI:
424 return "rdi";
425 case UNW_X86_64_RBP:
426 return "rbp";
427 case UNW_X86_64_RSP:
428 return "rsp";
429 case UNW_X86_64_R8:
430 return "r8";
431 case UNW_X86_64_R9:
432 return "r9";
433 case UNW_X86_64_R10:
434 return "r10";
435 case UNW_X86_64_R11:
436 return "r11";
437 case UNW_X86_64_R12:
438 return "r12";
439 case UNW_X86_64_R13:
440 return "r13";
441 case UNW_X86_64_R14:
442 return "r14";
443 case UNW_X86_64_R15:
444 return "r15";
445 default:
446 return "unknown register";
447 }
448}
449
450inline double Registers_x86_64::getFloatRegister(int) const {
451 _LIBUNWIND_ABORT("no x86_64 float registers");
452}
453
454inline void Registers_x86_64::setFloatRegister(int, double) {
455 _LIBUNWIND_ABORT("no x86_64 float registers");
456}
457
458inline v128 Registers_x86_64::getVectorRegister(int) const {
459 _LIBUNWIND_ABORT("no x86_64 vector registers");
460}
461
462inline void Registers_x86_64::setVectorRegister(int, v128) {
463 _LIBUNWIND_ABORT("no x86_64 vector registers");
464}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000465#endif // _LIBUNWIND_TARGET_X86_64
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000466
467
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000468#if defined(_LIBUNWIND_TARGET_PPC)
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000469/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
470/// process.
471class _LIBUNWIND_HIDDEN Registers_ppc {
472public:
473 Registers_ppc();
474 Registers_ppc(const void *registers);
475
476 bool validRegister(int num) const;
477 uint32_t getRegister(int num) const;
478 void setRegister(int num, uint32_t value);
479 bool validFloatRegister(int num) const;
480 double getFloatRegister(int num) const;
481 void setFloatRegister(int num, double value);
482 bool validVectorRegister(int num) const;
483 v128 getVectorRegister(int num) const;
484 void setVectorRegister(int num, v128 value);
485 const char *getRegisterName(int num);
486 void jumpto();
487 static int lastDwarfRegNum() { return 112; }
488
489 uint64_t getSP() const { return _registers.__r1; }
490 void setSP(uint32_t value) { _registers.__r1 = value; }
491 uint64_t getIP() const { return _registers.__srr0; }
492 void setIP(uint32_t value) { _registers.__srr0 = value; }
493
494private:
495 struct ppc_thread_state_t {
496 unsigned int __srr0; /* Instruction address register (PC) */
497 unsigned int __srr1; /* Machine state register (supervisor) */
498 unsigned int __r0;
499 unsigned int __r1;
500 unsigned int __r2;
501 unsigned int __r3;
502 unsigned int __r4;
503 unsigned int __r5;
504 unsigned int __r6;
505 unsigned int __r7;
506 unsigned int __r8;
507 unsigned int __r9;
508 unsigned int __r10;
509 unsigned int __r11;
510 unsigned int __r12;
511 unsigned int __r13;
512 unsigned int __r14;
513 unsigned int __r15;
514 unsigned int __r16;
515 unsigned int __r17;
516 unsigned int __r18;
517 unsigned int __r19;
518 unsigned int __r20;
519 unsigned int __r21;
520 unsigned int __r22;
521 unsigned int __r23;
522 unsigned int __r24;
523 unsigned int __r25;
524 unsigned int __r26;
525 unsigned int __r27;
526 unsigned int __r28;
527 unsigned int __r29;
528 unsigned int __r30;
529 unsigned int __r31;
530 unsigned int __cr; /* Condition register */
531 unsigned int __xer; /* User's integer exception register */
532 unsigned int __lr; /* Link register */
533 unsigned int __ctr; /* Count register */
534 unsigned int __mq; /* MQ register (601 only) */
535 unsigned int __vrsave; /* Vector Save Register */
536 };
537
538 struct ppc_float_state_t {
539 double __fpregs[32];
540
541 unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
542 unsigned int __fpscr; /* floating point status register */
543 };
544
545 ppc_thread_state_t _registers;
546 ppc_float_state_t _floatRegisters;
547 v128 _vectorRegisters[32]; // offset 424
548};
549
550inline Registers_ppc::Registers_ppc(const void *registers) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +0000551 static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000552 "ppc registers do not fit into unw_context_t");
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000553 memcpy(&_registers, static_cast<const uint8_t *>(registers),
554 sizeof(_registers));
555 static_assert(sizeof(ppc_thread_state_t) == 160,
556 "expected float register offset to be 160");
557 memcpy(&_floatRegisters,
558 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
559 sizeof(_floatRegisters));
560 static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
561 "expected vector register offset to be 424 bytes");
562 memcpy(_vectorRegisters,
563 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
564 sizeof(ppc_float_state_t),
565 sizeof(_vectorRegisters));
566}
567
568inline Registers_ppc::Registers_ppc() {
569 memset(&_registers, 0, sizeof(_registers));
570 memset(&_floatRegisters, 0, sizeof(_floatRegisters));
571 memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
572}
573
574inline bool Registers_ppc::validRegister(int regNum) const {
575 if (regNum == UNW_REG_IP)
576 return true;
577 if (regNum == UNW_REG_SP)
578 return true;
579 if (regNum == UNW_PPC_VRSAVE)
580 return true;
581 if (regNum < 0)
582 return false;
583 if (regNum <= UNW_PPC_R31)
584 return true;
585 if (regNum == UNW_PPC_MQ)
586 return true;
587 if (regNum == UNW_PPC_LR)
588 return true;
589 if (regNum == UNW_PPC_CTR)
590 return true;
591 if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
592 return true;
593 return false;
594}
595
596inline uint32_t Registers_ppc::getRegister(int regNum) const {
597 switch (regNum) {
598 case UNW_REG_IP:
599 return _registers.__srr0;
600 case UNW_REG_SP:
601 return _registers.__r1;
602 case UNW_PPC_R0:
603 return _registers.__r0;
604 case UNW_PPC_R1:
605 return _registers.__r1;
606 case UNW_PPC_R2:
607 return _registers.__r2;
608 case UNW_PPC_R3:
609 return _registers.__r3;
610 case UNW_PPC_R4:
611 return _registers.__r4;
612 case UNW_PPC_R5:
613 return _registers.__r5;
614 case UNW_PPC_R6:
615 return _registers.__r6;
616 case UNW_PPC_R7:
617 return _registers.__r7;
618 case UNW_PPC_R8:
619 return _registers.__r8;
620 case UNW_PPC_R9:
621 return _registers.__r9;
622 case UNW_PPC_R10:
623 return _registers.__r10;
624 case UNW_PPC_R11:
625 return _registers.__r11;
626 case UNW_PPC_R12:
627 return _registers.__r12;
628 case UNW_PPC_R13:
629 return _registers.__r13;
630 case UNW_PPC_R14:
631 return _registers.__r14;
632 case UNW_PPC_R15:
633 return _registers.__r15;
634 case UNW_PPC_R16:
635 return _registers.__r16;
636 case UNW_PPC_R17:
637 return _registers.__r17;
638 case UNW_PPC_R18:
639 return _registers.__r18;
640 case UNW_PPC_R19:
641 return _registers.__r19;
642 case UNW_PPC_R20:
643 return _registers.__r20;
644 case UNW_PPC_R21:
645 return _registers.__r21;
646 case UNW_PPC_R22:
647 return _registers.__r22;
648 case UNW_PPC_R23:
649 return _registers.__r23;
650 case UNW_PPC_R24:
651 return _registers.__r24;
652 case UNW_PPC_R25:
653 return _registers.__r25;
654 case UNW_PPC_R26:
655 return _registers.__r26;
656 case UNW_PPC_R27:
657 return _registers.__r27;
658 case UNW_PPC_R28:
659 return _registers.__r28;
660 case UNW_PPC_R29:
661 return _registers.__r29;
662 case UNW_PPC_R30:
663 return _registers.__r30;
664 case UNW_PPC_R31:
665 return _registers.__r31;
666 case UNW_PPC_LR:
667 return _registers.__lr;
668 case UNW_PPC_CR0:
669 return (_registers.__cr & 0xF0000000);
670 case UNW_PPC_CR1:
671 return (_registers.__cr & 0x0F000000);
672 case UNW_PPC_CR2:
673 return (_registers.__cr & 0x00F00000);
674 case UNW_PPC_CR3:
675 return (_registers.__cr & 0x000F0000);
676 case UNW_PPC_CR4:
677 return (_registers.__cr & 0x0000F000);
678 case UNW_PPC_CR5:
679 return (_registers.__cr & 0x00000F00);
680 case UNW_PPC_CR6:
681 return (_registers.__cr & 0x000000F0);
682 case UNW_PPC_CR7:
683 return (_registers.__cr & 0x0000000F);
684 case UNW_PPC_VRSAVE:
685 return _registers.__vrsave;
686 }
687 _LIBUNWIND_ABORT("unsupported ppc register");
688}
689
690inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
691 //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
692 switch (regNum) {
693 case UNW_REG_IP:
694 _registers.__srr0 = value;
695 return;
696 case UNW_REG_SP:
697 _registers.__r1 = value;
698 return;
699 case UNW_PPC_R0:
700 _registers.__r0 = value;
701 return;
702 case UNW_PPC_R1:
703 _registers.__r1 = value;
704 return;
705 case UNW_PPC_R2:
706 _registers.__r2 = value;
707 return;
708 case UNW_PPC_R3:
709 _registers.__r3 = value;
710 return;
711 case UNW_PPC_R4:
712 _registers.__r4 = value;
713 return;
714 case UNW_PPC_R5:
715 _registers.__r5 = value;
716 return;
717 case UNW_PPC_R6:
718 _registers.__r6 = value;
719 return;
720 case UNW_PPC_R7:
721 _registers.__r7 = value;
722 return;
723 case UNW_PPC_R8:
724 _registers.__r8 = value;
725 return;
726 case UNW_PPC_R9:
727 _registers.__r9 = value;
728 return;
729 case UNW_PPC_R10:
730 _registers.__r10 = value;
731 return;
732 case UNW_PPC_R11:
733 _registers.__r11 = value;
734 return;
735 case UNW_PPC_R12:
736 _registers.__r12 = value;
737 return;
738 case UNW_PPC_R13:
739 _registers.__r13 = value;
740 return;
741 case UNW_PPC_R14:
742 _registers.__r14 = value;
743 return;
744 case UNW_PPC_R15:
745 _registers.__r15 = value;
746 return;
747 case UNW_PPC_R16:
748 _registers.__r16 = value;
749 return;
750 case UNW_PPC_R17:
751 _registers.__r17 = value;
752 return;
753 case UNW_PPC_R18:
754 _registers.__r18 = value;
755 return;
756 case UNW_PPC_R19:
757 _registers.__r19 = value;
758 return;
759 case UNW_PPC_R20:
760 _registers.__r20 = value;
761 return;
762 case UNW_PPC_R21:
763 _registers.__r21 = value;
764 return;
765 case UNW_PPC_R22:
766 _registers.__r22 = value;
767 return;
768 case UNW_PPC_R23:
769 _registers.__r23 = value;
770 return;
771 case UNW_PPC_R24:
772 _registers.__r24 = value;
773 return;
774 case UNW_PPC_R25:
775 _registers.__r25 = value;
776 return;
777 case UNW_PPC_R26:
778 _registers.__r26 = value;
779 return;
780 case UNW_PPC_R27:
781 _registers.__r27 = value;
782 return;
783 case UNW_PPC_R28:
784 _registers.__r28 = value;
785 return;
786 case UNW_PPC_R29:
787 _registers.__r29 = value;
788 return;
789 case UNW_PPC_R30:
790 _registers.__r30 = value;
791 return;
792 case UNW_PPC_R31:
793 _registers.__r31 = value;
794 return;
795 case UNW_PPC_MQ:
796 _registers.__mq = value;
797 return;
798 case UNW_PPC_LR:
799 _registers.__lr = value;
800 return;
801 case UNW_PPC_CTR:
802 _registers.__ctr = value;
803 return;
804 case UNW_PPC_CR0:
805 _registers.__cr &= 0x0FFFFFFF;
806 _registers.__cr |= (value & 0xF0000000);
807 return;
808 case UNW_PPC_CR1:
809 _registers.__cr &= 0xF0FFFFFF;
810 _registers.__cr |= (value & 0x0F000000);
811 return;
812 case UNW_PPC_CR2:
813 _registers.__cr &= 0xFF0FFFFF;
814 _registers.__cr |= (value & 0x00F00000);
815 return;
816 case UNW_PPC_CR3:
817 _registers.__cr &= 0xFFF0FFFF;
818 _registers.__cr |= (value & 0x000F0000);
819 return;
820 case UNW_PPC_CR4:
821 _registers.__cr &= 0xFFFF0FFF;
822 _registers.__cr |= (value & 0x0000F000);
823 return;
824 case UNW_PPC_CR5:
825 _registers.__cr &= 0xFFFFF0FF;
826 _registers.__cr |= (value & 0x00000F00);
827 return;
828 case UNW_PPC_CR6:
829 _registers.__cr &= 0xFFFFFF0F;
830 _registers.__cr |= (value & 0x000000F0);
831 return;
832 case UNW_PPC_CR7:
833 _registers.__cr &= 0xFFFFFFF0;
834 _registers.__cr |= (value & 0x0000000F);
835 return;
836 case UNW_PPC_VRSAVE:
837 _registers.__vrsave = value;
838 return;
839 // not saved
840 return;
841 case UNW_PPC_XER:
842 _registers.__xer = value;
843 return;
844 case UNW_PPC_AP:
845 case UNW_PPC_VSCR:
846 case UNW_PPC_SPEFSCR:
847 // not saved
848 return;
849 }
850 _LIBUNWIND_ABORT("unsupported ppc register");
851}
852
853inline bool Registers_ppc::validFloatRegister(int regNum) const {
854 if (regNum < UNW_PPC_F0)
855 return false;
856 if (regNum > UNW_PPC_F31)
857 return false;
858 return true;
859}
860
861inline double Registers_ppc::getFloatRegister(int regNum) const {
862 assert(validFloatRegister(regNum));
863 return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
864}
865
866inline void Registers_ppc::setFloatRegister(int regNum, double value) {
867 assert(validFloatRegister(regNum));
868 _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
869}
870
871inline bool Registers_ppc::validVectorRegister(int regNum) const {
872 if (regNum < UNW_PPC_V0)
873 return false;
874 if (regNum > UNW_PPC_V31)
875 return false;
876 return true;
877}
878
879inline v128 Registers_ppc::getVectorRegister(int regNum) const {
880 assert(validVectorRegister(regNum));
881 v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
882 return result;
883}
884
885inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
886 assert(validVectorRegister(regNum));
887 _vectorRegisters[regNum - UNW_PPC_V0] = value;
888}
889
890inline const char *Registers_ppc::getRegisterName(int regNum) {
891 switch (regNum) {
892 case UNW_REG_IP:
893 return "ip";
894 case UNW_REG_SP:
895 return "sp";
896 case UNW_PPC_R0:
897 return "r0";
898 case UNW_PPC_R1:
899 return "r1";
900 case UNW_PPC_R2:
901 return "r2";
902 case UNW_PPC_R3:
903 return "r3";
904 case UNW_PPC_R4:
905 return "r4";
906 case UNW_PPC_R5:
907 return "r5";
908 case UNW_PPC_R6:
909 return "r6";
910 case UNW_PPC_R7:
911 return "r7";
912 case UNW_PPC_R8:
913 return "r8";
914 case UNW_PPC_R9:
915 return "r9";
916 case UNW_PPC_R10:
917 return "r10";
918 case UNW_PPC_R11:
919 return "r11";
920 case UNW_PPC_R12:
921 return "r12";
922 case UNW_PPC_R13:
923 return "r13";
924 case UNW_PPC_R14:
925 return "r14";
926 case UNW_PPC_R15:
927 return "r15";
928 case UNW_PPC_R16:
929 return "r16";
930 case UNW_PPC_R17:
931 return "r17";
932 case UNW_PPC_R18:
933 return "r18";
934 case UNW_PPC_R19:
935 return "r19";
936 case UNW_PPC_R20:
937 return "r20";
938 case UNW_PPC_R21:
939 return "r21";
940 case UNW_PPC_R22:
941 return "r22";
942 case UNW_PPC_R23:
943 return "r23";
944 case UNW_PPC_R24:
945 return "r24";
946 case UNW_PPC_R25:
947 return "r25";
948 case UNW_PPC_R26:
949 return "r26";
950 case UNW_PPC_R27:
951 return "r27";
952 case UNW_PPC_R28:
953 return "r28";
954 case UNW_PPC_R29:
955 return "r29";
956 case UNW_PPC_R30:
957 return "r30";
958 case UNW_PPC_R31:
959 return "r31";
960 case UNW_PPC_F0:
961 return "fp0";
962 case UNW_PPC_F1:
963 return "fp1";
964 case UNW_PPC_F2:
965 return "fp2";
966 case UNW_PPC_F3:
967 return "fp3";
968 case UNW_PPC_F4:
969 return "fp4";
970 case UNW_PPC_F5:
971 return "fp5";
972 case UNW_PPC_F6:
973 return "fp6";
974 case UNW_PPC_F7:
975 return "fp7";
976 case UNW_PPC_F8:
977 return "fp8";
978 case UNW_PPC_F9:
979 return "fp9";
980 case UNW_PPC_F10:
981 return "fp10";
982 case UNW_PPC_F11:
983 return "fp11";
984 case UNW_PPC_F12:
985 return "fp12";
986 case UNW_PPC_F13:
987 return "fp13";
988 case UNW_PPC_F14:
989 return "fp14";
990 case UNW_PPC_F15:
991 return "fp15";
992 case UNW_PPC_F16:
993 return "fp16";
994 case UNW_PPC_F17:
995 return "fp17";
996 case UNW_PPC_F18:
997 return "fp18";
998 case UNW_PPC_F19:
999 return "fp19";
1000 case UNW_PPC_F20:
1001 return "fp20";
1002 case UNW_PPC_F21:
1003 return "fp21";
1004 case UNW_PPC_F22:
1005 return "fp22";
1006 case UNW_PPC_F23:
1007 return "fp23";
1008 case UNW_PPC_F24:
1009 return "fp24";
1010 case UNW_PPC_F25:
1011 return "fp25";
1012 case UNW_PPC_F26:
1013 return "fp26";
1014 case UNW_PPC_F27:
1015 return "fp27";
1016 case UNW_PPC_F28:
1017 return "fp28";
1018 case UNW_PPC_F29:
1019 return "fp29";
1020 case UNW_PPC_F30:
1021 return "fp30";
1022 case UNW_PPC_F31:
1023 return "fp31";
1024 case UNW_PPC_LR:
1025 return "lr";
1026 default:
1027 return "unknown register";
1028 }
1029
1030}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001031#endif // _LIBUNWIND_TARGET_PPC
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001032
1033
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001034#if defined(_LIBUNWIND_TARGET_AARCH64)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001035/// Registers_arm64 holds the register state of a thread in a 64-bit arm
1036/// process.
1037class _LIBUNWIND_HIDDEN Registers_arm64 {
1038public:
1039 Registers_arm64();
1040 Registers_arm64(const void *registers);
1041
1042 bool validRegister(int num) const;
1043 uint64_t getRegister(int num) const;
1044 void setRegister(int num, uint64_t value);
1045 bool validFloatRegister(int num) const;
1046 double getFloatRegister(int num) const;
1047 void setFloatRegister(int num, double value);
1048 bool validVectorRegister(int num) const;
1049 v128 getVectorRegister(int num) const;
1050 void setVectorRegister(int num, v128 value);
1051 const char *getRegisterName(int num);
1052 void jumpto();
1053 static int lastDwarfRegNum() { return 95; }
1054
1055 uint64_t getSP() const { return _registers.__sp; }
1056 void setSP(uint64_t value) { _registers.__sp = value; }
1057 uint64_t getIP() const { return _registers.__pc; }
1058 void setIP(uint64_t value) { _registers.__pc = value; }
1059 uint64_t getFP() const { return _registers.__fp; }
1060 void setFP(uint64_t value) { _registers.__fp = value; }
1061
1062private:
1063 struct GPRs {
1064 uint64_t __x[29]; // x0-x28
1065 uint64_t __fp; // Frame pointer x29
1066 uint64_t __lr; // Link register x30
1067 uint64_t __sp; // Stack pointer x31
1068 uint64_t __pc; // Program counter
1069 uint64_t padding; // 16-byte align
1070 };
1071
1072 GPRs _registers;
1073 double _vectorHalfRegisters[32];
1074 // Currently only the lower double in 128-bit vectore registers
1075 // is perserved during unwinding. We could define new register
1076 // numbers (> 96) which mean whole vector registers, then this
1077 // struct would need to change to contain whole vector registers.
1078};
1079
1080inline Registers_arm64::Registers_arm64(const void *registers) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +00001081 static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001082 "arm64 registers do not fit into unw_context_t");
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001083 memcpy(&_registers, registers, sizeof(_registers));
1084 static_assert(sizeof(GPRs) == 0x110,
1085 "expected VFP registers to be at offset 272");
1086 memcpy(_vectorHalfRegisters,
1087 static_cast<const uint8_t *>(registers) + sizeof(GPRs),
1088 sizeof(_vectorHalfRegisters));
1089}
1090
1091inline Registers_arm64::Registers_arm64() {
1092 memset(&_registers, 0, sizeof(_registers));
1093 memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
1094}
1095
1096inline bool Registers_arm64::validRegister(int regNum) const {
1097 if (regNum == UNW_REG_IP)
1098 return true;
1099 if (regNum == UNW_REG_SP)
1100 return true;
1101 if (regNum < 0)
1102 return false;
1103 if (regNum > 95)
1104 return false;
1105 if ((regNum > 31) && (regNum < 64))
1106 return false;
1107 return true;
1108}
1109
1110inline uint64_t Registers_arm64::getRegister(int regNum) const {
1111 if (regNum == UNW_REG_IP)
1112 return _registers.__pc;
1113 if (regNum == UNW_REG_SP)
1114 return _registers.__sp;
1115 if ((regNum >= 0) && (regNum < 32))
1116 return _registers.__x[regNum];
1117 _LIBUNWIND_ABORT("unsupported arm64 register");
1118}
1119
1120inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1121 if (regNum == UNW_REG_IP)
1122 _registers.__pc = value;
1123 else if (regNum == UNW_REG_SP)
1124 _registers.__sp = value;
1125 else if ((regNum >= 0) && (regNum < 32))
1126 _registers.__x[regNum] = value;
1127 else
1128 _LIBUNWIND_ABORT("unsupported arm64 register");
1129}
1130
1131inline const char *Registers_arm64::getRegisterName(int regNum) {
1132 switch (regNum) {
1133 case UNW_REG_IP:
1134 return "pc";
1135 case UNW_REG_SP:
1136 return "sp";
1137 case UNW_ARM64_X0:
1138 return "x0";
1139 case UNW_ARM64_X1:
1140 return "x1";
1141 case UNW_ARM64_X2:
1142 return "x2";
1143 case UNW_ARM64_X3:
1144 return "x3";
1145 case UNW_ARM64_X4:
1146 return "x4";
1147 case UNW_ARM64_X5:
1148 return "x5";
1149 case UNW_ARM64_X6:
1150 return "x6";
1151 case UNW_ARM64_X7:
1152 return "x7";
1153 case UNW_ARM64_X8:
1154 return "x8";
1155 case UNW_ARM64_X9:
1156 return "x9";
1157 case UNW_ARM64_X10:
1158 return "x10";
1159 case UNW_ARM64_X11:
1160 return "x11";
1161 case UNW_ARM64_X12:
1162 return "x12";
1163 case UNW_ARM64_X13:
1164 return "x13";
1165 case UNW_ARM64_X14:
1166 return "x14";
1167 case UNW_ARM64_X15:
1168 return "x15";
1169 case UNW_ARM64_X16:
1170 return "x16";
1171 case UNW_ARM64_X17:
1172 return "x17";
1173 case UNW_ARM64_X18:
1174 return "x18";
1175 case UNW_ARM64_X19:
1176 return "x19";
1177 case UNW_ARM64_X20:
1178 return "x20";
1179 case UNW_ARM64_X21:
1180 return "x21";
1181 case UNW_ARM64_X22:
1182 return "x22";
1183 case UNW_ARM64_X23:
1184 return "x23";
1185 case UNW_ARM64_X24:
1186 return "x24";
1187 case UNW_ARM64_X25:
1188 return "x25";
1189 case UNW_ARM64_X26:
1190 return "x26";
1191 case UNW_ARM64_X27:
1192 return "x27";
1193 case UNW_ARM64_X28:
1194 return "x28";
1195 case UNW_ARM64_X29:
1196 return "fp";
1197 case UNW_ARM64_X30:
1198 return "lr";
1199 case UNW_ARM64_X31:
1200 return "sp";
1201 case UNW_ARM64_D0:
1202 return "d0";
1203 case UNW_ARM64_D1:
1204 return "d1";
1205 case UNW_ARM64_D2:
1206 return "d2";
1207 case UNW_ARM64_D3:
1208 return "d3";
1209 case UNW_ARM64_D4:
1210 return "d4";
1211 case UNW_ARM64_D5:
1212 return "d5";
1213 case UNW_ARM64_D6:
1214 return "d6";
1215 case UNW_ARM64_D7:
1216 return "d7";
1217 case UNW_ARM64_D8:
1218 return "d8";
1219 case UNW_ARM64_D9:
1220 return "d9";
1221 case UNW_ARM64_D10:
1222 return "d10";
1223 case UNW_ARM64_D11:
1224 return "d11";
1225 case UNW_ARM64_D12:
1226 return "d12";
1227 case UNW_ARM64_D13:
1228 return "d13";
1229 case UNW_ARM64_D14:
1230 return "d14";
1231 case UNW_ARM64_D15:
1232 return "d15";
1233 case UNW_ARM64_D16:
1234 return "d16";
1235 case UNW_ARM64_D17:
1236 return "d17";
1237 case UNW_ARM64_D18:
1238 return "d18";
1239 case UNW_ARM64_D19:
1240 return "d19";
1241 case UNW_ARM64_D20:
1242 return "d20";
1243 case UNW_ARM64_D21:
1244 return "d21";
1245 case UNW_ARM64_D22:
1246 return "d22";
1247 case UNW_ARM64_D23:
1248 return "d23";
1249 case UNW_ARM64_D24:
1250 return "d24";
1251 case UNW_ARM64_D25:
1252 return "d25";
1253 case UNW_ARM64_D26:
1254 return "d26";
1255 case UNW_ARM64_D27:
1256 return "d27";
1257 case UNW_ARM64_D28:
1258 return "d28";
1259 case UNW_ARM64_D29:
1260 return "d29";
1261 case UNW_ARM64_D30:
1262 return "d30";
1263 case UNW_ARM64_D31:
1264 return "d31";
1265 default:
1266 return "unknown register";
1267 }
1268}
1269
1270inline bool Registers_arm64::validFloatRegister(int regNum) const {
1271 if (regNum < UNW_ARM64_D0)
1272 return false;
1273 if (regNum > UNW_ARM64_D31)
1274 return false;
1275 return true;
1276}
1277
1278inline double Registers_arm64::getFloatRegister(int regNum) const {
1279 assert(validFloatRegister(regNum));
1280 return _vectorHalfRegisters[regNum - UNW_ARM64_D0];
1281}
1282
1283inline void Registers_arm64::setFloatRegister(int regNum, double value) {
1284 assert(validFloatRegister(regNum));
1285 _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value;
1286}
1287
1288inline bool Registers_arm64::validVectorRegister(int) const {
1289 return false;
1290}
1291
1292inline v128 Registers_arm64::getVectorRegister(int) const {
1293 _LIBUNWIND_ABORT("no arm64 vector register support yet");
1294}
1295
1296inline void Registers_arm64::setVectorRegister(int, v128) {
1297 _LIBUNWIND_ABORT("no arm64 vector register support yet");
1298}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001299#endif // _LIBUNWIND_TARGET_AARCH64
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001300
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001301#if defined(_LIBUNWIND_TARGET_ARM)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001302/// Registers_arm holds the register state of a thread in a 32-bit arm
1303/// process.
1304///
1305/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
1306/// this uses more memory than required.
1307class _LIBUNWIND_HIDDEN Registers_arm {
1308public:
1309 Registers_arm();
1310 Registers_arm(const void *registers);
1311
1312 bool validRegister(int num) const;
1313 uint32_t getRegister(int num);
1314 void setRegister(int num, uint32_t value);
1315 bool validFloatRegister(int num) const;
1316 unw_fpreg_t getFloatRegister(int num);
1317 void setFloatRegister(int num, unw_fpreg_t value);
1318 bool validVectorRegister(int num) const;
1319 v128 getVectorRegister(int num) const;
1320 void setVectorRegister(int num, v128 value);
1321 const char *getRegisterName(int num);
1322 void jumpto() {
1323 restoreSavedFloatRegisters();
1324 restoreCoreAndJumpTo();
1325 }
1326
1327 uint32_t getSP() const { return _registers.__sp; }
1328 void setSP(uint32_t value) { _registers.__sp = value; }
1329 uint32_t getIP() const { return _registers.__pc; }
1330 void setIP(uint32_t value) { _registers.__pc = value; }
1331
1332 void saveVFPAsX() {
1333 assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
1334 _use_X_for_vfp_save = true;
1335 }
1336
1337 void restoreSavedFloatRegisters() {
1338 if (_saved_vfp_d0_d15) {
1339 if (_use_X_for_vfp_save)
1340 restoreVFPWithFLDMX(_vfp_d0_d15_pad);
1341 else
1342 restoreVFPWithFLDMD(_vfp_d0_d15_pad);
1343 }
1344 if (_saved_vfp_d16_d31)
1345 restoreVFPv3(_vfp_d16_d31);
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001346#if defined(__ARM_WMMX)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001347 if (_saved_iwmmx)
1348 restoreiWMMX(_iwmmx);
1349 if (_saved_iwmmx_control)
1350 restoreiWMMXControl(_iwmmx_control);
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001351#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001352 }
1353
1354private:
1355 struct GPRs {
1356 uint32_t __r[13]; // r0-r12
1357 uint32_t __sp; // Stack pointer r13
1358 uint32_t __lr; // Link register r14
1359 uint32_t __pc; // Program counter r15
1360 };
1361
1362 static void saveVFPWithFSTMD(unw_fpreg_t*);
1363 static void saveVFPWithFSTMX(unw_fpreg_t*);
1364 static void saveVFPv3(unw_fpreg_t*);
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001365 static void restoreVFPWithFLDMD(unw_fpreg_t*);
1366 static void restoreVFPWithFLDMX(unw_fpreg_t*);
1367 static void restoreVFPv3(unw_fpreg_t*);
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001368#if defined(__ARM_WMMX)
1369 static void saveiWMMX(unw_fpreg_t*);
1370 static void saveiWMMXControl(uint32_t*);
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001371 static void restoreiWMMX(unw_fpreg_t*);
1372 static void restoreiWMMXControl(uint32_t*);
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001373#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001374 void restoreCoreAndJumpTo();
1375
1376 // ARM registers
1377 GPRs _registers;
1378
1379 // We save floating point registers lazily because we can't know ahead of
1380 // time which ones are used. See EHABI #4.7.
1381
1382 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
1383 //
1384 // See EHABI #7.5 that explains how matching instruction sequences for load
1385 // and store need to be used to correctly restore the exact register bits.
1386 bool _use_X_for_vfp_save;
1387 // Whether VFP D0-D15 are saved.
1388 bool _saved_vfp_d0_d15;
1389 // Whether VFPv3 D16-D31 are saved.
1390 bool _saved_vfp_d16_d31;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001391 // VFP registers D0-D15, + padding if saved using FSTMX
1392 unw_fpreg_t _vfp_d0_d15_pad[17];
1393 // VFPv3 registers D16-D31, always saved using FSTMD
1394 unw_fpreg_t _vfp_d16_d31[16];
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001395#if defined(__ARM_WMMX)
1396 // Whether iWMMX data registers are saved.
1397 bool _saved_iwmmx;
1398 // Whether iWMMX control registers are saved.
1399 bool _saved_iwmmx_control;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001400 // iWMMX registers
1401 unw_fpreg_t _iwmmx[16];
1402 // iWMMX control registers
1403 uint32_t _iwmmx_control[4];
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001404#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001405};
1406
1407inline Registers_arm::Registers_arm(const void *registers)
1408 : _use_X_for_vfp_save(false),
1409 _saved_vfp_d0_d15(false),
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001410 _saved_vfp_d16_d31(false) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +00001411 static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001412 "arm registers do not fit into unw_context_t");
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001413 // See unw_getcontext() note about data.
1414 memcpy(&_registers, registers, sizeof(_registers));
1415 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
1416 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001417#if defined(__ARM_WMMX)
1418 _saved_iwmmx = false;
1419 _saved_iwmmx_control = false;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001420 memset(&_iwmmx, 0, sizeof(_iwmmx));
1421 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001422#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001423}
1424
1425inline Registers_arm::Registers_arm()
1426 : _use_X_for_vfp_save(false),
1427 _saved_vfp_d0_d15(false),
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001428 _saved_vfp_d16_d31(false) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001429 memset(&_registers, 0, sizeof(_registers));
1430 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
1431 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001432#if defined(__ARM_WMMX)
1433 _saved_iwmmx = false;
1434 _saved_iwmmx_control = false;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001435 memset(&_iwmmx, 0, sizeof(_iwmmx));
1436 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001437#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001438}
1439
1440inline bool Registers_arm::validRegister(int regNum) const {
1441 // Returns true for all non-VFP registers supported by the EHABI
1442 // virtual register set (VRS).
1443 if (regNum == UNW_REG_IP)
1444 return true;
1445 if (regNum == UNW_REG_SP)
1446 return true;
1447 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
1448 return true;
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001449#if defined(__ARM_WMMX)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001450 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
1451 return true;
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001452#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001453 return false;
1454}
1455
1456inline uint32_t Registers_arm::getRegister(int regNum) {
1457 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
1458 return _registers.__sp;
1459 if (regNum == UNW_ARM_LR)
1460 return _registers.__lr;
1461 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
1462 return _registers.__pc;
1463 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
1464 return _registers.__r[regNum];
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001465#if defined(__ARM_WMMX)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001466 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
1467 if (!_saved_iwmmx_control) {
1468 _saved_iwmmx_control = true;
1469 saveiWMMXControl(_iwmmx_control);
1470 }
1471 return _iwmmx_control[regNum - UNW_ARM_WC0];
1472 }
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001473#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001474 _LIBUNWIND_ABORT("unsupported arm register");
1475}
1476
1477inline void Registers_arm::setRegister(int regNum, uint32_t value) {
1478 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
1479 _registers.__sp = value;
1480 else if (regNum == UNW_ARM_LR)
1481 _registers.__lr = value;
1482 else if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
1483 _registers.__pc = value;
1484 else if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
1485 _registers.__r[regNum] = value;
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001486#if defined(__ARM_WMMX)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001487 else if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
1488 if (!_saved_iwmmx_control) {
1489 _saved_iwmmx_control = true;
1490 saveiWMMXControl(_iwmmx_control);
1491 }
1492 _iwmmx_control[regNum - UNW_ARM_WC0] = value;
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001493 }
1494#endif
1495 else
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001496 _LIBUNWIND_ABORT("unsupported arm register");
1497}
1498
1499inline const char *Registers_arm::getRegisterName(int regNum) {
1500 switch (regNum) {
1501 case UNW_REG_IP:
1502 case UNW_ARM_IP: // UNW_ARM_R15 is alias
1503 return "pc";
1504 case UNW_ARM_LR: // UNW_ARM_R14 is alias
1505 return "lr";
1506 case UNW_REG_SP:
1507 case UNW_ARM_SP: // UNW_ARM_R13 is alias
1508 return "sp";
1509 case UNW_ARM_R0:
1510 return "r0";
1511 case UNW_ARM_R1:
1512 return "r1";
1513 case UNW_ARM_R2:
1514 return "r2";
1515 case UNW_ARM_R3:
1516 return "r3";
1517 case UNW_ARM_R4:
1518 return "r4";
1519 case UNW_ARM_R5:
1520 return "r5";
1521 case UNW_ARM_R6:
1522 return "r6";
1523 case UNW_ARM_R7:
1524 return "r7";
1525 case UNW_ARM_R8:
1526 return "r8";
1527 case UNW_ARM_R9:
1528 return "r9";
1529 case UNW_ARM_R10:
1530 return "r10";
1531 case UNW_ARM_R11:
1532 return "r11";
1533 case UNW_ARM_R12:
1534 return "r12";
1535 case UNW_ARM_S0:
1536 return "s0";
1537 case UNW_ARM_S1:
1538 return "s1";
1539 case UNW_ARM_S2:
1540 return "s2";
1541 case UNW_ARM_S3:
1542 return "s3";
1543 case UNW_ARM_S4:
1544 return "s4";
1545 case UNW_ARM_S5:
1546 return "s5";
1547 case UNW_ARM_S6:
1548 return "s6";
1549 case UNW_ARM_S7:
1550 return "s7";
1551 case UNW_ARM_S8:
1552 return "s8";
1553 case UNW_ARM_S9:
1554 return "s9";
1555 case UNW_ARM_S10:
1556 return "s10";
1557 case UNW_ARM_S11:
1558 return "s11";
1559 case UNW_ARM_S12:
1560 return "s12";
1561 case UNW_ARM_S13:
1562 return "s13";
1563 case UNW_ARM_S14:
1564 return "s14";
1565 case UNW_ARM_S15:
1566 return "s15";
1567 case UNW_ARM_S16:
1568 return "s16";
1569 case UNW_ARM_S17:
1570 return "s17";
1571 case UNW_ARM_S18:
1572 return "s18";
1573 case UNW_ARM_S19:
1574 return "s19";
1575 case UNW_ARM_S20:
1576 return "s20";
1577 case UNW_ARM_S21:
1578 return "s21";
1579 case UNW_ARM_S22:
1580 return "s22";
1581 case UNW_ARM_S23:
1582 return "s23";
1583 case UNW_ARM_S24:
1584 return "s24";
1585 case UNW_ARM_S25:
1586 return "s25";
1587 case UNW_ARM_S26:
1588 return "s26";
1589 case UNW_ARM_S27:
1590 return "s27";
1591 case UNW_ARM_S28:
1592 return "s28";
1593 case UNW_ARM_S29:
1594 return "s29";
1595 case UNW_ARM_S30:
1596 return "s30";
1597 case UNW_ARM_S31:
1598 return "s31";
1599 case UNW_ARM_D0:
1600 return "d0";
1601 case UNW_ARM_D1:
1602 return "d1";
1603 case UNW_ARM_D2:
1604 return "d2";
1605 case UNW_ARM_D3:
1606 return "d3";
1607 case UNW_ARM_D4:
1608 return "d4";
1609 case UNW_ARM_D5:
1610 return "d5";
1611 case UNW_ARM_D6:
1612 return "d6";
1613 case UNW_ARM_D7:
1614 return "d7";
1615 case UNW_ARM_D8:
1616 return "d8";
1617 case UNW_ARM_D9:
1618 return "d9";
1619 case UNW_ARM_D10:
1620 return "d10";
1621 case UNW_ARM_D11:
1622 return "d11";
1623 case UNW_ARM_D12:
1624 return "d12";
1625 case UNW_ARM_D13:
1626 return "d13";
1627 case UNW_ARM_D14:
1628 return "d14";
1629 case UNW_ARM_D15:
1630 return "d15";
1631 case UNW_ARM_D16:
1632 return "d16";
1633 case UNW_ARM_D17:
1634 return "d17";
1635 case UNW_ARM_D18:
1636 return "d18";
1637 case UNW_ARM_D19:
1638 return "d19";
1639 case UNW_ARM_D20:
1640 return "d20";
1641 case UNW_ARM_D21:
1642 return "d21";
1643 case UNW_ARM_D22:
1644 return "d22";
1645 case UNW_ARM_D23:
1646 return "d23";
1647 case UNW_ARM_D24:
1648 return "d24";
1649 case UNW_ARM_D25:
1650 return "d25";
1651 case UNW_ARM_D26:
1652 return "d26";
1653 case UNW_ARM_D27:
1654 return "d27";
1655 case UNW_ARM_D28:
1656 return "d28";
1657 case UNW_ARM_D29:
1658 return "d29";
1659 case UNW_ARM_D30:
1660 return "d30";
1661 case UNW_ARM_D31:
1662 return "d31";
1663 default:
1664 return "unknown register";
1665 }
1666}
1667
1668inline bool Registers_arm::validFloatRegister(int regNum) const {
1669 // NOTE: Consider the intel MMX registers floating points so the
1670 // unw_get_fpreg can be used to transmit the 64-bit data back.
1671 return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001672#if defined(__ARM_WMMX)
1673 || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
1674#endif
1675 ;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001676}
1677
1678inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
1679 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
1680 if (!_saved_vfp_d0_d15) {
1681 _saved_vfp_d0_d15 = true;
1682 if (_use_X_for_vfp_save)
1683 saveVFPWithFSTMX(_vfp_d0_d15_pad);
1684 else
1685 saveVFPWithFSTMD(_vfp_d0_d15_pad);
1686 }
1687 return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
1688 } else if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
1689 if (!_saved_vfp_d16_d31) {
1690 _saved_vfp_d16_d31 = true;
1691 saveVFPv3(_vfp_d16_d31);
1692 }
1693 return _vfp_d16_d31[regNum - UNW_ARM_D16];
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001694 }
1695#if defined(__ARM_WMMX)
1696 else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001697 if (!_saved_iwmmx) {
1698 _saved_iwmmx = true;
1699 saveiWMMX(_iwmmx);
1700 }
1701 return _iwmmx[regNum - UNW_ARM_WR0];
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001702 }
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001703#endif
1704 else
1705 _LIBUNWIND_ABORT("Unknown ARM float register");
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001706}
1707
1708inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
1709 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
1710 if (!_saved_vfp_d0_d15) {
1711 _saved_vfp_d0_d15 = true;
1712 if (_use_X_for_vfp_save)
1713 saveVFPWithFSTMX(_vfp_d0_d15_pad);
1714 else
1715 saveVFPWithFSTMD(_vfp_d0_d15_pad);
1716 }
1717 _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
1718 } else if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
1719 if (!_saved_vfp_d16_d31) {
1720 _saved_vfp_d16_d31 = true;
1721 saveVFPv3(_vfp_d16_d31);
1722 }
Saleem Abdulrasool7a61b662015-08-21 03:21:31 +00001723 _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001724 }
1725#if defined(__ARM_WMMX)
1726 else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001727 if (!_saved_iwmmx) {
1728 _saved_iwmmx = true;
1729 saveiWMMX(_iwmmx);
1730 }
1731 _iwmmx[regNum - UNW_ARM_WR0] = value;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001732 }
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001733#endif
1734 else
1735 _LIBUNWIND_ABORT("Unknown ARM float register");
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001736}
1737
1738inline bool Registers_arm::validVectorRegister(int) const {
1739 return false;
1740}
1741
1742inline v128 Registers_arm::getVectorRegister(int) const {
1743 _LIBUNWIND_ABORT("ARM vector support not implemented");
1744}
1745
1746inline void Registers_arm::setVectorRegister(int, v128) {
1747 _LIBUNWIND_ABORT("ARM vector support not implemented");
1748}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001749#endif // _LIBUNWIND_TARGET_ARM
1750
1751
1752#if defined(_LIBUNWIND_TARGET_OR1K)
Peter Zotovd4255ab2015-08-31 05:26:37 +00001753/// Registers_or1k holds the register state of a thread in an OpenRISC1000
1754/// process.
1755class _LIBUNWIND_HIDDEN Registers_or1k {
1756public:
1757 Registers_or1k();
1758 Registers_or1k(const void *registers);
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001759
Peter Zotovd4255ab2015-08-31 05:26:37 +00001760 bool validRegister(int num) const;
1761 uint32_t getRegister(int num) const;
1762 void setRegister(int num, uint32_t value);
1763 bool validFloatRegister(int num) const;
1764 double getFloatRegister(int num) const;
1765 void setFloatRegister(int num, double value);
1766 bool validVectorRegister(int num) const;
1767 v128 getVectorRegister(int num) const;
1768 void setVectorRegister(int num, v128 value);
1769 const char *getRegisterName(int num);
1770 void jumpto();
1771 static int lastDwarfRegNum() { return 31; }
1772
1773 uint64_t getSP() const { return _registers.__r[1]; }
1774 void setSP(uint32_t value) { _registers.__r[1] = value; }
1775 uint64_t getIP() const { return _registers.__r[9]; }
1776 void setIP(uint32_t value) { _registers.__r[9] = value; }
1777
1778private:
1779 struct or1k_thread_state_t {
1780 unsigned int __r[32];
1781 };
1782
1783 or1k_thread_state_t _registers;
1784};
1785
1786inline Registers_or1k::Registers_or1k(const void *registers) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +00001787 static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001788 "or1k registers do not fit into unw_context_t");
Peter Zotovd4255ab2015-08-31 05:26:37 +00001789 memcpy(&_registers, static_cast<const uint8_t *>(registers),
1790 sizeof(_registers));
1791}
1792
1793inline Registers_or1k::Registers_or1k() {
1794 memset(&_registers, 0, sizeof(_registers));
1795}
1796
1797inline bool Registers_or1k::validRegister(int regNum) const {
1798 if (regNum == UNW_REG_IP)
1799 return true;
1800 if (regNum == UNW_REG_SP)
1801 return true;
1802 if (regNum < 0)
1803 return false;
1804 if (regNum <= UNW_OR1K_R31)
1805 return true;
1806 return false;
1807}
1808
1809inline uint32_t Registers_or1k::getRegister(int regNum) const {
1810 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
1811 return _registers.__r[regNum - UNW_OR1K_R0];
1812
1813 switch (regNum) {
1814 case UNW_REG_IP:
1815 return _registers.__r[9];
1816 case UNW_REG_SP:
1817 return _registers.__r[1];
1818 }
1819 _LIBUNWIND_ABORT("unsupported or1k register");
1820}
1821
1822inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
1823 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
1824 _registers.__r[regNum - UNW_OR1K_R0] = value;
1825 return;
1826 }
1827
1828 switch (regNum) {
1829 case UNW_REG_IP:
1830 _registers.__r[9] = value;
1831 return;
1832 case UNW_REG_SP:
1833 _registers.__r[1] = value;
1834 return;
1835 }
1836 _LIBUNWIND_ABORT("unsupported or1k register");
1837}
1838
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001839inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001840 return false;
1841}
1842
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001843inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001844 _LIBUNWIND_ABORT("or1k float support not implemented");
1845}
1846
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001847inline void Registers_or1k::setFloatRegister(int /* regNum */,
1848 double /* value */) {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001849 _LIBUNWIND_ABORT("or1k float support not implemented");
1850}
1851
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001852inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001853 return false;
1854}
1855
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001856inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001857 _LIBUNWIND_ABORT("or1k vector support not implemented");
1858}
1859
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001860inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001861 _LIBUNWIND_ABORT("or1k vector support not implemented");
1862}
1863
1864inline const char *Registers_or1k::getRegisterName(int regNum) {
1865 switch (regNum) {
1866 case UNW_OR1K_R0:
1867 return "r0";
1868 case UNW_OR1K_R1:
1869 return "r1";
1870 case UNW_OR1K_R2:
1871 return "r2";
1872 case UNW_OR1K_R3:
1873 return "r3";
1874 case UNW_OR1K_R4:
1875 return "r4";
1876 case UNW_OR1K_R5:
1877 return "r5";
1878 case UNW_OR1K_R6:
1879 return "r6";
1880 case UNW_OR1K_R7:
1881 return "r7";
1882 case UNW_OR1K_R8:
1883 return "r8";
1884 case UNW_OR1K_R9:
1885 return "r9";
1886 case UNW_OR1K_R10:
1887 return "r10";
1888 case UNW_OR1K_R11:
1889 return "r11";
1890 case UNW_OR1K_R12:
1891 return "r12";
1892 case UNW_OR1K_R13:
1893 return "r13";
1894 case UNW_OR1K_R14:
1895 return "r14";
1896 case UNW_OR1K_R15:
1897 return "r15";
1898 case UNW_OR1K_R16:
1899 return "r16";
1900 case UNW_OR1K_R17:
1901 return "r17";
1902 case UNW_OR1K_R18:
1903 return "r18";
1904 case UNW_OR1K_R19:
1905 return "r19";
1906 case UNW_OR1K_R20:
1907 return "r20";
1908 case UNW_OR1K_R21:
1909 return "r21";
1910 case UNW_OR1K_R22:
1911 return "r22";
1912 case UNW_OR1K_R23:
1913 return "r23";
1914 case UNW_OR1K_R24:
1915 return "r24";
1916 case UNW_OR1K_R25:
1917 return "r25";
1918 case UNW_OR1K_R26:
1919 return "r26";
1920 case UNW_OR1K_R27:
1921 return "r27";
1922 case UNW_OR1K_R28:
1923 return "r28";
1924 case UNW_OR1K_R29:
1925 return "r29";
1926 case UNW_OR1K_R30:
1927 return "r30";
1928 case UNW_OR1K_R31:
1929 return "r31";
1930 default:
1931 return "unknown register";
1932 }
1933
1934}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001935#endif // _LIBUNWIND_TARGET_OR1K
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001936} // namespace libunwind
1937
1938#endif // __REGISTERS_HPP__