1 //===----------------------------- Registers.hpp --------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
9 // Models register sets for supported processors.
11 //===----------------------------------------------------------------------===//
13 #ifndef __REGISTERS_HPP__
14 #define __REGISTERS_HPP__
19 #include "libunwind.h"
24 // For emulating 128-bit registers
25 struct v128 { uint32_t vec[4]; };
28 /// Registers_x86 holds the register state of a thread in a 32-bit intel
30 class _LIBUNWIND_HIDDEN Registers_x86 {
33 Registers_x86(const void *registers);
35 bool validRegister(int num) const;
36 uint32_t getRegister(int num) const;
37 void setRegister(int num, uint32_t value);
38 bool validFloatRegister(int) const { return false; }
39 double getFloatRegister(int num) const;
40 void setFloatRegister(int num, double value);
41 bool validVectorRegister(int) const { return false; }
42 v128 getVectorRegister(int num) const;
43 void setVectorRegister(int num, v128 value);
44 const char *getRegisterName(int num);
47 uint32_t getSP() const { return _registers.__esp; }
48 void setSP(uint32_t value) { _registers.__esp = value; }
49 uint32_t getIP() const { return _registers.__eip; }
50 void setIP(uint32_t value) { _registers.__eip = value; }
51 uint32_t getEBP() const { return _registers.__ebp; }
52 void setEBP(uint32_t value) { _registers.__ebp = value; }
53 uint32_t getEBX() const { return _registers.__ebx; }
54 void setEBX(uint32_t value) { _registers.__ebx = value; }
55 uint32_t getECX() const { return _registers.__ecx; }
56 void setECX(uint32_t value) { _registers.__ecx = value; }
57 uint32_t getEDX() const { return _registers.__edx; }
58 void setEDX(uint32_t value) { _registers.__edx = value; }
59 uint32_t getESI() const { return _registers.__esi; }
60 void setESI(uint32_t value) { _registers.__esi = value; }
61 uint32_t getEDI() const { return _registers.__edi; }
62 void setEDI(uint32_t value) { _registers.__edi = value; }
75 unsigned int __eflags;
87 inline Registers_x86::Registers_x86(const void *registers) {
88 static_assert(sizeof(Registers_x86) < sizeof(unw_context_t),
89 "x86 registers do not fit into unw_context_t");
90 _registers = *((GPRs *)registers);
93 inline Registers_x86::Registers_x86() {
94 bzero(&_registers, sizeof(_registers));
97 inline bool Registers_x86::validRegister(int regNum) const {
98 if (regNum == UNW_REG_IP)
100 if (regNum == UNW_REG_SP)
109 inline uint32_t Registers_x86::getRegister(int regNum) const {
112 return _registers.__eip;
114 return _registers.__esp;
116 return _registers.__eax;
118 return _registers.__ecx;
120 return _registers.__edx;
122 return _registers.__ebx;
124 return _registers.__ebp;
126 return _registers.__esp;
128 return _registers.__esi;
130 return _registers.__edi;
132 _LIBUNWIND_ABORT("unsupported x86 register");
135 inline void Registers_x86::setRegister(int regNum, uint32_t value) {
138 _registers.__eip = value;
141 _registers.__esp = value;
144 _registers.__eax = value;
147 _registers.__ecx = value;
150 _registers.__edx = value;
153 _registers.__ebx = value;
156 _registers.__ebp = value;
159 _registers.__esp = value;
162 _registers.__esi = value;
165 _registers.__edi = value;
168 _LIBUNWIND_ABORT("unsupported x86 register");
171 inline const char *Registers_x86::getRegisterName(int regNum) {
194 return "unknown register";
198 inline double Registers_x86::getFloatRegister(int) const {
199 _LIBUNWIND_ABORT("no x86 float registers");
202 inline void Registers_x86::setFloatRegister(int, double) {
203 _LIBUNWIND_ABORT("no x86 float registers");
206 inline v128 Registers_x86::getVectorRegister(int) const {
207 _LIBUNWIND_ABORT("no x86 vector registers");
210 inline void Registers_x86::setVectorRegister(int, v128) {
211 _LIBUNWIND_ABORT("no x86 vector registers");
215 /// Registers_x86_64 holds the register state of a thread in a 64-bit intel
217 class _LIBUNWIND_HIDDEN Registers_x86_64 {
220 Registers_x86_64(const void *registers);
222 bool validRegister(int num) const;
223 uint64_t getRegister(int num) const;
224 void setRegister(int num, uint64_t value);
225 bool validFloatRegister(int) const { return false; }
226 double getFloatRegister(int num) const;
227 void setFloatRegister(int num, double value);
228 bool validVectorRegister(int) const { return false; }
229 v128 getVectorRegister(int num) const;
230 void setVectorRegister(int num, v128 value);
231 const char *getRegisterName(int num);
234 uint64_t getSP() const { return _registers.__rsp; }
235 void setSP(uint64_t value) { _registers.__rsp = value; }
236 uint64_t getIP() const { return _registers.__rip; }
237 void setIP(uint64_t value) { _registers.__rip = value; }
238 uint64_t getRBP() const { return _registers.__rbp; }
239 void setRBP(uint64_t value) { _registers.__rbp = value; }
240 uint64_t getRBX() const { return _registers.__rbx; }
241 void setRBX(uint64_t value) { _registers.__rbx = value; }
242 uint64_t getR12() const { return _registers.__r12; }
243 void setR12(uint64_t value) { _registers.__r12 = value; }
244 uint64_t getR13() const { return _registers.__r13; }
245 void setR13(uint64_t value) { _registers.__r13 = value; }
246 uint64_t getR14() const { return _registers.__r14; }
247 void setR14(uint64_t value) { _registers.__r14 = value; }
248 uint64_t getR15() const { return _registers.__r15; }
249 void setR15(uint64_t value) { _registers.__r15 = value; }
278 inline Registers_x86_64::Registers_x86_64(const void *registers) {
279 static_assert(sizeof(Registers_x86_64) < sizeof(unw_context_t),
280 "x86_64 registers do not fit into unw_context_t");
281 _registers = *((GPRs *)registers);
284 inline Registers_x86_64::Registers_x86_64() {
285 bzero(&_registers, sizeof(_registers));
288 inline bool Registers_x86_64::validRegister(int regNum) const {
289 if (regNum == UNW_REG_IP)
291 if (regNum == UNW_REG_SP)
300 inline uint64_t Registers_x86_64::getRegister(int regNum) const {
303 return _registers.__rip;
305 return _registers.__rsp;
307 return _registers.__rax;
309 return _registers.__rdx;
311 return _registers.__rcx;
313 return _registers.__rbx;
315 return _registers.__rsi;
317 return _registers.__rdi;
319 return _registers.__rbp;
321 return _registers.__rsp;
323 return _registers.__r8;
325 return _registers.__r9;
327 return _registers.__r10;
329 return _registers.__r11;
331 return _registers.__r12;
333 return _registers.__r13;
335 return _registers.__r14;
337 return _registers.__r15;
339 _LIBUNWIND_ABORT("unsupported x86_64 register");
342 inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
345 _registers.__rip = value;
348 _registers.__rsp = value;
351 _registers.__rax = value;
354 _registers.__rdx = value;
357 _registers.__rcx = value;
360 _registers.__rbx = value;
363 _registers.__rsi = value;
366 _registers.__rdi = value;
369 _registers.__rbp = value;
372 _registers.__rsp = value;
375 _registers.__r8 = value;
378 _registers.__r9 = value;
381 _registers.__r10 = value;
384 _registers.__r11 = value;
387 _registers.__r12 = value;
390 _registers.__r13 = value;
393 _registers.__r14 = value;
396 _registers.__r15 = value;
399 _LIBUNWIND_ABORT("unsupported x86_64 register");
402 inline const char *Registers_x86_64::getRegisterName(int regNum) {
441 return "unknown register";
445 inline double Registers_x86_64::getFloatRegister(int) const {
446 _LIBUNWIND_ABORT("no x86_64 float registers");
449 inline void Registers_x86_64::setFloatRegister(int, double) {
450 _LIBUNWIND_ABORT("no x86_64 float registers");
453 inline v128 Registers_x86_64::getVectorRegister(int) const {
454 _LIBUNWIND_ABORT("no x86_64 vector registers");
457 inline void Registers_x86_64::setVectorRegister(int, v128) {
458 _LIBUNWIND_ABORT("no x86_64 vector registers");
462 /// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
464 class _LIBUNWIND_HIDDEN Registers_ppc {
467 Registers_ppc(const void *registers);
469 bool validRegister(int num) const;
470 uint32_t getRegister(int num) const;
471 void setRegister(int num, uint32_t value);
472 bool validFloatRegister(int num) const;
473 double getFloatRegister(int num) const;
474 void setFloatRegister(int num, double value);
475 bool validVectorRegister(int num) const;
476 v128 getVectorRegister(int num) const;
477 void setVectorRegister(int num, v128 value);
478 const char *getRegisterName(int num);
481 uint64_t getSP() const { return _registers.__r1; }
482 void setSP(uint32_t value) { _registers.__r1 = value; }
483 uint64_t getIP() const { return _registers.__srr0; }
484 void setIP(uint32_t value) { _registers.__srr0 = value; }
487 struct ppc_thread_state_t {
488 unsigned int __srr0; /* Instruction address register (PC) */
489 unsigned int __srr1; /* Machine state register (supervisor) */
522 unsigned int __cr; /* Condition register */
523 unsigned int __xer; /* User's integer exception register */
524 unsigned int __lr; /* Link register */
525 unsigned int __ctr; /* Count register */
526 unsigned int __mq; /* MQ register (601 only) */
527 unsigned int __vrsave; /* Vector Save Register */
530 struct ppc_float_state_t {
533 unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
534 unsigned int __fpscr; /* floating point status register */
537 ppc_thread_state_t _registers;
538 ppc_float_state_t _floatRegisters;
539 v128 _vectorRegisters[32]; // offset 424
542 inline Registers_ppc::Registers_ppc(const void *registers) {
543 static_assert(sizeof(Registers_ppc) < sizeof(unw_context_t),
544 "ppc registers do not fit into unw_context_t");
545 _registers = *((ppc_thread_state_t *)registers);
546 _floatRegisters = *((ppc_float_state_t *)((char *)registers + 160));
547 memcpy(_vectorRegisters, ((char *)registers + 424), sizeof(_vectorRegisters));
550 inline Registers_ppc::Registers_ppc() {
551 bzero(&_registers, sizeof(_registers));
552 bzero(&_floatRegisters, sizeof(_floatRegisters));
553 bzero(&_vectorRegisters, sizeof(_vectorRegisters));
556 inline bool Registers_ppc::validRegister(int regNum) const {
557 if (regNum == UNW_REG_IP)
559 if (regNum == UNW_REG_SP)
561 if (regNum == UNW_PPC_VRSAVE)
565 if (regNum <= UNW_PPC_R31)
567 if (regNum == UNW_PPC_MQ)
569 if (regNum == UNW_PPC_LR)
571 if (regNum == UNW_PPC_CTR)
573 if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
578 inline uint32_t Registers_ppc::getRegister(int regNum) const {
581 return _registers.__srr0;
583 return _registers.__r1;
585 return _registers.__r0;
587 return _registers.__r1;
589 return _registers.__r2;
591 return _registers.__r3;
593 return _registers.__r4;
595 return _registers.__r5;
597 return _registers.__r6;
599 return _registers.__r7;
601 return _registers.__r8;
603 return _registers.__r9;
605 return _registers.__r10;
607 return _registers.__r11;
609 return _registers.__r12;
611 return _registers.__r13;
613 return _registers.__r14;
615 return _registers.__r15;
617 return _registers.__r16;
619 return _registers.__r17;
621 return _registers.__r18;
623 return _registers.__r19;
625 return _registers.__r20;
627 return _registers.__r21;
629 return _registers.__r22;
631 return _registers.__r23;
633 return _registers.__r24;
635 return _registers.__r25;
637 return _registers.__r26;
639 return _registers.__r27;
641 return _registers.__r28;
643 return _registers.__r29;
645 return _registers.__r30;
647 return _registers.__r31;
649 return _registers.__lr;
651 return (_registers.__cr & 0xF0000000);
653 return (_registers.__cr & 0x0F000000);
655 return (_registers.__cr & 0x00F00000);
657 return (_registers.__cr & 0x000F0000);
659 return (_registers.__cr & 0x0000F000);
661 return (_registers.__cr & 0x00000F00);
663 return (_registers.__cr & 0x000000F0);
665 return (_registers.__cr & 0x0000000F);
667 return _registers.__vrsave;
669 _LIBUNWIND_ABORT("unsupported ppc register");
672 inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
673 //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
676 _registers.__srr0 = value;
679 _registers.__r1 = value;
682 _registers.__r0 = value;
685 _registers.__r1 = value;
688 _registers.__r2 = value;
691 _registers.__r3 = value;
694 _registers.__r4 = value;
697 _registers.__r5 = value;
700 _registers.__r6 = value;
703 _registers.__r7 = value;
706 _registers.__r8 = value;
709 _registers.__r9 = value;
712 _registers.__r10 = value;
715 _registers.__r11 = value;
718 _registers.__r12 = value;
721 _registers.__r13 = value;
724 _registers.__r14 = value;
727 _registers.__r15 = value;
730 _registers.__r16 = value;
733 _registers.__r17 = value;
736 _registers.__r18 = value;
739 _registers.__r19 = value;
742 _registers.__r20 = value;
745 _registers.__r21 = value;
748 _registers.__r22 = value;
751 _registers.__r23 = value;
754 _registers.__r24 = value;
757 _registers.__r25 = value;
760 _registers.__r26 = value;
763 _registers.__r27 = value;
766 _registers.__r28 = value;
769 _registers.__r29 = value;
772 _registers.__r30 = value;
775 _registers.__r31 = value;
778 _registers.__mq = value;
781 _registers.__lr = value;
784 _registers.__ctr = value;
787 _registers.__cr &= 0x0FFFFFFF;
788 _registers.__cr |= (value & 0xF0000000);
791 _registers.__cr &= 0xF0FFFFFF;
792 _registers.__cr |= (value & 0x0F000000);
795 _registers.__cr &= 0xFF0FFFFF;
796 _registers.__cr |= (value & 0x00F00000);
799 _registers.__cr &= 0xFFF0FFFF;
800 _registers.__cr |= (value & 0x000F0000);
803 _registers.__cr &= 0xFFFF0FFF;
804 _registers.__cr |= (value & 0x0000F000);
807 _registers.__cr &= 0xFFFFF0FF;
808 _registers.__cr |= (value & 0x00000F00);
811 _registers.__cr &= 0xFFFFFF0F;
812 _registers.__cr |= (value & 0x000000F0);
815 _registers.__cr &= 0xFFFFFFF0;
816 _registers.__cr |= (value & 0x0000000F);
819 _registers.__vrsave = value;
824 _registers.__xer = value;
828 case UNW_PPC_SPEFSCR:
832 _LIBUNWIND_ABORT("unsupported ppc register");
835 inline bool Registers_ppc::validFloatRegister(int regNum) const {
836 if (regNum < UNW_PPC_F0)
838 if (regNum > UNW_PPC_F31)
843 inline double Registers_ppc::getFloatRegister(int regNum) const {
844 assert(validFloatRegister(regNum));
845 return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
848 inline void Registers_ppc::setFloatRegister(int regNum, double value) {
849 assert(validFloatRegister(regNum));
850 _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
853 inline bool Registers_ppc::validVectorRegister(int regNum) const {
854 if (regNum < UNW_PPC_V0)
856 if (regNum > UNW_PPC_V31)
861 inline v128 Registers_ppc::getVectorRegister(int regNum) const {
862 assert(validVectorRegister(regNum));
863 v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
867 inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
868 assert(validVectorRegister(regNum));
869 _vectorRegisters[regNum - UNW_PPC_V0] = value;
872 inline const char *Registers_ppc::getRegisterName(int regNum) {
1009 return "unknown register";
1015 /// Registers_arm64 holds the register state of a thread in a 64-bit arm
1017 class _LIBUNWIND_HIDDEN Registers_arm64 {
1020 Registers_arm64(const void *registers);
1022 bool validRegister(int num) const;
1023 uint64_t getRegister(int num) const;
1024 void setRegister(int num, uint64_t value);
1025 bool validFloatRegister(int num) const;
1026 double getFloatRegister(int num) const;
1027 void setFloatRegister(int num, double value);
1028 bool validVectorRegister(int num) const;
1029 v128 getVectorRegister(int num) const;
1030 void setVectorRegister(int num, v128 value);
1031 const char *getRegisterName(int num);
1034 uint64_t getSP() const { return _registers.__sp; }
1035 void setSP(uint64_t value) { _registers.__sp = value; }
1036 uint64_t getIP() const { return _registers.__pc; }
1037 void setIP(uint64_t value) { _registers.__pc = value; }
1038 uint64_t getFP() const { return _registers.__fp; }
1039 void setFP(uint64_t value) { _registers.__fp = value; }
1043 uint64_t __x[29]; // x0-x28
1044 uint64_t __fp; // Frame pointer x29
1045 uint64_t __lr; // Link register x30
1046 uint64_t __sp; // Stack pointer x31
1047 uint64_t __pc; // Program counter
1048 uint64_t padding; // 16-byte align
1052 double _vectorHalfRegisters[32];
1053 // Currently only the lower double in 128-bit vectore registers
1054 // is perserved during unwinding. We could define new register
1055 // numbers (> 96) which mean whole vector registers, then this
1056 // struct would need to change to contain whole vector registers.
1059 inline Registers_arm64::Registers_arm64(const void *registers) {
1060 static_assert(sizeof(Registers_arm64) < sizeof(unw_context_t),
1061 "arm64 registers do not fit into unw_context_t");
1062 memcpy(&_registers, registers, sizeof(_registers));
1063 memcpy(_vectorHalfRegisters, (((char *)registers) + 0x110),
1064 sizeof(_vectorHalfRegisters));
1067 inline Registers_arm64::Registers_arm64() {
1068 bzero(&_registers, sizeof(_registers));
1069 bzero(&_vectorHalfRegisters, sizeof(_vectorHalfRegisters));
1072 inline bool Registers_arm64::validRegister(int regNum) const {
1073 if (regNum == UNW_REG_IP)
1075 if (regNum == UNW_REG_SP)
1081 if ((regNum > 31) && (regNum < 64))
1086 inline uint64_t Registers_arm64::getRegister(int regNum) const {
1087 if (regNum == UNW_REG_IP)
1088 return _registers.__pc;
1089 if (regNum == UNW_REG_SP)
1090 return _registers.__sp;
1091 if ((regNum >= 0) && (regNum < 32))
1092 return _registers.__x[regNum];
1093 _LIBUNWIND_ABORT("unsupported arm64 register");
1096 inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1097 if (regNum == UNW_REG_IP)
1098 _registers.__pc = value;
1099 else if (regNum == UNW_REG_SP)
1100 _registers.__sp = value;
1101 else if ((regNum >= 0) && (regNum < 32))
1102 _registers.__x[regNum] = value;
1104 _LIBUNWIND_ABORT("unsupported arm64 register");
1107 inline const char *Registers_arm64::getRegisterName(int regNum) {
1242 return "unknown register";
1246 inline bool Registers_arm64::validFloatRegister(int regNum) const {
1247 if (regNum < UNW_ARM64_D0)
1249 if (regNum > UNW_ARM64_D31)
1254 inline double Registers_arm64::getFloatRegister(int regNum) const {
1255 assert(validFloatRegister(regNum));
1256 return _vectorHalfRegisters[regNum - UNW_ARM64_D0];
1259 inline void Registers_arm64::setFloatRegister(int regNum, double value) {
1260 assert(validFloatRegister(regNum));
1261 _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value;
1264 inline bool Registers_arm64::validVectorRegister(int) const {
1268 inline v128 Registers_arm64::getVectorRegister(int) const {
1269 _LIBUNWIND_ABORT("no arm64 vector register support yet");
1272 inline void Registers_arm64::setVectorRegister(int, v128) {
1273 _LIBUNWIND_ABORT("no arm64 vector register support yet");
1276 /// Registers_arm holds the register state of a thread in a 32-bit arm
1279 /// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
1280 /// this uses more memory than required.
1282 /// FIXME: Support MMX Data Registers, Control registers, and load/stores
1283 /// for different representations in the VFP registers as listed in
1284 /// Table 1 of EHABI #7.5.2
1285 class _LIBUNWIND_HIDDEN Registers_arm {
1288 Registers_arm(const void *registers);
1290 bool validRegister(int num) const;
1291 uint32_t getRegister(int num) const;
1292 void setRegister(int num, uint32_t value);
1293 // FIXME: Due to ARM VRS's support for reading/writing different
1294 // representations into the VFP registers this set of accessors seem wrong.
1295 // If {get,set}FloatRegister() is the backing store for
1296 // _Unwind_VRS_{Get,Set} then it might be best to return a tagged union
1297 // with types for each representation in _Unwind_VRS_DataRepresentation.
1298 // Similarly, unw_{get,set}_fpreg in the public libunwind API may want to
1299 // use a similar tagged union to back the unw_fpreg_t output parameter type.
1300 bool validFloatRegister(int num) const;
1301 unw_fpreg_t getFloatRegister(int num) const;
1302 void setFloatRegister(int num, unw_fpreg_t value);
1303 bool validVectorRegister(int num) const;
1304 v128 getVectorRegister(int num) const;
1305 void setVectorRegister(int num, v128 value);
1306 const char *getRegisterName(int num);
1309 uint32_t getSP() const { return _registers.__sp; }
1310 void setSP(uint32_t value) { _registers.__sp = value; }
1311 uint32_t getIP() const { return _registers.__pc; }
1312 void setIP(uint32_t value) { _registers.__pc = value; }
1316 uint32_t __r[13]; // r0-r12
1317 uint32_t __sp; // Stack pointer r13
1318 uint32_t __lr; // Link register r14
1319 uint32_t __pc; // Program counter r15
1325 inline Registers_arm::Registers_arm(const void *registers) {
1326 static_assert(sizeof(Registers_arm) < sizeof(unw_context_t),
1327 "arm registers do not fit into unw_context_t");
1328 memcpy(&_registers, registers, sizeof(_registers));
1331 inline Registers_arm::Registers_arm() {
1332 bzero(&_registers, sizeof(_registers));
1335 inline bool Registers_arm::validRegister(int regNum) const {
1336 // Returns true for all non-VFP registers supported by the EHABI
1337 // virtual register set (VRS).
1338 if (regNum == UNW_REG_IP)
1340 if (regNum == UNW_REG_SP)
1342 if ((regNum >= UNW_ARM_R0) && (regNum <= UNW_ARM_R15))
1347 inline uint32_t Registers_arm::getRegister(int regNum) const {
1348 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
1349 return _registers.__sp;
1350 if (regNum == UNW_ARM_LR)
1351 return _registers.__lr;
1352 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
1353 return _registers.__pc;
1354 if ((regNum >= UNW_ARM_R0) && (regNum <= UNW_ARM_R12))
1355 return _registers.__r[regNum];
1356 _LIBUNWIND_ABORT("unsupported arm register");
1359 inline void Registers_arm::setRegister(int regNum, uint32_t value) {
1360 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
1361 _registers.__sp = value;
1362 else if (regNum == UNW_ARM_LR)
1363 _registers.__lr = value;
1364 else if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
1365 _registers.__pc = value;
1366 else if ((regNum >= UNW_ARM_R0) && (regNum <= UNW_ARM_R12))
1367 _registers.__r[regNum] = value;
1369 _LIBUNWIND_ABORT("unsupported arm register");
1372 inline const char *Registers_arm::getRegisterName(int regNum) {
1375 case UNW_ARM_IP: // UNW_ARM_R15 is alias
1377 case UNW_ARM_LR: // UNW_ARM_R14 is alias
1380 case UNW_ARM_SP: // UNW_ARM_R13 is alias
1537 return "unknown register";
1541 inline bool Registers_arm::validFloatRegister(int) const {
1542 // FIXME: Implement float register support.
1546 inline unw_fpreg_t Registers_arm::getFloatRegister(int) const {
1547 _LIBUNWIND_ABORT("ARM float register support not yet implemented");
1550 inline void Registers_arm::setFloatRegister(int, unw_fpreg_t) {
1551 _LIBUNWIND_ABORT("ARM float register support not yet implemented");
1554 inline bool Registers_arm::validVectorRegister(int) const {
1558 inline v128 Registers_arm::getVectorRegister(int) const {
1559 _LIBUNWIND_ABORT("ARM vector support not implemented");
1562 inline void Registers_arm::setVectorRegister(int, v128) {
1563 _LIBUNWIND_ABORT("ARM vector support not implemented");
1566 } // namespace libunwind
1568 #endif // __REGISTERS_HPP__