blob: d881e200782ea94a0e104def3cbc21d4d9876611 [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();
Martin Storsjo7c4a46a2017-10-28 20:19:49 +000047 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }
Saleem Abdulrasool675df582015-04-24 19:39:17 +000048
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;
Saleem Abdulrasoolaa805e42017-01-21 16:22:59 +0000125#if !defined(__APPLE__)
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000126 case UNW_X86_ESP:
Saleem Abdulrasoolaa805e42017-01-21 16:22:59 +0000127#else
128 case UNW_X86_EBP:
129#endif
130 return _registers.__ebp;
131#if !defined(__APPLE__)
132 case UNW_X86_EBP:
133#else
134 case UNW_X86_ESP:
135#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000136 return _registers.__esp;
137 case UNW_X86_ESI:
138 return _registers.__esi;
139 case UNW_X86_EDI:
140 return _registers.__edi;
141 }
142 _LIBUNWIND_ABORT("unsupported x86 register");
143}
144
145inline void Registers_x86::setRegister(int regNum, uint32_t value) {
146 switch (regNum) {
147 case UNW_REG_IP:
148 _registers.__eip = value;
149 return;
150 case UNW_REG_SP:
151 _registers.__esp = value;
152 return;
153 case UNW_X86_EAX:
154 _registers.__eax = value;
155 return;
156 case UNW_X86_ECX:
157 _registers.__ecx = value;
158 return;
159 case UNW_X86_EDX:
160 _registers.__edx = value;
161 return;
162 case UNW_X86_EBX:
163 _registers.__ebx = value;
164 return;
Saleem Abdulrasoolaa805e42017-01-21 16:22:59 +0000165#if !defined(__APPLE__)
166 case UNW_X86_ESP:
167#else
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000168 case UNW_X86_EBP:
Saleem Abdulrasoolaa805e42017-01-21 16:22:59 +0000169#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000170 _registers.__ebp = value;
171 return;
Saleem Abdulrasoolaa805e42017-01-21 16:22:59 +0000172#if !defined(__APPLE__)
173 case UNW_X86_EBP:
174#else
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000175 case UNW_X86_ESP:
Saleem Abdulrasoolaa805e42017-01-21 16:22:59 +0000176#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000177 _registers.__esp = value;
178 return;
179 case UNW_X86_ESI:
180 _registers.__esi = value;
181 return;
182 case UNW_X86_EDI:
183 _registers.__edi = value;
184 return;
185 }
186 _LIBUNWIND_ABORT("unsupported x86 register");
187}
188
189inline const char *Registers_x86::getRegisterName(int regNum) {
190 switch (regNum) {
191 case UNW_REG_IP:
192 return "ip";
193 case UNW_REG_SP:
194 return "esp";
195 case UNW_X86_EAX:
196 return "eax";
197 case UNW_X86_ECX:
198 return "ecx";
199 case UNW_X86_EDX:
200 return "edx";
201 case UNW_X86_EBX:
202 return "ebx";
203 case UNW_X86_EBP:
204 return "ebp";
205 case UNW_X86_ESP:
206 return "esp";
207 case UNW_X86_ESI:
208 return "esi";
209 case UNW_X86_EDI:
210 return "edi";
211 default:
212 return "unknown register";
213 }
214}
215
216inline double Registers_x86::getFloatRegister(int) const {
217 _LIBUNWIND_ABORT("no x86 float registers");
218}
219
220inline void Registers_x86::setFloatRegister(int, double) {
221 _LIBUNWIND_ABORT("no x86 float registers");
222}
223
224inline v128 Registers_x86::getVectorRegister(int) const {
225 _LIBUNWIND_ABORT("no x86 vector registers");
226}
227
228inline void Registers_x86::setVectorRegister(int, v128) {
229 _LIBUNWIND_ABORT("no x86 vector registers");
230}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000231#endif // _LIBUNWIND_TARGET_I386
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000232
233
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000234#if defined(_LIBUNWIND_TARGET_X86_64)
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000235/// Registers_x86_64 holds the register state of a thread in a 64-bit intel
236/// process.
237class _LIBUNWIND_HIDDEN Registers_x86_64 {
238public:
239 Registers_x86_64();
240 Registers_x86_64(const void *registers);
241
242 bool validRegister(int num) const;
243 uint64_t getRegister(int num) const;
244 void setRegister(int num, uint64_t value);
245 bool validFloatRegister(int) const { return false; }
246 double getFloatRegister(int num) const;
247 void setFloatRegister(int num, double value);
Martin Storsjo86e02182017-10-27 08:11:36 +0000248 bool validVectorRegister(int) const;
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000249 v128 getVectorRegister(int num) const;
250 void setVectorRegister(int num, v128 value);
251 const char *getRegisterName(int num);
252 void jumpto();
Martin Storsjo7c4a46a2017-10-28 20:19:49 +0000253 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000254
255 uint64_t getSP() const { return _registers.__rsp; }
256 void setSP(uint64_t value) { _registers.__rsp = value; }
257 uint64_t getIP() const { return _registers.__rip; }
258 void setIP(uint64_t value) { _registers.__rip = value; }
259 uint64_t getRBP() const { return _registers.__rbp; }
260 void setRBP(uint64_t value) { _registers.__rbp = value; }
261 uint64_t getRBX() const { return _registers.__rbx; }
262 void setRBX(uint64_t value) { _registers.__rbx = value; }
263 uint64_t getR12() const { return _registers.__r12; }
264 void setR12(uint64_t value) { _registers.__r12 = value; }
265 uint64_t getR13() const { return _registers.__r13; }
266 void setR13(uint64_t value) { _registers.__r13 = value; }
267 uint64_t getR14() const { return _registers.__r14; }
268 void setR14(uint64_t value) { _registers.__r14 = value; }
269 uint64_t getR15() const { return _registers.__r15; }
270 void setR15(uint64_t value) { _registers.__r15 = value; }
271
272private:
273 struct GPRs {
274 uint64_t __rax;
275 uint64_t __rbx;
276 uint64_t __rcx;
277 uint64_t __rdx;
278 uint64_t __rdi;
279 uint64_t __rsi;
280 uint64_t __rbp;
281 uint64_t __rsp;
282 uint64_t __r8;
283 uint64_t __r9;
284 uint64_t __r10;
285 uint64_t __r11;
286 uint64_t __r12;
287 uint64_t __r13;
288 uint64_t __r14;
289 uint64_t __r15;
290 uint64_t __rip;
291 uint64_t __rflags;
292 uint64_t __cs;
293 uint64_t __fs;
294 uint64_t __gs;
Martin Storsjo86e02182017-10-27 08:11:36 +0000295#if defined(_WIN64)
296 uint64_t __padding; // 16-byte align
297#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000298 };
299 GPRs _registers;
Martin Storsjo86e02182017-10-27 08:11:36 +0000300#if defined(_WIN64)
301 v128 _xmm[16];
302#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000303};
304
305inline Registers_x86_64::Registers_x86_64(const void *registers) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +0000306 static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000307 "x86_64 registers do not fit into unw_context_t");
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000308 memcpy(&_registers, registers, sizeof(_registers));
309}
310
311inline Registers_x86_64::Registers_x86_64() {
312 memset(&_registers, 0, sizeof(_registers));
313}
314
315inline bool Registers_x86_64::validRegister(int regNum) const {
316 if (regNum == UNW_REG_IP)
317 return true;
318 if (regNum == UNW_REG_SP)
319 return true;
320 if (regNum < 0)
321 return false;
322 if (regNum > 15)
323 return false;
324 return true;
325}
326
327inline uint64_t Registers_x86_64::getRegister(int regNum) const {
328 switch (regNum) {
329 case UNW_REG_IP:
330 return _registers.__rip;
331 case UNW_REG_SP:
332 return _registers.__rsp;
333 case UNW_X86_64_RAX:
334 return _registers.__rax;
335 case UNW_X86_64_RDX:
336 return _registers.__rdx;
337 case UNW_X86_64_RCX:
338 return _registers.__rcx;
339 case UNW_X86_64_RBX:
340 return _registers.__rbx;
341 case UNW_X86_64_RSI:
342 return _registers.__rsi;
343 case UNW_X86_64_RDI:
344 return _registers.__rdi;
345 case UNW_X86_64_RBP:
346 return _registers.__rbp;
347 case UNW_X86_64_RSP:
348 return _registers.__rsp;
349 case UNW_X86_64_R8:
350 return _registers.__r8;
351 case UNW_X86_64_R9:
352 return _registers.__r9;
353 case UNW_X86_64_R10:
354 return _registers.__r10;
355 case UNW_X86_64_R11:
356 return _registers.__r11;
357 case UNW_X86_64_R12:
358 return _registers.__r12;
359 case UNW_X86_64_R13:
360 return _registers.__r13;
361 case UNW_X86_64_R14:
362 return _registers.__r14;
363 case UNW_X86_64_R15:
364 return _registers.__r15;
365 }
366 _LIBUNWIND_ABORT("unsupported x86_64 register");
367}
368
369inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
370 switch (regNum) {
371 case UNW_REG_IP:
372 _registers.__rip = value;
373 return;
374 case UNW_REG_SP:
375 _registers.__rsp = value;
376 return;
377 case UNW_X86_64_RAX:
378 _registers.__rax = value;
379 return;
380 case UNW_X86_64_RDX:
381 _registers.__rdx = value;
382 return;
383 case UNW_X86_64_RCX:
384 _registers.__rcx = value;
385 return;
386 case UNW_X86_64_RBX:
387 _registers.__rbx = value;
388 return;
389 case UNW_X86_64_RSI:
390 _registers.__rsi = value;
391 return;
392 case UNW_X86_64_RDI:
393 _registers.__rdi = value;
394 return;
395 case UNW_X86_64_RBP:
396 _registers.__rbp = value;
397 return;
398 case UNW_X86_64_RSP:
399 _registers.__rsp = value;
400 return;
401 case UNW_X86_64_R8:
402 _registers.__r8 = value;
403 return;
404 case UNW_X86_64_R9:
405 _registers.__r9 = value;
406 return;
407 case UNW_X86_64_R10:
408 _registers.__r10 = value;
409 return;
410 case UNW_X86_64_R11:
411 _registers.__r11 = value;
412 return;
413 case UNW_X86_64_R12:
414 _registers.__r12 = value;
415 return;
416 case UNW_X86_64_R13:
417 _registers.__r13 = value;
418 return;
419 case UNW_X86_64_R14:
420 _registers.__r14 = value;
421 return;
422 case UNW_X86_64_R15:
423 _registers.__r15 = value;
424 return;
425 }
426 _LIBUNWIND_ABORT("unsupported x86_64 register");
427}
428
429inline const char *Registers_x86_64::getRegisterName(int regNum) {
430 switch (regNum) {
431 case UNW_REG_IP:
432 return "rip";
433 case UNW_REG_SP:
434 return "rsp";
435 case UNW_X86_64_RAX:
436 return "rax";
437 case UNW_X86_64_RDX:
438 return "rdx";
439 case UNW_X86_64_RCX:
440 return "rcx";
441 case UNW_X86_64_RBX:
442 return "rbx";
443 case UNW_X86_64_RSI:
444 return "rsi";
445 case UNW_X86_64_RDI:
446 return "rdi";
447 case UNW_X86_64_RBP:
448 return "rbp";
449 case UNW_X86_64_RSP:
450 return "rsp";
451 case UNW_X86_64_R8:
452 return "r8";
453 case UNW_X86_64_R9:
454 return "r9";
455 case UNW_X86_64_R10:
456 return "r10";
457 case UNW_X86_64_R11:
458 return "r11";
459 case UNW_X86_64_R12:
460 return "r12";
461 case UNW_X86_64_R13:
462 return "r13";
463 case UNW_X86_64_R14:
464 return "r14";
465 case UNW_X86_64_R15:
466 return "r15";
Martin Storsjo86e02182017-10-27 08:11:36 +0000467 case UNW_X86_64_XMM0:
468 return "xmm0";
469 case UNW_X86_64_XMM1:
470 return "xmm1";
471 case UNW_X86_64_XMM2:
472 return "xmm2";
473 case UNW_X86_64_XMM3:
474 return "xmm3";
475 case UNW_X86_64_XMM4:
476 return "xmm4";
477 case UNW_X86_64_XMM5:
478 return "xmm5";
479 case UNW_X86_64_XMM6:
480 return "xmm6";
481 case UNW_X86_64_XMM7:
482 return "xmm7";
483 case UNW_X86_64_XMM8:
484 return "xmm8";
485 case UNW_X86_64_XMM9:
486 return "xmm9";
487 case UNW_X86_64_XMM10:
488 return "xmm10";
489 case UNW_X86_64_XMM11:
490 return "xmm11";
491 case UNW_X86_64_XMM12:
492 return "xmm12";
493 case UNW_X86_64_XMM13:
494 return "xmm13";
495 case UNW_X86_64_XMM14:
496 return "xmm14";
497 case UNW_X86_64_XMM15:
498 return "xmm15";
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000499 default:
500 return "unknown register";
501 }
502}
503
504inline double Registers_x86_64::getFloatRegister(int) const {
505 _LIBUNWIND_ABORT("no x86_64 float registers");
506}
507
508inline void Registers_x86_64::setFloatRegister(int, double) {
509 _LIBUNWIND_ABORT("no x86_64 float registers");
510}
511
Martin Storsjo86e02182017-10-27 08:11:36 +0000512inline bool Registers_x86_64::validVectorRegister(int regNum) const {
513#if defined(_WIN64)
514 if (regNum < UNW_X86_64_XMM0)
515 return false;
516 if (regNum > UNW_X86_64_XMM15)
517 return false;
518 return true;
519#else
520 return false;
521#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000522}
523
Martin Storsjo86e02182017-10-27 08:11:36 +0000524inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
525#if defined(_WIN64)
526 assert(validVectorRegister(regNum));
527 return _xmm[regNum - UNW_X86_64_XMM0];
528#else
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000529 _LIBUNWIND_ABORT("no x86_64 vector registers");
Martin Storsjo86e02182017-10-27 08:11:36 +0000530#endif
531}
532
533inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
534#if defined(_WIN64)
535 assert(validVectorRegister(regNum));
536 _xmm[regNum - UNW_X86_64_XMM0] = value;
537#else
538 _LIBUNWIND_ABORT("no x86_64 vector registers");
539#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000540}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000541#endif // _LIBUNWIND_TARGET_X86_64
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000542
543
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000544#if defined(_LIBUNWIND_TARGET_PPC)
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000545/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
546/// process.
547class _LIBUNWIND_HIDDEN Registers_ppc {
548public:
549 Registers_ppc();
550 Registers_ppc(const void *registers);
551
552 bool validRegister(int num) const;
553 uint32_t getRegister(int num) const;
554 void setRegister(int num, uint32_t value);
555 bool validFloatRegister(int num) const;
556 double getFloatRegister(int num) const;
557 void setFloatRegister(int num, double value);
558 bool validVectorRegister(int num) const;
559 v128 getVectorRegister(int num) const;
560 void setVectorRegister(int num, v128 value);
561 const char *getRegisterName(int num);
562 void jumpto();
Martin Storsjo7c4a46a2017-10-28 20:19:49 +0000563 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; }
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000564
565 uint64_t getSP() const { return _registers.__r1; }
566 void setSP(uint32_t value) { _registers.__r1 = value; }
567 uint64_t getIP() const { return _registers.__srr0; }
568 void setIP(uint32_t value) { _registers.__srr0 = value; }
569
570private:
571 struct ppc_thread_state_t {
572 unsigned int __srr0; /* Instruction address register (PC) */
573 unsigned int __srr1; /* Machine state register (supervisor) */
574 unsigned int __r0;
575 unsigned int __r1;
576 unsigned int __r2;
577 unsigned int __r3;
578 unsigned int __r4;
579 unsigned int __r5;
580 unsigned int __r6;
581 unsigned int __r7;
582 unsigned int __r8;
583 unsigned int __r9;
584 unsigned int __r10;
585 unsigned int __r11;
586 unsigned int __r12;
587 unsigned int __r13;
588 unsigned int __r14;
589 unsigned int __r15;
590 unsigned int __r16;
591 unsigned int __r17;
592 unsigned int __r18;
593 unsigned int __r19;
594 unsigned int __r20;
595 unsigned int __r21;
596 unsigned int __r22;
597 unsigned int __r23;
598 unsigned int __r24;
599 unsigned int __r25;
600 unsigned int __r26;
601 unsigned int __r27;
602 unsigned int __r28;
603 unsigned int __r29;
604 unsigned int __r30;
605 unsigned int __r31;
606 unsigned int __cr; /* Condition register */
607 unsigned int __xer; /* User's integer exception register */
608 unsigned int __lr; /* Link register */
609 unsigned int __ctr; /* Count register */
610 unsigned int __mq; /* MQ register (601 only) */
611 unsigned int __vrsave; /* Vector Save Register */
612 };
613
614 struct ppc_float_state_t {
615 double __fpregs[32];
616
617 unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
618 unsigned int __fpscr; /* floating point status register */
619 };
620
621 ppc_thread_state_t _registers;
622 ppc_float_state_t _floatRegisters;
623 v128 _vectorRegisters[32]; // offset 424
624};
625
626inline Registers_ppc::Registers_ppc(const void *registers) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +0000627 static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +0000628 "ppc registers do not fit into unw_context_t");
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000629 memcpy(&_registers, static_cast<const uint8_t *>(registers),
630 sizeof(_registers));
631 static_assert(sizeof(ppc_thread_state_t) == 160,
632 "expected float register offset to be 160");
633 memcpy(&_floatRegisters,
634 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
635 sizeof(_floatRegisters));
636 static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
637 "expected vector register offset to be 424 bytes");
638 memcpy(_vectorRegisters,
639 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
640 sizeof(ppc_float_state_t),
641 sizeof(_vectorRegisters));
642}
643
644inline Registers_ppc::Registers_ppc() {
645 memset(&_registers, 0, sizeof(_registers));
646 memset(&_floatRegisters, 0, sizeof(_floatRegisters));
647 memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
648}
649
650inline bool Registers_ppc::validRegister(int regNum) const {
651 if (regNum == UNW_REG_IP)
652 return true;
653 if (regNum == UNW_REG_SP)
654 return true;
655 if (regNum == UNW_PPC_VRSAVE)
656 return true;
657 if (regNum < 0)
658 return false;
659 if (regNum <= UNW_PPC_R31)
660 return true;
661 if (regNum == UNW_PPC_MQ)
662 return true;
663 if (regNum == UNW_PPC_LR)
664 return true;
665 if (regNum == UNW_PPC_CTR)
666 return true;
667 if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
668 return true;
669 return false;
670}
671
672inline uint32_t Registers_ppc::getRegister(int regNum) const {
673 switch (regNum) {
674 case UNW_REG_IP:
675 return _registers.__srr0;
676 case UNW_REG_SP:
677 return _registers.__r1;
678 case UNW_PPC_R0:
679 return _registers.__r0;
680 case UNW_PPC_R1:
681 return _registers.__r1;
682 case UNW_PPC_R2:
683 return _registers.__r2;
684 case UNW_PPC_R3:
685 return _registers.__r3;
686 case UNW_PPC_R4:
687 return _registers.__r4;
688 case UNW_PPC_R5:
689 return _registers.__r5;
690 case UNW_PPC_R6:
691 return _registers.__r6;
692 case UNW_PPC_R7:
693 return _registers.__r7;
694 case UNW_PPC_R8:
695 return _registers.__r8;
696 case UNW_PPC_R9:
697 return _registers.__r9;
698 case UNW_PPC_R10:
699 return _registers.__r10;
700 case UNW_PPC_R11:
701 return _registers.__r11;
702 case UNW_PPC_R12:
703 return _registers.__r12;
704 case UNW_PPC_R13:
705 return _registers.__r13;
706 case UNW_PPC_R14:
707 return _registers.__r14;
708 case UNW_PPC_R15:
709 return _registers.__r15;
710 case UNW_PPC_R16:
711 return _registers.__r16;
712 case UNW_PPC_R17:
713 return _registers.__r17;
714 case UNW_PPC_R18:
715 return _registers.__r18;
716 case UNW_PPC_R19:
717 return _registers.__r19;
718 case UNW_PPC_R20:
719 return _registers.__r20;
720 case UNW_PPC_R21:
721 return _registers.__r21;
722 case UNW_PPC_R22:
723 return _registers.__r22;
724 case UNW_PPC_R23:
725 return _registers.__r23;
726 case UNW_PPC_R24:
727 return _registers.__r24;
728 case UNW_PPC_R25:
729 return _registers.__r25;
730 case UNW_PPC_R26:
731 return _registers.__r26;
732 case UNW_PPC_R27:
733 return _registers.__r27;
734 case UNW_PPC_R28:
735 return _registers.__r28;
736 case UNW_PPC_R29:
737 return _registers.__r29;
738 case UNW_PPC_R30:
739 return _registers.__r30;
740 case UNW_PPC_R31:
741 return _registers.__r31;
742 case UNW_PPC_LR:
743 return _registers.__lr;
744 case UNW_PPC_CR0:
745 return (_registers.__cr & 0xF0000000);
746 case UNW_PPC_CR1:
747 return (_registers.__cr & 0x0F000000);
748 case UNW_PPC_CR2:
749 return (_registers.__cr & 0x00F00000);
750 case UNW_PPC_CR3:
751 return (_registers.__cr & 0x000F0000);
752 case UNW_PPC_CR4:
753 return (_registers.__cr & 0x0000F000);
754 case UNW_PPC_CR5:
755 return (_registers.__cr & 0x00000F00);
756 case UNW_PPC_CR6:
757 return (_registers.__cr & 0x000000F0);
758 case UNW_PPC_CR7:
759 return (_registers.__cr & 0x0000000F);
760 case UNW_PPC_VRSAVE:
761 return _registers.__vrsave;
762 }
763 _LIBUNWIND_ABORT("unsupported ppc register");
764}
765
766inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
767 //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
768 switch (regNum) {
769 case UNW_REG_IP:
770 _registers.__srr0 = value;
771 return;
772 case UNW_REG_SP:
773 _registers.__r1 = value;
774 return;
775 case UNW_PPC_R0:
776 _registers.__r0 = value;
777 return;
778 case UNW_PPC_R1:
779 _registers.__r1 = value;
780 return;
781 case UNW_PPC_R2:
782 _registers.__r2 = value;
783 return;
784 case UNW_PPC_R3:
785 _registers.__r3 = value;
786 return;
787 case UNW_PPC_R4:
788 _registers.__r4 = value;
789 return;
790 case UNW_PPC_R5:
791 _registers.__r5 = value;
792 return;
793 case UNW_PPC_R6:
794 _registers.__r6 = value;
795 return;
796 case UNW_PPC_R7:
797 _registers.__r7 = value;
798 return;
799 case UNW_PPC_R8:
800 _registers.__r8 = value;
801 return;
802 case UNW_PPC_R9:
803 _registers.__r9 = value;
804 return;
805 case UNW_PPC_R10:
806 _registers.__r10 = value;
807 return;
808 case UNW_PPC_R11:
809 _registers.__r11 = value;
810 return;
811 case UNW_PPC_R12:
812 _registers.__r12 = value;
813 return;
814 case UNW_PPC_R13:
815 _registers.__r13 = value;
816 return;
817 case UNW_PPC_R14:
818 _registers.__r14 = value;
819 return;
820 case UNW_PPC_R15:
821 _registers.__r15 = value;
822 return;
823 case UNW_PPC_R16:
824 _registers.__r16 = value;
825 return;
826 case UNW_PPC_R17:
827 _registers.__r17 = value;
828 return;
829 case UNW_PPC_R18:
830 _registers.__r18 = value;
831 return;
832 case UNW_PPC_R19:
833 _registers.__r19 = value;
834 return;
835 case UNW_PPC_R20:
836 _registers.__r20 = value;
837 return;
838 case UNW_PPC_R21:
839 _registers.__r21 = value;
840 return;
841 case UNW_PPC_R22:
842 _registers.__r22 = value;
843 return;
844 case UNW_PPC_R23:
845 _registers.__r23 = value;
846 return;
847 case UNW_PPC_R24:
848 _registers.__r24 = value;
849 return;
850 case UNW_PPC_R25:
851 _registers.__r25 = value;
852 return;
853 case UNW_PPC_R26:
854 _registers.__r26 = value;
855 return;
856 case UNW_PPC_R27:
857 _registers.__r27 = value;
858 return;
859 case UNW_PPC_R28:
860 _registers.__r28 = value;
861 return;
862 case UNW_PPC_R29:
863 _registers.__r29 = value;
864 return;
865 case UNW_PPC_R30:
866 _registers.__r30 = value;
867 return;
868 case UNW_PPC_R31:
869 _registers.__r31 = value;
870 return;
871 case UNW_PPC_MQ:
872 _registers.__mq = value;
873 return;
874 case UNW_PPC_LR:
875 _registers.__lr = value;
876 return;
877 case UNW_PPC_CTR:
878 _registers.__ctr = value;
879 return;
880 case UNW_PPC_CR0:
881 _registers.__cr &= 0x0FFFFFFF;
882 _registers.__cr |= (value & 0xF0000000);
883 return;
884 case UNW_PPC_CR1:
885 _registers.__cr &= 0xF0FFFFFF;
886 _registers.__cr |= (value & 0x0F000000);
887 return;
888 case UNW_PPC_CR2:
889 _registers.__cr &= 0xFF0FFFFF;
890 _registers.__cr |= (value & 0x00F00000);
891 return;
892 case UNW_PPC_CR3:
893 _registers.__cr &= 0xFFF0FFFF;
894 _registers.__cr |= (value & 0x000F0000);
895 return;
896 case UNW_PPC_CR4:
897 _registers.__cr &= 0xFFFF0FFF;
898 _registers.__cr |= (value & 0x0000F000);
899 return;
900 case UNW_PPC_CR5:
901 _registers.__cr &= 0xFFFFF0FF;
902 _registers.__cr |= (value & 0x00000F00);
903 return;
904 case UNW_PPC_CR6:
905 _registers.__cr &= 0xFFFFFF0F;
906 _registers.__cr |= (value & 0x000000F0);
907 return;
908 case UNW_PPC_CR7:
909 _registers.__cr &= 0xFFFFFFF0;
910 _registers.__cr |= (value & 0x0000000F);
911 return;
912 case UNW_PPC_VRSAVE:
913 _registers.__vrsave = value;
914 return;
915 // not saved
916 return;
917 case UNW_PPC_XER:
918 _registers.__xer = value;
919 return;
920 case UNW_PPC_AP:
921 case UNW_PPC_VSCR:
922 case UNW_PPC_SPEFSCR:
923 // not saved
924 return;
925 }
926 _LIBUNWIND_ABORT("unsupported ppc register");
927}
928
929inline bool Registers_ppc::validFloatRegister(int regNum) const {
930 if (regNum < UNW_PPC_F0)
931 return false;
932 if (regNum > UNW_PPC_F31)
933 return false;
934 return true;
935}
936
937inline double Registers_ppc::getFloatRegister(int regNum) const {
938 assert(validFloatRegister(regNum));
939 return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
940}
941
942inline void Registers_ppc::setFloatRegister(int regNum, double value) {
943 assert(validFloatRegister(regNum));
944 _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
945}
946
947inline bool Registers_ppc::validVectorRegister(int regNum) const {
948 if (regNum < UNW_PPC_V0)
949 return false;
950 if (regNum > UNW_PPC_V31)
951 return false;
952 return true;
953}
954
955inline v128 Registers_ppc::getVectorRegister(int regNum) const {
956 assert(validVectorRegister(regNum));
957 v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
958 return result;
959}
960
961inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
962 assert(validVectorRegister(regNum));
963 _vectorRegisters[regNum - UNW_PPC_V0] = value;
964}
965
966inline const char *Registers_ppc::getRegisterName(int regNum) {
967 switch (regNum) {
968 case UNW_REG_IP:
969 return "ip";
970 case UNW_REG_SP:
971 return "sp";
972 case UNW_PPC_R0:
973 return "r0";
974 case UNW_PPC_R1:
975 return "r1";
976 case UNW_PPC_R2:
977 return "r2";
978 case UNW_PPC_R3:
979 return "r3";
980 case UNW_PPC_R4:
981 return "r4";
982 case UNW_PPC_R5:
983 return "r5";
984 case UNW_PPC_R6:
985 return "r6";
986 case UNW_PPC_R7:
987 return "r7";
988 case UNW_PPC_R8:
989 return "r8";
990 case UNW_PPC_R9:
991 return "r9";
992 case UNW_PPC_R10:
993 return "r10";
994 case UNW_PPC_R11:
995 return "r11";
996 case UNW_PPC_R12:
997 return "r12";
998 case UNW_PPC_R13:
999 return "r13";
1000 case UNW_PPC_R14:
1001 return "r14";
1002 case UNW_PPC_R15:
1003 return "r15";
1004 case UNW_PPC_R16:
1005 return "r16";
1006 case UNW_PPC_R17:
1007 return "r17";
1008 case UNW_PPC_R18:
1009 return "r18";
1010 case UNW_PPC_R19:
1011 return "r19";
1012 case UNW_PPC_R20:
1013 return "r20";
1014 case UNW_PPC_R21:
1015 return "r21";
1016 case UNW_PPC_R22:
1017 return "r22";
1018 case UNW_PPC_R23:
1019 return "r23";
1020 case UNW_PPC_R24:
1021 return "r24";
1022 case UNW_PPC_R25:
1023 return "r25";
1024 case UNW_PPC_R26:
1025 return "r26";
1026 case UNW_PPC_R27:
1027 return "r27";
1028 case UNW_PPC_R28:
1029 return "r28";
1030 case UNW_PPC_R29:
1031 return "r29";
1032 case UNW_PPC_R30:
1033 return "r30";
1034 case UNW_PPC_R31:
1035 return "r31";
1036 case UNW_PPC_F0:
1037 return "fp0";
1038 case UNW_PPC_F1:
1039 return "fp1";
1040 case UNW_PPC_F2:
1041 return "fp2";
1042 case UNW_PPC_F3:
1043 return "fp3";
1044 case UNW_PPC_F4:
1045 return "fp4";
1046 case UNW_PPC_F5:
1047 return "fp5";
1048 case UNW_PPC_F6:
1049 return "fp6";
1050 case UNW_PPC_F7:
1051 return "fp7";
1052 case UNW_PPC_F8:
1053 return "fp8";
1054 case UNW_PPC_F9:
1055 return "fp9";
1056 case UNW_PPC_F10:
1057 return "fp10";
1058 case UNW_PPC_F11:
1059 return "fp11";
1060 case UNW_PPC_F12:
1061 return "fp12";
1062 case UNW_PPC_F13:
1063 return "fp13";
1064 case UNW_PPC_F14:
1065 return "fp14";
1066 case UNW_PPC_F15:
1067 return "fp15";
1068 case UNW_PPC_F16:
1069 return "fp16";
1070 case UNW_PPC_F17:
1071 return "fp17";
1072 case UNW_PPC_F18:
1073 return "fp18";
1074 case UNW_PPC_F19:
1075 return "fp19";
1076 case UNW_PPC_F20:
1077 return "fp20";
1078 case UNW_PPC_F21:
1079 return "fp21";
1080 case UNW_PPC_F22:
1081 return "fp22";
1082 case UNW_PPC_F23:
1083 return "fp23";
1084 case UNW_PPC_F24:
1085 return "fp24";
1086 case UNW_PPC_F25:
1087 return "fp25";
1088 case UNW_PPC_F26:
1089 return "fp26";
1090 case UNW_PPC_F27:
1091 return "fp27";
1092 case UNW_PPC_F28:
1093 return "fp28";
1094 case UNW_PPC_F29:
1095 return "fp29";
1096 case UNW_PPC_F30:
1097 return "fp30";
1098 case UNW_PPC_F31:
1099 return "fp31";
1100 case UNW_PPC_LR:
1101 return "lr";
1102 default:
1103 return "unknown register";
1104 }
1105
1106}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001107#endif // _LIBUNWIND_TARGET_PPC
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001108
1109
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001110#if defined(_LIBUNWIND_TARGET_AARCH64)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001111/// Registers_arm64 holds the register state of a thread in a 64-bit arm
1112/// process.
1113class _LIBUNWIND_HIDDEN Registers_arm64 {
1114public:
1115 Registers_arm64();
1116 Registers_arm64(const void *registers);
1117
1118 bool validRegister(int num) const;
1119 uint64_t getRegister(int num) const;
1120 void setRegister(int num, uint64_t value);
1121 bool validFloatRegister(int num) const;
1122 double getFloatRegister(int num) const;
1123 void setFloatRegister(int num, double value);
1124 bool validVectorRegister(int num) const;
1125 v128 getVectorRegister(int num) const;
1126 void setVectorRegister(int num, v128 value);
1127 const char *getRegisterName(int num);
1128 void jumpto();
Martin Storsjo7c4a46a2017-10-28 20:19:49 +00001129 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001130
1131 uint64_t getSP() const { return _registers.__sp; }
1132 void setSP(uint64_t value) { _registers.__sp = value; }
1133 uint64_t getIP() const { return _registers.__pc; }
1134 void setIP(uint64_t value) { _registers.__pc = value; }
1135 uint64_t getFP() const { return _registers.__fp; }
1136 void setFP(uint64_t value) { _registers.__fp = value; }
1137
1138private:
1139 struct GPRs {
1140 uint64_t __x[29]; // x0-x28
1141 uint64_t __fp; // Frame pointer x29
1142 uint64_t __lr; // Link register x30
1143 uint64_t __sp; // Stack pointer x31
1144 uint64_t __pc; // Program counter
1145 uint64_t padding; // 16-byte align
1146 };
1147
1148 GPRs _registers;
1149 double _vectorHalfRegisters[32];
1150 // Currently only the lower double in 128-bit vectore registers
1151 // is perserved during unwinding. We could define new register
1152 // numbers (> 96) which mean whole vector registers, then this
1153 // struct would need to change to contain whole vector registers.
1154};
1155
1156inline Registers_arm64::Registers_arm64(const void *registers) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +00001157 static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001158 "arm64 registers do not fit into unw_context_t");
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001159 memcpy(&_registers, registers, sizeof(_registers));
1160 static_assert(sizeof(GPRs) == 0x110,
1161 "expected VFP registers to be at offset 272");
1162 memcpy(_vectorHalfRegisters,
1163 static_cast<const uint8_t *>(registers) + sizeof(GPRs),
1164 sizeof(_vectorHalfRegisters));
1165}
1166
1167inline Registers_arm64::Registers_arm64() {
1168 memset(&_registers, 0, sizeof(_registers));
1169 memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
1170}
1171
1172inline bool Registers_arm64::validRegister(int regNum) const {
1173 if (regNum == UNW_REG_IP)
1174 return true;
1175 if (regNum == UNW_REG_SP)
1176 return true;
1177 if (regNum < 0)
1178 return false;
1179 if (regNum > 95)
1180 return false;
1181 if ((regNum > 31) && (regNum < 64))
1182 return false;
1183 return true;
1184}
1185
1186inline uint64_t Registers_arm64::getRegister(int regNum) const {
1187 if (regNum == UNW_REG_IP)
1188 return _registers.__pc;
1189 if (regNum == UNW_REG_SP)
1190 return _registers.__sp;
1191 if ((regNum >= 0) && (regNum < 32))
1192 return _registers.__x[regNum];
1193 _LIBUNWIND_ABORT("unsupported arm64 register");
1194}
1195
1196inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1197 if (regNum == UNW_REG_IP)
1198 _registers.__pc = value;
1199 else if (regNum == UNW_REG_SP)
1200 _registers.__sp = value;
1201 else if ((regNum >= 0) && (regNum < 32))
1202 _registers.__x[regNum] = value;
1203 else
1204 _LIBUNWIND_ABORT("unsupported arm64 register");
1205}
1206
1207inline const char *Registers_arm64::getRegisterName(int regNum) {
1208 switch (regNum) {
1209 case UNW_REG_IP:
1210 return "pc";
1211 case UNW_REG_SP:
1212 return "sp";
1213 case UNW_ARM64_X0:
1214 return "x0";
1215 case UNW_ARM64_X1:
1216 return "x1";
1217 case UNW_ARM64_X2:
1218 return "x2";
1219 case UNW_ARM64_X3:
1220 return "x3";
1221 case UNW_ARM64_X4:
1222 return "x4";
1223 case UNW_ARM64_X5:
1224 return "x5";
1225 case UNW_ARM64_X6:
1226 return "x6";
1227 case UNW_ARM64_X7:
1228 return "x7";
1229 case UNW_ARM64_X8:
1230 return "x8";
1231 case UNW_ARM64_X9:
1232 return "x9";
1233 case UNW_ARM64_X10:
1234 return "x10";
1235 case UNW_ARM64_X11:
1236 return "x11";
1237 case UNW_ARM64_X12:
1238 return "x12";
1239 case UNW_ARM64_X13:
1240 return "x13";
1241 case UNW_ARM64_X14:
1242 return "x14";
1243 case UNW_ARM64_X15:
1244 return "x15";
1245 case UNW_ARM64_X16:
1246 return "x16";
1247 case UNW_ARM64_X17:
1248 return "x17";
1249 case UNW_ARM64_X18:
1250 return "x18";
1251 case UNW_ARM64_X19:
1252 return "x19";
1253 case UNW_ARM64_X20:
1254 return "x20";
1255 case UNW_ARM64_X21:
1256 return "x21";
1257 case UNW_ARM64_X22:
1258 return "x22";
1259 case UNW_ARM64_X23:
1260 return "x23";
1261 case UNW_ARM64_X24:
1262 return "x24";
1263 case UNW_ARM64_X25:
1264 return "x25";
1265 case UNW_ARM64_X26:
1266 return "x26";
1267 case UNW_ARM64_X27:
1268 return "x27";
1269 case UNW_ARM64_X28:
1270 return "x28";
1271 case UNW_ARM64_X29:
1272 return "fp";
1273 case UNW_ARM64_X30:
1274 return "lr";
1275 case UNW_ARM64_X31:
1276 return "sp";
1277 case UNW_ARM64_D0:
1278 return "d0";
1279 case UNW_ARM64_D1:
1280 return "d1";
1281 case UNW_ARM64_D2:
1282 return "d2";
1283 case UNW_ARM64_D3:
1284 return "d3";
1285 case UNW_ARM64_D4:
1286 return "d4";
1287 case UNW_ARM64_D5:
1288 return "d5";
1289 case UNW_ARM64_D6:
1290 return "d6";
1291 case UNW_ARM64_D7:
1292 return "d7";
1293 case UNW_ARM64_D8:
1294 return "d8";
1295 case UNW_ARM64_D9:
1296 return "d9";
1297 case UNW_ARM64_D10:
1298 return "d10";
1299 case UNW_ARM64_D11:
1300 return "d11";
1301 case UNW_ARM64_D12:
1302 return "d12";
1303 case UNW_ARM64_D13:
1304 return "d13";
1305 case UNW_ARM64_D14:
1306 return "d14";
1307 case UNW_ARM64_D15:
1308 return "d15";
1309 case UNW_ARM64_D16:
1310 return "d16";
1311 case UNW_ARM64_D17:
1312 return "d17";
1313 case UNW_ARM64_D18:
1314 return "d18";
1315 case UNW_ARM64_D19:
1316 return "d19";
1317 case UNW_ARM64_D20:
1318 return "d20";
1319 case UNW_ARM64_D21:
1320 return "d21";
1321 case UNW_ARM64_D22:
1322 return "d22";
1323 case UNW_ARM64_D23:
1324 return "d23";
1325 case UNW_ARM64_D24:
1326 return "d24";
1327 case UNW_ARM64_D25:
1328 return "d25";
1329 case UNW_ARM64_D26:
1330 return "d26";
1331 case UNW_ARM64_D27:
1332 return "d27";
1333 case UNW_ARM64_D28:
1334 return "d28";
1335 case UNW_ARM64_D29:
1336 return "d29";
1337 case UNW_ARM64_D30:
1338 return "d30";
1339 case UNW_ARM64_D31:
1340 return "d31";
1341 default:
1342 return "unknown register";
1343 }
1344}
1345
1346inline bool Registers_arm64::validFloatRegister(int regNum) const {
1347 if (regNum < UNW_ARM64_D0)
1348 return false;
1349 if (regNum > UNW_ARM64_D31)
1350 return false;
1351 return true;
1352}
1353
1354inline double Registers_arm64::getFloatRegister(int regNum) const {
1355 assert(validFloatRegister(regNum));
1356 return _vectorHalfRegisters[regNum - UNW_ARM64_D0];
1357}
1358
1359inline void Registers_arm64::setFloatRegister(int regNum, double value) {
1360 assert(validFloatRegister(regNum));
1361 _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value;
1362}
1363
1364inline bool Registers_arm64::validVectorRegister(int) const {
1365 return false;
1366}
1367
1368inline v128 Registers_arm64::getVectorRegister(int) const {
1369 _LIBUNWIND_ABORT("no arm64 vector register support yet");
1370}
1371
1372inline void Registers_arm64::setVectorRegister(int, v128) {
1373 _LIBUNWIND_ABORT("no arm64 vector register support yet");
1374}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001375#endif // _LIBUNWIND_TARGET_AARCH64
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001376
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001377#if defined(_LIBUNWIND_TARGET_ARM)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001378/// Registers_arm holds the register state of a thread in a 32-bit arm
1379/// process.
1380///
1381/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
1382/// this uses more memory than required.
1383class _LIBUNWIND_HIDDEN Registers_arm {
1384public:
1385 Registers_arm();
1386 Registers_arm(const void *registers);
1387
1388 bool validRegister(int num) const;
Martin Storsjo23a943b2017-11-02 08:16:16 +00001389 uint32_t getRegister(int num) const;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001390 void setRegister(int num, uint32_t value);
1391 bool validFloatRegister(int num) const;
1392 unw_fpreg_t getFloatRegister(int num);
1393 void setFloatRegister(int num, unw_fpreg_t value);
1394 bool validVectorRegister(int num) const;
1395 v128 getVectorRegister(int num) const;
1396 void setVectorRegister(int num, v128 value);
1397 const char *getRegisterName(int num);
1398 void jumpto() {
1399 restoreSavedFloatRegisters();
1400 restoreCoreAndJumpTo();
1401 }
Martin Storsjo23a943b2017-11-02 08:16:16 +00001402 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; }
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001403
1404 uint32_t getSP() const { return _registers.__sp; }
1405 void setSP(uint32_t value) { _registers.__sp = value; }
1406 uint32_t getIP() const { return _registers.__pc; }
1407 void setIP(uint32_t value) { _registers.__pc = value; }
1408
1409 void saveVFPAsX() {
1410 assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
1411 _use_X_for_vfp_save = true;
1412 }
1413
1414 void restoreSavedFloatRegisters() {
1415 if (_saved_vfp_d0_d15) {
1416 if (_use_X_for_vfp_save)
1417 restoreVFPWithFLDMX(_vfp_d0_d15_pad);
1418 else
1419 restoreVFPWithFLDMD(_vfp_d0_d15_pad);
1420 }
1421 if (_saved_vfp_d16_d31)
1422 restoreVFPv3(_vfp_d16_d31);
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001423#if defined(__ARM_WMMX)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001424 if (_saved_iwmmx)
1425 restoreiWMMX(_iwmmx);
1426 if (_saved_iwmmx_control)
1427 restoreiWMMXControl(_iwmmx_control);
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001428#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001429 }
1430
1431private:
1432 struct GPRs {
1433 uint32_t __r[13]; // r0-r12
1434 uint32_t __sp; // Stack pointer r13
1435 uint32_t __lr; // Link register r14
1436 uint32_t __pc; // Program counter r15
1437 };
1438
1439 static void saveVFPWithFSTMD(unw_fpreg_t*);
1440 static void saveVFPWithFSTMX(unw_fpreg_t*);
1441 static void saveVFPv3(unw_fpreg_t*);
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001442 static void restoreVFPWithFLDMD(unw_fpreg_t*);
1443 static void restoreVFPWithFLDMX(unw_fpreg_t*);
1444 static void restoreVFPv3(unw_fpreg_t*);
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001445#if defined(__ARM_WMMX)
1446 static void saveiWMMX(unw_fpreg_t*);
1447 static void saveiWMMXControl(uint32_t*);
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001448 static void restoreiWMMX(unw_fpreg_t*);
1449 static void restoreiWMMXControl(uint32_t*);
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001450#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001451 void restoreCoreAndJumpTo();
1452
1453 // ARM registers
1454 GPRs _registers;
1455
1456 // We save floating point registers lazily because we can't know ahead of
1457 // time which ones are used. See EHABI #4.7.
1458
1459 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
1460 //
1461 // See EHABI #7.5 that explains how matching instruction sequences for load
1462 // and store need to be used to correctly restore the exact register bits.
1463 bool _use_X_for_vfp_save;
1464 // Whether VFP D0-D15 are saved.
1465 bool _saved_vfp_d0_d15;
1466 // Whether VFPv3 D16-D31 are saved.
1467 bool _saved_vfp_d16_d31;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001468 // VFP registers D0-D15, + padding if saved using FSTMX
1469 unw_fpreg_t _vfp_d0_d15_pad[17];
1470 // VFPv3 registers D16-D31, always saved using FSTMD
1471 unw_fpreg_t _vfp_d16_d31[16];
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001472#if defined(__ARM_WMMX)
1473 // Whether iWMMX data registers are saved.
1474 bool _saved_iwmmx;
1475 // Whether iWMMX control registers are saved.
Martin Storsjo23a943b2017-11-02 08:16:16 +00001476 mutable bool _saved_iwmmx_control;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001477 // iWMMX registers
1478 unw_fpreg_t _iwmmx[16];
1479 // iWMMX control registers
Martin Storsjo23a943b2017-11-02 08:16:16 +00001480 mutable uint32_t _iwmmx_control[4];
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001481#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001482};
1483
1484inline Registers_arm::Registers_arm(const void *registers)
1485 : _use_X_for_vfp_save(false),
1486 _saved_vfp_d0_d15(false),
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001487 _saved_vfp_d16_d31(false) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +00001488 static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001489 "arm registers do not fit into unw_context_t");
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001490 // See unw_getcontext() note about data.
1491 memcpy(&_registers, registers, sizeof(_registers));
1492 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
1493 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001494#if defined(__ARM_WMMX)
1495 _saved_iwmmx = false;
1496 _saved_iwmmx_control = false;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001497 memset(&_iwmmx, 0, sizeof(_iwmmx));
1498 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001499#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001500}
1501
1502inline Registers_arm::Registers_arm()
1503 : _use_X_for_vfp_save(false),
1504 _saved_vfp_d0_d15(false),
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001505 _saved_vfp_d16_d31(false) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001506 memset(&_registers, 0, sizeof(_registers));
1507 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
1508 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001509#if defined(__ARM_WMMX)
1510 _saved_iwmmx = false;
1511 _saved_iwmmx_control = false;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001512 memset(&_iwmmx, 0, sizeof(_iwmmx));
1513 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001514#endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001515}
1516
1517inline bool Registers_arm::validRegister(int regNum) const {
1518 // Returns true for all non-VFP registers supported by the EHABI
1519 // virtual register set (VRS).
1520 if (regNum == UNW_REG_IP)
1521 return true;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001522
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001523 if (regNum == UNW_REG_SP)
1524 return true;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001525
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001526 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
1527 return true;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001528
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001529#if defined(__ARM_WMMX)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001530 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
1531 return true;
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001532#endif
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001533
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001534 return false;
1535}
1536
Martin Storsjo23a943b2017-11-02 08:16:16 +00001537inline uint32_t Registers_arm::getRegister(int regNum) const {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001538 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
1539 return _registers.__sp;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001540
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001541 if (regNum == UNW_ARM_LR)
1542 return _registers.__lr;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001543
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001544 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
1545 return _registers.__pc;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001546
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001547 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
1548 return _registers.__r[regNum];
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001549
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001550#if defined(__ARM_WMMX)
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001551 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
1552 if (!_saved_iwmmx_control) {
1553 _saved_iwmmx_control = true;
1554 saveiWMMXControl(_iwmmx_control);
1555 }
1556 return _iwmmx_control[regNum - UNW_ARM_WC0];
1557 }
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001558#endif
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001559
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001560 _LIBUNWIND_ABORT("unsupported arm register");
1561}
1562
1563inline void Registers_arm::setRegister(int regNum, uint32_t value) {
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001564 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001565 _registers.__sp = value;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001566 return;
1567 }
1568
1569 if (regNum == UNW_ARM_LR) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001570 _registers.__lr = value;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001571 return;
1572 }
1573
1574 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001575 _registers.__pc = value;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001576 return;
1577 }
1578
1579 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001580 _registers.__r[regNum] = value;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001581 return;
1582 }
1583
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001584#if defined(__ARM_WMMX)
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001585 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001586 if (!_saved_iwmmx_control) {
1587 _saved_iwmmx_control = true;
1588 saveiWMMXControl(_iwmmx_control);
1589 }
1590 _iwmmx_control[regNum - UNW_ARM_WC0] = value;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001591 return;
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001592 }
1593#endif
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001594
1595 _LIBUNWIND_ABORT("unsupported arm register");
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001596}
1597
1598inline const char *Registers_arm::getRegisterName(int regNum) {
1599 switch (regNum) {
1600 case UNW_REG_IP:
1601 case UNW_ARM_IP: // UNW_ARM_R15 is alias
1602 return "pc";
1603 case UNW_ARM_LR: // UNW_ARM_R14 is alias
1604 return "lr";
1605 case UNW_REG_SP:
1606 case UNW_ARM_SP: // UNW_ARM_R13 is alias
1607 return "sp";
1608 case UNW_ARM_R0:
1609 return "r0";
1610 case UNW_ARM_R1:
1611 return "r1";
1612 case UNW_ARM_R2:
1613 return "r2";
1614 case UNW_ARM_R3:
1615 return "r3";
1616 case UNW_ARM_R4:
1617 return "r4";
1618 case UNW_ARM_R5:
1619 return "r5";
1620 case UNW_ARM_R6:
1621 return "r6";
1622 case UNW_ARM_R7:
1623 return "r7";
1624 case UNW_ARM_R8:
1625 return "r8";
1626 case UNW_ARM_R9:
1627 return "r9";
1628 case UNW_ARM_R10:
1629 return "r10";
1630 case UNW_ARM_R11:
1631 return "r11";
1632 case UNW_ARM_R12:
1633 return "r12";
1634 case UNW_ARM_S0:
1635 return "s0";
1636 case UNW_ARM_S1:
1637 return "s1";
1638 case UNW_ARM_S2:
1639 return "s2";
1640 case UNW_ARM_S3:
1641 return "s3";
1642 case UNW_ARM_S4:
1643 return "s4";
1644 case UNW_ARM_S5:
1645 return "s5";
1646 case UNW_ARM_S6:
1647 return "s6";
1648 case UNW_ARM_S7:
1649 return "s7";
1650 case UNW_ARM_S8:
1651 return "s8";
1652 case UNW_ARM_S9:
1653 return "s9";
1654 case UNW_ARM_S10:
1655 return "s10";
1656 case UNW_ARM_S11:
1657 return "s11";
1658 case UNW_ARM_S12:
1659 return "s12";
1660 case UNW_ARM_S13:
1661 return "s13";
1662 case UNW_ARM_S14:
1663 return "s14";
1664 case UNW_ARM_S15:
1665 return "s15";
1666 case UNW_ARM_S16:
1667 return "s16";
1668 case UNW_ARM_S17:
1669 return "s17";
1670 case UNW_ARM_S18:
1671 return "s18";
1672 case UNW_ARM_S19:
1673 return "s19";
1674 case UNW_ARM_S20:
1675 return "s20";
1676 case UNW_ARM_S21:
1677 return "s21";
1678 case UNW_ARM_S22:
1679 return "s22";
1680 case UNW_ARM_S23:
1681 return "s23";
1682 case UNW_ARM_S24:
1683 return "s24";
1684 case UNW_ARM_S25:
1685 return "s25";
1686 case UNW_ARM_S26:
1687 return "s26";
1688 case UNW_ARM_S27:
1689 return "s27";
1690 case UNW_ARM_S28:
1691 return "s28";
1692 case UNW_ARM_S29:
1693 return "s29";
1694 case UNW_ARM_S30:
1695 return "s30";
1696 case UNW_ARM_S31:
1697 return "s31";
1698 case UNW_ARM_D0:
1699 return "d0";
1700 case UNW_ARM_D1:
1701 return "d1";
1702 case UNW_ARM_D2:
1703 return "d2";
1704 case UNW_ARM_D3:
1705 return "d3";
1706 case UNW_ARM_D4:
1707 return "d4";
1708 case UNW_ARM_D5:
1709 return "d5";
1710 case UNW_ARM_D6:
1711 return "d6";
1712 case UNW_ARM_D7:
1713 return "d7";
1714 case UNW_ARM_D8:
1715 return "d8";
1716 case UNW_ARM_D9:
1717 return "d9";
1718 case UNW_ARM_D10:
1719 return "d10";
1720 case UNW_ARM_D11:
1721 return "d11";
1722 case UNW_ARM_D12:
1723 return "d12";
1724 case UNW_ARM_D13:
1725 return "d13";
1726 case UNW_ARM_D14:
1727 return "d14";
1728 case UNW_ARM_D15:
1729 return "d15";
1730 case UNW_ARM_D16:
1731 return "d16";
1732 case UNW_ARM_D17:
1733 return "d17";
1734 case UNW_ARM_D18:
1735 return "d18";
1736 case UNW_ARM_D19:
1737 return "d19";
1738 case UNW_ARM_D20:
1739 return "d20";
1740 case UNW_ARM_D21:
1741 return "d21";
1742 case UNW_ARM_D22:
1743 return "d22";
1744 case UNW_ARM_D23:
1745 return "d23";
1746 case UNW_ARM_D24:
1747 return "d24";
1748 case UNW_ARM_D25:
1749 return "d25";
1750 case UNW_ARM_D26:
1751 return "d26";
1752 case UNW_ARM_D27:
1753 return "d27";
1754 case UNW_ARM_D28:
1755 return "d28";
1756 case UNW_ARM_D29:
1757 return "d29";
1758 case UNW_ARM_D30:
1759 return "d30";
1760 case UNW_ARM_D31:
1761 return "d31";
1762 default:
1763 return "unknown register";
1764 }
1765}
1766
1767inline bool Registers_arm::validFloatRegister(int regNum) const {
1768 // NOTE: Consider the intel MMX registers floating points so the
1769 // unw_get_fpreg can be used to transmit the 64-bit data back.
1770 return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001771#if defined(__ARM_WMMX)
1772 || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
1773#endif
1774 ;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001775}
1776
1777inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
1778 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
1779 if (!_saved_vfp_d0_d15) {
1780 _saved_vfp_d0_d15 = true;
1781 if (_use_X_for_vfp_save)
1782 saveVFPWithFSTMX(_vfp_d0_d15_pad);
1783 else
1784 saveVFPWithFSTMD(_vfp_d0_d15_pad);
1785 }
1786 return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001787 }
1788
1789 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001790 if (!_saved_vfp_d16_d31) {
1791 _saved_vfp_d16_d31 = true;
1792 saveVFPv3(_vfp_d16_d31);
1793 }
1794 return _vfp_d16_d31[regNum - UNW_ARM_D16];
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001795 }
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001796
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001797#if defined(__ARM_WMMX)
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001798 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001799 if (!_saved_iwmmx) {
1800 _saved_iwmmx = true;
1801 saveiWMMX(_iwmmx);
1802 }
1803 return _iwmmx[regNum - UNW_ARM_WR0];
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001804 }
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001805#endif
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001806
1807 _LIBUNWIND_ABORT("Unknown ARM float register");
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001808}
1809
1810inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
1811 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
1812 if (!_saved_vfp_d0_d15) {
1813 _saved_vfp_d0_d15 = true;
1814 if (_use_X_for_vfp_save)
1815 saveVFPWithFSTMX(_vfp_d0_d15_pad);
1816 else
1817 saveVFPWithFSTMD(_vfp_d0_d15_pad);
1818 }
1819 _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001820 return;
1821 }
1822
1823 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001824 if (!_saved_vfp_d16_d31) {
1825 _saved_vfp_d16_d31 = true;
1826 saveVFPv3(_vfp_d16_d31);
1827 }
Saleem Abdulrasool7a61b662015-08-21 03:21:31 +00001828 _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001829 return;
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001830 }
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001831
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001832#if defined(__ARM_WMMX)
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001833 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001834 if (!_saved_iwmmx) {
1835 _saved_iwmmx = true;
1836 saveiWMMX(_iwmmx);
1837 }
1838 _iwmmx[regNum - UNW_ARM_WR0] = value;
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001839 return;
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001840 }
Asiri Rathnayake0ddaf132016-07-07 10:55:39 +00001841#endif
Asiri Rathnayake878c40b2016-07-08 12:13:31 +00001842
1843 _LIBUNWIND_ABORT("Unknown ARM float register");
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001844}
1845
1846inline bool Registers_arm::validVectorRegister(int) const {
1847 return false;
1848}
1849
1850inline v128 Registers_arm::getVectorRegister(int) const {
1851 _LIBUNWIND_ABORT("ARM vector support not implemented");
1852}
1853
1854inline void Registers_arm::setVectorRegister(int, v128) {
1855 _LIBUNWIND_ABORT("ARM vector support not implemented");
1856}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001857#endif // _LIBUNWIND_TARGET_ARM
1858
1859
1860#if defined(_LIBUNWIND_TARGET_OR1K)
Peter Zotovd4255ab2015-08-31 05:26:37 +00001861/// Registers_or1k holds the register state of a thread in an OpenRISC1000
1862/// process.
1863class _LIBUNWIND_HIDDEN Registers_or1k {
1864public:
1865 Registers_or1k();
1866 Registers_or1k(const void *registers);
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001867
Peter Zotovd4255ab2015-08-31 05:26:37 +00001868 bool validRegister(int num) const;
1869 uint32_t getRegister(int num) const;
1870 void setRegister(int num, uint32_t value);
1871 bool validFloatRegister(int num) const;
1872 double getFloatRegister(int num) const;
1873 void setFloatRegister(int num, double value);
1874 bool validVectorRegister(int num) const;
1875 v128 getVectorRegister(int num) const;
1876 void setVectorRegister(int num, v128 value);
1877 const char *getRegisterName(int num);
1878 void jumpto();
Martin Storsjo7c4a46a2017-10-28 20:19:49 +00001879 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; }
Peter Zotovd4255ab2015-08-31 05:26:37 +00001880
1881 uint64_t getSP() const { return _registers.__r[1]; }
1882 void setSP(uint32_t value) { _registers.__r[1] = value; }
1883 uint64_t getIP() const { return _registers.__r[9]; }
1884 void setIP(uint32_t value) { _registers.__r[9] = value; }
1885
1886private:
1887 struct or1k_thread_state_t {
1888 unsigned int __r[32];
1889 };
1890
1891 or1k_thread_state_t _registers;
1892};
1893
1894inline Registers_or1k::Registers_or1k(const void *registers) {
Asiri Rathnayake98bc6762016-05-26 21:45:54 +00001895 static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00001896 "or1k registers do not fit into unw_context_t");
Peter Zotovd4255ab2015-08-31 05:26:37 +00001897 memcpy(&_registers, static_cast<const uint8_t *>(registers),
1898 sizeof(_registers));
1899}
1900
1901inline Registers_or1k::Registers_or1k() {
1902 memset(&_registers, 0, sizeof(_registers));
1903}
1904
1905inline bool Registers_or1k::validRegister(int regNum) const {
1906 if (regNum == UNW_REG_IP)
1907 return true;
1908 if (regNum == UNW_REG_SP)
1909 return true;
1910 if (regNum < 0)
1911 return false;
1912 if (regNum <= UNW_OR1K_R31)
1913 return true;
1914 return false;
1915}
1916
1917inline uint32_t Registers_or1k::getRegister(int regNum) const {
1918 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
1919 return _registers.__r[regNum - UNW_OR1K_R0];
1920
1921 switch (regNum) {
1922 case UNW_REG_IP:
1923 return _registers.__r[9];
1924 case UNW_REG_SP:
1925 return _registers.__r[1];
1926 }
1927 _LIBUNWIND_ABORT("unsupported or1k register");
1928}
1929
1930inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
1931 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
1932 _registers.__r[regNum - UNW_OR1K_R0] = value;
1933 return;
1934 }
1935
1936 switch (regNum) {
1937 case UNW_REG_IP:
1938 _registers.__r[9] = value;
1939 return;
1940 case UNW_REG_SP:
1941 _registers.__r[1] = value;
1942 return;
1943 }
1944 _LIBUNWIND_ABORT("unsupported or1k register");
1945}
1946
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001947inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001948 return false;
1949}
1950
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001951inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001952 _LIBUNWIND_ABORT("or1k float support not implemented");
1953}
1954
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001955inline void Registers_or1k::setFloatRegister(int /* regNum */,
1956 double /* value */) {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001957 _LIBUNWIND_ABORT("or1k float support not implemented");
1958}
1959
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001960inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001961 return false;
1962}
1963
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001964inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001965 _LIBUNWIND_ABORT("or1k vector support not implemented");
1966}
1967
Saleem Abdulrasool4911b2f2015-09-01 04:29:03 +00001968inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
Peter Zotovd4255ab2015-08-31 05:26:37 +00001969 _LIBUNWIND_ABORT("or1k vector support not implemented");
1970}
1971
1972inline const char *Registers_or1k::getRegisterName(int regNum) {
1973 switch (regNum) {
1974 case UNW_OR1K_R0:
1975 return "r0";
1976 case UNW_OR1K_R1:
1977 return "r1";
1978 case UNW_OR1K_R2:
1979 return "r2";
1980 case UNW_OR1K_R3:
1981 return "r3";
1982 case UNW_OR1K_R4:
1983 return "r4";
1984 case UNW_OR1K_R5:
1985 return "r5";
1986 case UNW_OR1K_R6:
1987 return "r6";
1988 case UNW_OR1K_R7:
1989 return "r7";
1990 case UNW_OR1K_R8:
1991 return "r8";
1992 case UNW_OR1K_R9:
1993 return "r9";
1994 case UNW_OR1K_R10:
1995 return "r10";
1996 case UNW_OR1K_R11:
1997 return "r11";
1998 case UNW_OR1K_R12:
1999 return "r12";
2000 case UNW_OR1K_R13:
2001 return "r13";
2002 case UNW_OR1K_R14:
2003 return "r14";
2004 case UNW_OR1K_R15:
2005 return "r15";
2006 case UNW_OR1K_R16:
2007 return "r16";
2008 case UNW_OR1K_R17:
2009 return "r17";
2010 case UNW_OR1K_R18:
2011 return "r18";
2012 case UNW_OR1K_R19:
2013 return "r19";
2014 case UNW_OR1K_R20:
2015 return "r20";
2016 case UNW_OR1K_R21:
2017 return "r21";
2018 case UNW_OR1K_R22:
2019 return "r22";
2020 case UNW_OR1K_R23:
2021 return "r23";
2022 case UNW_OR1K_R24:
2023 return "r24";
2024 case UNW_OR1K_R25:
2025 return "r25";
2026 case UNW_OR1K_R26:
2027 return "r26";
2028 case UNW_OR1K_R27:
2029 return "r27";
2030 case UNW_OR1K_R28:
2031 return "r28";
2032 case UNW_OR1K_R29:
2033 return "r29";
2034 case UNW_OR1K_R30:
2035 return "r30";
2036 case UNW_OR1K_R31:
2037 return "r31";
2038 default:
2039 return "unknown register";
2040 }
2041
2042}
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +00002043#endif // _LIBUNWIND_TARGET_OR1K
John Baldwin375a3662017-12-12 21:43:36 +00002044
2045#if defined(_LIBUNWIND_TARGET_MIPS_O32)
2046/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2047/// process.
2048class _LIBUNWIND_HIDDEN Registers_mips_o32 {
2049public:
2050 Registers_mips_o32();
2051 Registers_mips_o32(const void *registers);
2052
2053 bool validRegister(int num) const;
2054 uint32_t getRegister(int num) const;
2055 void setRegister(int num, uint32_t value);
2056 bool validFloatRegister(int num) const;
2057 double getFloatRegister(int num) const;
2058 void setFloatRegister(int num, double value);
2059 bool validVectorRegister(int num) const;
2060 v128 getVectorRegister(int num) const;
2061 void setVectorRegister(int num, v128 value);
2062 const char *getRegisterName(int num);
2063 void jumpto();
2064 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
2065
2066 uint32_t getSP() const { return _registers.__r[29]; }
2067 void setSP(uint32_t value) { _registers.__r[29] = value; }
2068 uint32_t getIP() const { return _registers.__pc; }
2069 void setIP(uint32_t value) { _registers.__pc = value; }
2070
2071private:
2072 struct mips_o32_thread_state_t {
2073 uint32_t __r[32];
2074 uint32_t __pc;
2075 uint32_t __hi;
2076 uint32_t __lo;
2077 };
2078
2079 mips_o32_thread_state_t _registers;
2080};
2081
2082inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
2083 static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
2084 "mips_o32 registers do not fit into unw_context_t");
2085 memcpy(&_registers, static_cast<const uint8_t *>(registers),
2086 sizeof(_registers));
2087}
2088
2089inline Registers_mips_o32::Registers_mips_o32() {
2090 memset(&_registers, 0, sizeof(_registers));
2091}
2092
2093inline bool Registers_mips_o32::validRegister(int regNum) const {
2094 if (regNum == UNW_REG_IP)
2095 return true;
2096 if (regNum == UNW_REG_SP)
2097 return true;
2098 if (regNum < 0)
2099 return false;
2100 if (regNum <= UNW_MIPS_R31)
2101 return true;
2102 if (regNum == UNW_MIPS_HI)
2103 return true;
2104 if (regNum == UNW_MIPS_LO)
2105 return true;
2106 // FIXME: Hard float, DSP accumulator registers, MSA registers
2107 return false;
2108}
2109
2110inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
2111 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
2112 return _registers.__r[regNum - UNW_MIPS_R0];
2113
2114 switch (regNum) {
2115 case UNW_REG_IP:
2116 return _registers.__pc;
2117 case UNW_REG_SP:
2118 return _registers.__r[29];
2119 case UNW_MIPS_HI:
2120 return _registers.__hi;
2121 case UNW_MIPS_LO:
2122 return _registers.__lo;
2123 }
2124 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2125}
2126
2127inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
2128 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
2129 _registers.__r[regNum - UNW_MIPS_R0] = value;
2130 return;
2131 }
2132
2133 switch (regNum) {
2134 case UNW_REG_IP:
2135 _registers.__pc = value;
2136 return;
2137 case UNW_REG_SP:
2138 _registers.__r[29] = value;
2139 return;
2140 case UNW_MIPS_HI:
2141 _registers.__hi = value;
2142 return;
2143 case UNW_MIPS_LO:
2144 _registers.__lo = value;
2145 return;
2146 }
2147 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2148}
2149
2150inline bool Registers_mips_o32::validFloatRegister(int /* regNum */) const {
2151 return false;
2152}
2153
2154inline double Registers_mips_o32::getFloatRegister(int /* regNum */) const {
2155 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2156}
2157
2158inline void Registers_mips_o32::setFloatRegister(int /* regNum */,
2159 double /* value */) {
2160 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2161}
2162
2163inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
2164 return false;
2165}
2166
2167inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
2168 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2169}
2170
2171inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
2172 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2173}
2174
2175inline const char *Registers_mips_o32::getRegisterName(int regNum) {
2176 switch (regNum) {
2177 case UNW_MIPS_R0:
2178 return "$0";
2179 case UNW_MIPS_R1:
2180 return "$1";
2181 case UNW_MIPS_R2:
2182 return "$2";
2183 case UNW_MIPS_R3:
2184 return "$3";
2185 case UNW_MIPS_R4:
2186 return "$4";
2187 case UNW_MIPS_R5:
2188 return "$5";
2189 case UNW_MIPS_R6:
2190 return "$6";
2191 case UNW_MIPS_R7:
2192 return "$7";
2193 case UNW_MIPS_R8:
2194 return "$8";
2195 case UNW_MIPS_R9:
2196 return "$9";
2197 case UNW_MIPS_R10:
2198 return "$10";
2199 case UNW_MIPS_R11:
2200 return "$11";
2201 case UNW_MIPS_R12:
2202 return "$12";
2203 case UNW_MIPS_R13:
2204 return "$13";
2205 case UNW_MIPS_R14:
2206 return "$14";
2207 case UNW_MIPS_R15:
2208 return "$15";
2209 case UNW_MIPS_R16:
2210 return "$16";
2211 case UNW_MIPS_R17:
2212 return "$17";
2213 case UNW_MIPS_R18:
2214 return "$18";
2215 case UNW_MIPS_R19:
2216 return "$19";
2217 case UNW_MIPS_R20:
2218 return "$20";
2219 case UNW_MIPS_R21:
2220 return "$21";
2221 case UNW_MIPS_R22:
2222 return "$22";
2223 case UNW_MIPS_R23:
2224 return "$23";
2225 case UNW_MIPS_R24:
2226 return "$24";
2227 case UNW_MIPS_R25:
2228 return "$25";
2229 case UNW_MIPS_R26:
2230 return "$26";
2231 case UNW_MIPS_R27:
2232 return "$27";
2233 case UNW_MIPS_R28:
2234 return "$28";
2235 case UNW_MIPS_R29:
2236 return "$29";
2237 case UNW_MIPS_R30:
2238 return "$30";
2239 case UNW_MIPS_R31:
2240 return "$31";
2241 case UNW_MIPS_HI:
2242 return "$hi";
2243 case UNW_MIPS_LO:
2244 return "$lo";
2245 default:
2246 return "unknown register";
2247 }
2248}
2249#endif // _LIBUNWIND_TARGET_MIPS_O32
2250
2251#if defined(_LIBUNWIND_TARGET_MIPS_N64)
2252/// Registers_mips_n64 holds the register state of a thread in a 64-bit MIPS
2253/// process.
2254class _LIBUNWIND_HIDDEN Registers_mips_n64 {
2255public:
2256 Registers_mips_n64();
2257 Registers_mips_n64(const void *registers);
2258
2259 bool validRegister(int num) const;
2260 uint64_t getRegister(int num) const;
2261 void setRegister(int num, uint64_t value);
2262 bool validFloatRegister(int num) const;
2263 double getFloatRegister(int num) const;
2264 void setFloatRegister(int num, double value);
2265 bool validVectorRegister(int num) const;
2266 v128 getVectorRegister(int num) const;
2267 void setVectorRegister(int num, v128 value);
2268 const char *getRegisterName(int num);
2269 void jumpto();
2270 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
2271
2272 uint64_t getSP() const { return _registers.__r[29]; }
2273 void setSP(uint64_t value) { _registers.__r[29] = value; }
2274 uint64_t getIP() const { return _registers.__pc; }
2275 void setIP(uint64_t value) { _registers.__pc = value; }
2276
2277private:
2278 struct mips_n64_thread_state_t {
2279 uint64_t __r[32];
2280 uint64_t __pc;
2281 uint64_t __hi;
2282 uint64_t __lo;
2283 };
2284
2285 mips_n64_thread_state_t _registers;
2286};
2287
2288inline Registers_mips_n64::Registers_mips_n64(const void *registers) {
2289 static_assert((check_fit<Registers_mips_n64, unw_context_t>::does_fit),
2290 "mips_n64 registers do not fit into unw_context_t");
2291 memcpy(&_registers, static_cast<const uint8_t *>(registers),
2292 sizeof(_registers));
2293}
2294
2295inline Registers_mips_n64::Registers_mips_n64() {
2296 memset(&_registers, 0, sizeof(_registers));
2297}
2298
2299inline bool Registers_mips_n64::validRegister(int regNum) const {
2300 if (regNum == UNW_REG_IP)
2301 return true;
2302 if (regNum == UNW_REG_SP)
2303 return true;
2304 if (regNum < 0)
2305 return false;
2306 if (regNum <= UNW_MIPS_R31)
2307 return true;
2308 if (regNum == UNW_MIPS_HI)
2309 return true;
2310 if (regNum == UNW_MIPS_LO)
2311 return true;
2312 // FIXME: Hard float, DSP accumulator registers, MSA registers
2313 return false;
2314}
2315
2316inline uint64_t Registers_mips_n64::getRegister(int regNum) const {
2317 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
2318 return _registers.__r[regNum - UNW_MIPS_R0];
2319
2320 switch (regNum) {
2321 case UNW_REG_IP:
2322 return _registers.__pc;
2323 case UNW_REG_SP:
2324 return _registers.__r[29];
2325 case UNW_MIPS_HI:
2326 return _registers.__hi;
2327 case UNW_MIPS_LO:
2328 return _registers.__lo;
2329 }
2330 _LIBUNWIND_ABORT("unsupported mips_n64 register");
2331}
2332
2333inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) {
2334 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
2335 _registers.__r[regNum - UNW_MIPS_R0] = value;
2336 return;
2337 }
2338
2339 switch (regNum) {
2340 case UNW_REG_IP:
2341 _registers.__pc = value;
2342 return;
2343 case UNW_REG_SP:
2344 _registers.__r[29] = value;
2345 return;
2346 case UNW_MIPS_HI:
2347 _registers.__hi = value;
2348 return;
2349 case UNW_MIPS_LO:
2350 _registers.__lo = value;
2351 return;
2352 }
2353 _LIBUNWIND_ABORT("unsupported mips_n64 register");
2354}
2355
2356inline bool Registers_mips_n64::validFloatRegister(int /* regNum */) const {
2357 return false;
2358}
2359
2360inline double Registers_mips_n64::getFloatRegister(int /* regNum */) const {
2361 _LIBUNWIND_ABORT("mips_n64 float support not implemented");
2362}
2363
2364inline void Registers_mips_n64::setFloatRegister(int /* regNum */,
2365 double /* value */) {
2366 _LIBUNWIND_ABORT("mips_n64 float support not implemented");
2367}
2368
2369inline bool Registers_mips_n64::validVectorRegister(int /* regNum */) const {
2370 return false;
2371}
2372
2373inline v128 Registers_mips_n64::getVectorRegister(int /* regNum */) const {
2374 _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
2375}
2376
2377inline void Registers_mips_n64::setVectorRegister(int /* regNum */, v128 /* value */) {
2378 _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
2379}
2380
2381inline const char *Registers_mips_n64::getRegisterName(int regNum) {
2382 switch (regNum) {
2383 case UNW_MIPS_R0:
2384 return "$0";
2385 case UNW_MIPS_R1:
2386 return "$1";
2387 case UNW_MIPS_R2:
2388 return "$2";
2389 case UNW_MIPS_R3:
2390 return "$3";
2391 case UNW_MIPS_R4:
2392 return "$4";
2393 case UNW_MIPS_R5:
2394 return "$5";
2395 case UNW_MIPS_R6:
2396 return "$6";
2397 case UNW_MIPS_R7:
2398 return "$7";
2399 case UNW_MIPS_R8:
2400 return "$8";
2401 case UNW_MIPS_R9:
2402 return "$9";
2403 case UNW_MIPS_R10:
2404 return "$10";
2405 case UNW_MIPS_R11:
2406 return "$11";
2407 case UNW_MIPS_R12:
2408 return "$12";
2409 case UNW_MIPS_R13:
2410 return "$13";
2411 case UNW_MIPS_R14:
2412 return "$14";
2413 case UNW_MIPS_R15:
2414 return "$15";
2415 case UNW_MIPS_R16:
2416 return "$16";
2417 case UNW_MIPS_R17:
2418 return "$17";
2419 case UNW_MIPS_R18:
2420 return "$18";
2421 case UNW_MIPS_R19:
2422 return "$19";
2423 case UNW_MIPS_R20:
2424 return "$20";
2425 case UNW_MIPS_R21:
2426 return "$21";
2427 case UNW_MIPS_R22:
2428 return "$22";
2429 case UNW_MIPS_R23:
2430 return "$23";
2431 case UNW_MIPS_R24:
2432 return "$24";
2433 case UNW_MIPS_R25:
2434 return "$25";
2435 case UNW_MIPS_R26:
2436 return "$26";
2437 case UNW_MIPS_R27:
2438 return "$27";
2439 case UNW_MIPS_R28:
2440 return "$28";
2441 case UNW_MIPS_R29:
2442 return "$29";
2443 case UNW_MIPS_R30:
2444 return "$30";
2445 case UNW_MIPS_R31:
2446 return "$31";
2447 case UNW_MIPS_HI:
2448 return "$hi";
2449 case UNW_MIPS_LO:
2450 return "$lo";
2451 default:
2452 return "unknown register";
2453 }
2454}
2455#endif // _LIBUNWIND_TARGET_MIPS_N64
Saleem Abdulrasool675df582015-04-24 19:39:17 +00002456} // namespace libunwind
2457
2458#endif // __REGISTERS_HPP__