1349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric // Models register sets for supported processors.
90b57cec5SDimitry Andric //
100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
110b57cec5SDimitry Andric
120b57cec5SDimitry Andric #ifndef __REGISTERS_HPP__
130b57cec5SDimitry Andric #define __REGISTERS_HPP__
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include <stdint.h>
160b57cec5SDimitry Andric #include <string.h>
170b57cec5SDimitry Andric
18349cc55cSDimitry Andric #include "cet_unwind.h"
190b57cec5SDimitry Andric #include "config.h"
20349cc55cSDimitry Andric #include "libunwind.h"
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric namespace libunwind {
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric // For emulating 128-bit registers
250b57cec5SDimitry Andric struct v128 { uint32_t vec[4]; };
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric enum {
280b57cec5SDimitry Andric REGISTERS_X86,
290b57cec5SDimitry Andric REGISTERS_X86_64,
300b57cec5SDimitry Andric REGISTERS_PPC,
310b57cec5SDimitry Andric REGISTERS_PPC64,
320b57cec5SDimitry Andric REGISTERS_ARM64,
330b57cec5SDimitry Andric REGISTERS_ARM,
340b57cec5SDimitry Andric REGISTERS_OR1K,
350b57cec5SDimitry Andric REGISTERS_MIPS_O32,
360b57cec5SDimitry Andric REGISTERS_MIPS_NEWABI,
370b57cec5SDimitry Andric REGISTERS_SPARC,
38d56accc7SDimitry Andric REGISTERS_SPARC64,
395ffd83dbSDimitry Andric REGISTERS_HEXAGON,
40480093f4SDimitry Andric REGISTERS_RISCV,
41e8d8bef9SDimitry Andric REGISTERS_VE,
4281ad6265SDimitry Andric REGISTERS_S390X,
43bdd1243dSDimitry Andric REGISTERS_LOONGARCH,
440b57cec5SDimitry Andric };
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_I386)
47e8d8bef9SDimitry Andric class _LIBUNWIND_HIDDEN Registers_x86;
48e8d8bef9SDimitry Andric extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
49349cc55cSDimitry Andric
50349cc55cSDimitry Andric #if defined(_LIBUNWIND_USE_CET)
__libunwind_cet_get_jump_target()51349cc55cSDimitry Andric extern "C" void *__libunwind_cet_get_jump_target() {
52349cc55cSDimitry Andric return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto);
53349cc55cSDimitry Andric }
54349cc55cSDimitry Andric #endif
55349cc55cSDimitry Andric
560b57cec5SDimitry Andric /// Registers_x86 holds the register state of a thread in a 32-bit intel
570b57cec5SDimitry Andric /// process.
580b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_x86 {
590b57cec5SDimitry Andric public:
600b57cec5SDimitry Andric Registers_x86();
610b57cec5SDimitry Andric Registers_x86(const void *registers);
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric bool validRegister(int num) const;
640b57cec5SDimitry Andric uint32_t getRegister(int num) const;
650b57cec5SDimitry Andric void setRegister(int num, uint32_t value);
validFloatRegister(int) const660b57cec5SDimitry Andric bool validFloatRegister(int) const { return false; }
670b57cec5SDimitry Andric double getFloatRegister(int num) const;
680b57cec5SDimitry Andric void setFloatRegister(int num, double value);
validVectorRegister(int) const690b57cec5SDimitry Andric bool validVectorRegister(int) const { return false; }
700b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
710b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
720b57cec5SDimitry Andric static const char *getRegisterName(int num);
jumpto()73e8d8bef9SDimitry Andric void jumpto() { __libunwind_Registers_x86_jumpto(this); }
lastDwarfRegNum()7481ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
7581ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86;
7681ad6265SDimitry Andric }
getArch()770b57cec5SDimitry Andric static int getArch() { return REGISTERS_X86; }
780b57cec5SDimitry Andric
getSP() const790b57cec5SDimitry Andric uint32_t getSP() const { return _registers.__esp; }
setSP(uint32_t value)800b57cec5SDimitry Andric void setSP(uint32_t value) { _registers.__esp = value; }
getIP() const810b57cec5SDimitry Andric uint32_t getIP() const { return _registers.__eip; }
setIP(uint32_t value)820b57cec5SDimitry Andric void setIP(uint32_t value) { _registers.__eip = value; }
getEBP() const830b57cec5SDimitry Andric uint32_t getEBP() const { return _registers.__ebp; }
setEBP(uint32_t value)840b57cec5SDimitry Andric void setEBP(uint32_t value) { _registers.__ebp = value; }
getEBX() const850b57cec5SDimitry Andric uint32_t getEBX() const { return _registers.__ebx; }
setEBX(uint32_t value)860b57cec5SDimitry Andric void setEBX(uint32_t value) { _registers.__ebx = value; }
getECX() const870b57cec5SDimitry Andric uint32_t getECX() const { return _registers.__ecx; }
setECX(uint32_t value)880b57cec5SDimitry Andric void setECX(uint32_t value) { _registers.__ecx = value; }
getEDX() const890b57cec5SDimitry Andric uint32_t getEDX() const { return _registers.__edx; }
setEDX(uint32_t value)900b57cec5SDimitry Andric void setEDX(uint32_t value) { _registers.__edx = value; }
getESI() const910b57cec5SDimitry Andric uint32_t getESI() const { return _registers.__esi; }
setESI(uint32_t value)920b57cec5SDimitry Andric void setESI(uint32_t value) { _registers.__esi = value; }
getEDI() const930b57cec5SDimitry Andric uint32_t getEDI() const { return _registers.__edi; }
setEDI(uint32_t value)940b57cec5SDimitry Andric void setEDI(uint32_t value) { _registers.__edi = value; }
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric private:
970b57cec5SDimitry Andric struct GPRs {
980b57cec5SDimitry Andric unsigned int __eax;
990b57cec5SDimitry Andric unsigned int __ebx;
1000b57cec5SDimitry Andric unsigned int __ecx;
1010b57cec5SDimitry Andric unsigned int __edx;
1020b57cec5SDimitry Andric unsigned int __edi;
1030b57cec5SDimitry Andric unsigned int __esi;
1040b57cec5SDimitry Andric unsigned int __ebp;
1050b57cec5SDimitry Andric unsigned int __esp;
1060b57cec5SDimitry Andric unsigned int __ss;
1070b57cec5SDimitry Andric unsigned int __eflags;
1080b57cec5SDimitry Andric unsigned int __eip;
1090b57cec5SDimitry Andric unsigned int __cs;
1100b57cec5SDimitry Andric unsigned int __ds;
1110b57cec5SDimitry Andric unsigned int __es;
1120b57cec5SDimitry Andric unsigned int __fs;
1130b57cec5SDimitry Andric unsigned int __gs;
1140b57cec5SDimitry Andric };
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric GPRs _registers;
1170b57cec5SDimitry Andric };
1180b57cec5SDimitry Andric
Registers_x86(const void * registers)1190b57cec5SDimitry Andric inline Registers_x86::Registers_x86(const void *registers) {
1200b57cec5SDimitry Andric static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
1210b57cec5SDimitry Andric "x86 registers do not fit into unw_context_t");
1220b57cec5SDimitry Andric memcpy(&_registers, registers, sizeof(_registers));
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric
Registers_x86()1250b57cec5SDimitry Andric inline Registers_x86::Registers_x86() {
1260b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric
validRegister(int regNum) const1290b57cec5SDimitry Andric inline bool Registers_x86::validRegister(int regNum) const {
1300b57cec5SDimitry Andric if (regNum == UNW_REG_IP)
1310b57cec5SDimitry Andric return true;
1320b57cec5SDimitry Andric if (regNum == UNW_REG_SP)
1330b57cec5SDimitry Andric return true;
1340b57cec5SDimitry Andric if (regNum < 0)
1350b57cec5SDimitry Andric return false;
1360b57cec5SDimitry Andric if (regNum > 7)
1370b57cec5SDimitry Andric return false;
1380b57cec5SDimitry Andric return true;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric
getRegister(int regNum) const1410b57cec5SDimitry Andric inline uint32_t Registers_x86::getRegister(int regNum) const {
1420b57cec5SDimitry Andric switch (regNum) {
1430b57cec5SDimitry Andric case UNW_REG_IP:
1440b57cec5SDimitry Andric return _registers.__eip;
1450b57cec5SDimitry Andric case UNW_REG_SP:
1460b57cec5SDimitry Andric return _registers.__esp;
1470b57cec5SDimitry Andric case UNW_X86_EAX:
1480b57cec5SDimitry Andric return _registers.__eax;
1490b57cec5SDimitry Andric case UNW_X86_ECX:
1500b57cec5SDimitry Andric return _registers.__ecx;
1510b57cec5SDimitry Andric case UNW_X86_EDX:
1520b57cec5SDimitry Andric return _registers.__edx;
1530b57cec5SDimitry Andric case UNW_X86_EBX:
1540b57cec5SDimitry Andric return _registers.__ebx;
1550b57cec5SDimitry Andric #if !defined(__APPLE__)
1560b57cec5SDimitry Andric case UNW_X86_ESP:
1570b57cec5SDimitry Andric #else
1580b57cec5SDimitry Andric case UNW_X86_EBP:
1590b57cec5SDimitry Andric #endif
1600b57cec5SDimitry Andric return _registers.__ebp;
1610b57cec5SDimitry Andric #if !defined(__APPLE__)
1620b57cec5SDimitry Andric case UNW_X86_EBP:
1630b57cec5SDimitry Andric #else
1640b57cec5SDimitry Andric case UNW_X86_ESP:
1650b57cec5SDimitry Andric #endif
1660b57cec5SDimitry Andric return _registers.__esp;
1670b57cec5SDimitry Andric case UNW_X86_ESI:
1680b57cec5SDimitry Andric return _registers.__esi;
1690b57cec5SDimitry Andric case UNW_X86_EDI:
1700b57cec5SDimitry Andric return _registers.__edi;
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported x86 register");
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
setRegister(int regNum,uint32_t value)1750b57cec5SDimitry Andric inline void Registers_x86::setRegister(int regNum, uint32_t value) {
1760b57cec5SDimitry Andric switch (regNum) {
1770b57cec5SDimitry Andric case UNW_REG_IP:
1780b57cec5SDimitry Andric _registers.__eip = value;
1790b57cec5SDimitry Andric return;
1800b57cec5SDimitry Andric case UNW_REG_SP:
1810b57cec5SDimitry Andric _registers.__esp = value;
1820b57cec5SDimitry Andric return;
1830b57cec5SDimitry Andric case UNW_X86_EAX:
1840b57cec5SDimitry Andric _registers.__eax = value;
1850b57cec5SDimitry Andric return;
1860b57cec5SDimitry Andric case UNW_X86_ECX:
1870b57cec5SDimitry Andric _registers.__ecx = value;
1880b57cec5SDimitry Andric return;
1890b57cec5SDimitry Andric case UNW_X86_EDX:
1900b57cec5SDimitry Andric _registers.__edx = value;
1910b57cec5SDimitry Andric return;
1920b57cec5SDimitry Andric case UNW_X86_EBX:
1930b57cec5SDimitry Andric _registers.__ebx = value;
1940b57cec5SDimitry Andric return;
1950b57cec5SDimitry Andric #if !defined(__APPLE__)
1960b57cec5SDimitry Andric case UNW_X86_ESP:
1970b57cec5SDimitry Andric #else
1980b57cec5SDimitry Andric case UNW_X86_EBP:
1990b57cec5SDimitry Andric #endif
2000b57cec5SDimitry Andric _registers.__ebp = value;
2010b57cec5SDimitry Andric return;
2020b57cec5SDimitry Andric #if !defined(__APPLE__)
2030b57cec5SDimitry Andric case UNW_X86_EBP:
2040b57cec5SDimitry Andric #else
2050b57cec5SDimitry Andric case UNW_X86_ESP:
2060b57cec5SDimitry Andric #endif
2070b57cec5SDimitry Andric _registers.__esp = value;
2080b57cec5SDimitry Andric return;
2090b57cec5SDimitry Andric case UNW_X86_ESI:
2100b57cec5SDimitry Andric _registers.__esi = value;
2110b57cec5SDimitry Andric return;
2120b57cec5SDimitry Andric case UNW_X86_EDI:
2130b57cec5SDimitry Andric _registers.__edi = value;
2140b57cec5SDimitry Andric return;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported x86 register");
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric
getRegisterName(int regNum)2190b57cec5SDimitry Andric inline const char *Registers_x86::getRegisterName(int regNum) {
2200b57cec5SDimitry Andric switch (regNum) {
2210b57cec5SDimitry Andric case UNW_REG_IP:
2220b57cec5SDimitry Andric return "ip";
2230b57cec5SDimitry Andric case UNW_REG_SP:
2240b57cec5SDimitry Andric return "esp";
2250b57cec5SDimitry Andric case UNW_X86_EAX:
2260b57cec5SDimitry Andric return "eax";
2270b57cec5SDimitry Andric case UNW_X86_ECX:
2280b57cec5SDimitry Andric return "ecx";
2290b57cec5SDimitry Andric case UNW_X86_EDX:
2300b57cec5SDimitry Andric return "edx";
2310b57cec5SDimitry Andric case UNW_X86_EBX:
2320b57cec5SDimitry Andric return "ebx";
2330b57cec5SDimitry Andric case UNW_X86_EBP:
2340b57cec5SDimitry Andric return "ebp";
2350b57cec5SDimitry Andric case UNW_X86_ESP:
2360b57cec5SDimitry Andric return "esp";
2370b57cec5SDimitry Andric case UNW_X86_ESI:
2380b57cec5SDimitry Andric return "esi";
2390b57cec5SDimitry Andric case UNW_X86_EDI:
2400b57cec5SDimitry Andric return "edi";
2410b57cec5SDimitry Andric default:
2420b57cec5SDimitry Andric return "unknown register";
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
getFloatRegister(int) const2460b57cec5SDimitry Andric inline double Registers_x86::getFloatRegister(int) const {
2470b57cec5SDimitry Andric _LIBUNWIND_ABORT("no x86 float registers");
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric
setFloatRegister(int,double)2500b57cec5SDimitry Andric inline void Registers_x86::setFloatRegister(int, double) {
2510b57cec5SDimitry Andric _LIBUNWIND_ABORT("no x86 float registers");
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric
getVectorRegister(int) const2540b57cec5SDimitry Andric inline v128 Registers_x86::getVectorRegister(int) const {
2550b57cec5SDimitry Andric _LIBUNWIND_ABORT("no x86 vector registers");
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric
setVectorRegister(int,v128)2580b57cec5SDimitry Andric inline void Registers_x86::setVectorRegister(int, v128) {
2590b57cec5SDimitry Andric _LIBUNWIND_ABORT("no x86 vector registers");
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_I386
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric
2640b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_X86_64)
2650b57cec5SDimitry Andric /// Registers_x86_64 holds the register state of a thread in a 64-bit intel
2660b57cec5SDimitry Andric /// process.
267e8d8bef9SDimitry Andric class _LIBUNWIND_HIDDEN Registers_x86_64;
268e8d8bef9SDimitry Andric extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
269349cc55cSDimitry Andric
270349cc55cSDimitry Andric #if defined(_LIBUNWIND_USE_CET)
__libunwind_cet_get_jump_target()271349cc55cSDimitry Andric extern "C" void *__libunwind_cet_get_jump_target() {
272349cc55cSDimitry Andric return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto);
273349cc55cSDimitry Andric }
274349cc55cSDimitry Andric #endif
275349cc55cSDimitry Andric
2760b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_x86_64 {
2770b57cec5SDimitry Andric public:
2780b57cec5SDimitry Andric Registers_x86_64();
2790b57cec5SDimitry Andric Registers_x86_64(const void *registers);
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andric bool validRegister(int num) const;
2820b57cec5SDimitry Andric uint64_t getRegister(int num) const;
2830b57cec5SDimitry Andric void setRegister(int num, uint64_t value);
validFloatRegister(int) const2840b57cec5SDimitry Andric bool validFloatRegister(int) const { return false; }
2850b57cec5SDimitry Andric double getFloatRegister(int num) const;
2860b57cec5SDimitry Andric void setFloatRegister(int num, double value);
2870b57cec5SDimitry Andric bool validVectorRegister(int) const;
2880b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
2890b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
2900b57cec5SDimitry Andric static const char *getRegisterName(int num);
jumpto()291e8d8bef9SDimitry Andric void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }
lastDwarfRegNum()29281ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
29381ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64;
29481ad6265SDimitry Andric }
getArch()2950b57cec5SDimitry Andric static int getArch() { return REGISTERS_X86_64; }
2960b57cec5SDimitry Andric
getSP() const2970b57cec5SDimitry Andric uint64_t getSP() const { return _registers.__rsp; }
setSP(uint64_t value)2980b57cec5SDimitry Andric void setSP(uint64_t value) { _registers.__rsp = value; }
getIP() const2990b57cec5SDimitry Andric uint64_t getIP() const { return _registers.__rip; }
setIP(uint64_t value)3000b57cec5SDimitry Andric void setIP(uint64_t value) { _registers.__rip = value; }
getRBP() const3010b57cec5SDimitry Andric uint64_t getRBP() const { return _registers.__rbp; }
setRBP(uint64_t value)3020b57cec5SDimitry Andric void setRBP(uint64_t value) { _registers.__rbp = value; }
getRBX() const3030b57cec5SDimitry Andric uint64_t getRBX() const { return _registers.__rbx; }
setRBX(uint64_t value)3040b57cec5SDimitry Andric void setRBX(uint64_t value) { _registers.__rbx = value; }
getR12() const3050b57cec5SDimitry Andric uint64_t getR12() const { return _registers.__r12; }
setR12(uint64_t value)3060b57cec5SDimitry Andric void setR12(uint64_t value) { _registers.__r12 = value; }
getR13() const3070b57cec5SDimitry Andric uint64_t getR13() const { return _registers.__r13; }
setR13(uint64_t value)3080b57cec5SDimitry Andric void setR13(uint64_t value) { _registers.__r13 = value; }
getR14() const3090b57cec5SDimitry Andric uint64_t getR14() const { return _registers.__r14; }
setR14(uint64_t value)3100b57cec5SDimitry Andric void setR14(uint64_t value) { _registers.__r14 = value; }
getR15() const3110b57cec5SDimitry Andric uint64_t getR15() const { return _registers.__r15; }
setR15(uint64_t value)3120b57cec5SDimitry Andric void setR15(uint64_t value) { _registers.__r15 = value; }
3130b57cec5SDimitry Andric
3140b57cec5SDimitry Andric private:
3150b57cec5SDimitry Andric struct GPRs {
3160b57cec5SDimitry Andric uint64_t __rax;
3170b57cec5SDimitry Andric uint64_t __rbx;
3180b57cec5SDimitry Andric uint64_t __rcx;
3190b57cec5SDimitry Andric uint64_t __rdx;
3200b57cec5SDimitry Andric uint64_t __rdi;
3210b57cec5SDimitry Andric uint64_t __rsi;
3220b57cec5SDimitry Andric uint64_t __rbp;
3230b57cec5SDimitry Andric uint64_t __rsp;
3240b57cec5SDimitry Andric uint64_t __r8;
3250b57cec5SDimitry Andric uint64_t __r9;
3260b57cec5SDimitry Andric uint64_t __r10;
3270b57cec5SDimitry Andric uint64_t __r11;
3280b57cec5SDimitry Andric uint64_t __r12;
3290b57cec5SDimitry Andric uint64_t __r13;
3300b57cec5SDimitry Andric uint64_t __r14;
3310b57cec5SDimitry Andric uint64_t __r15;
3320b57cec5SDimitry Andric uint64_t __rip;
3330b57cec5SDimitry Andric uint64_t __rflags;
3340b57cec5SDimitry Andric uint64_t __cs;
3350b57cec5SDimitry Andric uint64_t __fs;
3360b57cec5SDimitry Andric uint64_t __gs;
3370b57cec5SDimitry Andric #if defined(_WIN64)
3380b57cec5SDimitry Andric uint64_t __padding; // 16-byte align
3390b57cec5SDimitry Andric #endif
3400b57cec5SDimitry Andric };
3410b57cec5SDimitry Andric GPRs _registers;
3420b57cec5SDimitry Andric #if defined(_WIN64)
3430b57cec5SDimitry Andric v128 _xmm[16];
3440b57cec5SDimitry Andric #endif
3450b57cec5SDimitry Andric };
3460b57cec5SDimitry Andric
Registers_x86_64(const void * registers)3470b57cec5SDimitry Andric inline Registers_x86_64::Registers_x86_64(const void *registers) {
3480b57cec5SDimitry Andric static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
3490b57cec5SDimitry Andric "x86_64 registers do not fit into unw_context_t");
3500b57cec5SDimitry Andric memcpy(&_registers, registers, sizeof(_registers));
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric
Registers_x86_64()3530b57cec5SDimitry Andric inline Registers_x86_64::Registers_x86_64() {
3540b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric
validRegister(int regNum) const3570b57cec5SDimitry Andric inline bool Registers_x86_64::validRegister(int regNum) const {
3580b57cec5SDimitry Andric if (regNum == UNW_REG_IP)
3590b57cec5SDimitry Andric return true;
3600b57cec5SDimitry Andric if (regNum == UNW_REG_SP)
3610b57cec5SDimitry Andric return true;
3620b57cec5SDimitry Andric if (regNum < 0)
3630b57cec5SDimitry Andric return false;
364349cc55cSDimitry Andric if (regNum > 16)
3650b57cec5SDimitry Andric return false;
3660b57cec5SDimitry Andric return true;
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric
getRegister(int regNum) const3690b57cec5SDimitry Andric inline uint64_t Registers_x86_64::getRegister(int regNum) const {
3700b57cec5SDimitry Andric switch (regNum) {
3710b57cec5SDimitry Andric case UNW_REG_IP:
372349cc55cSDimitry Andric case UNW_X86_64_RIP:
3730b57cec5SDimitry Andric return _registers.__rip;
3740b57cec5SDimitry Andric case UNW_REG_SP:
3750b57cec5SDimitry Andric return _registers.__rsp;
3760b57cec5SDimitry Andric case UNW_X86_64_RAX:
3770b57cec5SDimitry Andric return _registers.__rax;
3780b57cec5SDimitry Andric case UNW_X86_64_RDX:
3790b57cec5SDimitry Andric return _registers.__rdx;
3800b57cec5SDimitry Andric case UNW_X86_64_RCX:
3810b57cec5SDimitry Andric return _registers.__rcx;
3820b57cec5SDimitry Andric case UNW_X86_64_RBX:
3830b57cec5SDimitry Andric return _registers.__rbx;
3840b57cec5SDimitry Andric case UNW_X86_64_RSI:
3850b57cec5SDimitry Andric return _registers.__rsi;
3860b57cec5SDimitry Andric case UNW_X86_64_RDI:
3870b57cec5SDimitry Andric return _registers.__rdi;
3880b57cec5SDimitry Andric case UNW_X86_64_RBP:
3890b57cec5SDimitry Andric return _registers.__rbp;
3900b57cec5SDimitry Andric case UNW_X86_64_RSP:
3910b57cec5SDimitry Andric return _registers.__rsp;
3920b57cec5SDimitry Andric case UNW_X86_64_R8:
3930b57cec5SDimitry Andric return _registers.__r8;
3940b57cec5SDimitry Andric case UNW_X86_64_R9:
3950b57cec5SDimitry Andric return _registers.__r9;
3960b57cec5SDimitry Andric case UNW_X86_64_R10:
3970b57cec5SDimitry Andric return _registers.__r10;
3980b57cec5SDimitry Andric case UNW_X86_64_R11:
3990b57cec5SDimitry Andric return _registers.__r11;
4000b57cec5SDimitry Andric case UNW_X86_64_R12:
4010b57cec5SDimitry Andric return _registers.__r12;
4020b57cec5SDimitry Andric case UNW_X86_64_R13:
4030b57cec5SDimitry Andric return _registers.__r13;
4040b57cec5SDimitry Andric case UNW_X86_64_R14:
4050b57cec5SDimitry Andric return _registers.__r14;
4060b57cec5SDimitry Andric case UNW_X86_64_R15:
4070b57cec5SDimitry Andric return _registers.__r15;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported x86_64 register");
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
setRegister(int regNum,uint64_t value)4120b57cec5SDimitry Andric inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
4130b57cec5SDimitry Andric switch (regNum) {
4140b57cec5SDimitry Andric case UNW_REG_IP:
415349cc55cSDimitry Andric case UNW_X86_64_RIP:
4160b57cec5SDimitry Andric _registers.__rip = value;
4170b57cec5SDimitry Andric return;
4180b57cec5SDimitry Andric case UNW_REG_SP:
4190b57cec5SDimitry Andric _registers.__rsp = value;
4200b57cec5SDimitry Andric return;
4210b57cec5SDimitry Andric case UNW_X86_64_RAX:
4220b57cec5SDimitry Andric _registers.__rax = value;
4230b57cec5SDimitry Andric return;
4240b57cec5SDimitry Andric case UNW_X86_64_RDX:
4250b57cec5SDimitry Andric _registers.__rdx = value;
4260b57cec5SDimitry Andric return;
4270b57cec5SDimitry Andric case UNW_X86_64_RCX:
4280b57cec5SDimitry Andric _registers.__rcx = value;
4290b57cec5SDimitry Andric return;
4300b57cec5SDimitry Andric case UNW_X86_64_RBX:
4310b57cec5SDimitry Andric _registers.__rbx = value;
4320b57cec5SDimitry Andric return;
4330b57cec5SDimitry Andric case UNW_X86_64_RSI:
4340b57cec5SDimitry Andric _registers.__rsi = value;
4350b57cec5SDimitry Andric return;
4360b57cec5SDimitry Andric case UNW_X86_64_RDI:
4370b57cec5SDimitry Andric _registers.__rdi = value;
4380b57cec5SDimitry Andric return;
4390b57cec5SDimitry Andric case UNW_X86_64_RBP:
4400b57cec5SDimitry Andric _registers.__rbp = value;
4410b57cec5SDimitry Andric return;
4420b57cec5SDimitry Andric case UNW_X86_64_RSP:
4430b57cec5SDimitry Andric _registers.__rsp = value;
4440b57cec5SDimitry Andric return;
4450b57cec5SDimitry Andric case UNW_X86_64_R8:
4460b57cec5SDimitry Andric _registers.__r8 = value;
4470b57cec5SDimitry Andric return;
4480b57cec5SDimitry Andric case UNW_X86_64_R9:
4490b57cec5SDimitry Andric _registers.__r9 = value;
4500b57cec5SDimitry Andric return;
4510b57cec5SDimitry Andric case UNW_X86_64_R10:
4520b57cec5SDimitry Andric _registers.__r10 = value;
4530b57cec5SDimitry Andric return;
4540b57cec5SDimitry Andric case UNW_X86_64_R11:
4550b57cec5SDimitry Andric _registers.__r11 = value;
4560b57cec5SDimitry Andric return;
4570b57cec5SDimitry Andric case UNW_X86_64_R12:
4580b57cec5SDimitry Andric _registers.__r12 = value;
4590b57cec5SDimitry Andric return;
4600b57cec5SDimitry Andric case UNW_X86_64_R13:
4610b57cec5SDimitry Andric _registers.__r13 = value;
4620b57cec5SDimitry Andric return;
4630b57cec5SDimitry Andric case UNW_X86_64_R14:
4640b57cec5SDimitry Andric _registers.__r14 = value;
4650b57cec5SDimitry Andric return;
4660b57cec5SDimitry Andric case UNW_X86_64_R15:
4670b57cec5SDimitry Andric _registers.__r15 = value;
4680b57cec5SDimitry Andric return;
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported x86_64 register");
4710b57cec5SDimitry Andric }
4720b57cec5SDimitry Andric
getRegisterName(int regNum)4730b57cec5SDimitry Andric inline const char *Registers_x86_64::getRegisterName(int regNum) {
4740b57cec5SDimitry Andric switch (regNum) {
4750b57cec5SDimitry Andric case UNW_REG_IP:
476349cc55cSDimitry Andric case UNW_X86_64_RIP:
4770b57cec5SDimitry Andric return "rip";
4780b57cec5SDimitry Andric case UNW_REG_SP:
4790b57cec5SDimitry Andric return "rsp";
4800b57cec5SDimitry Andric case UNW_X86_64_RAX:
4810b57cec5SDimitry Andric return "rax";
4820b57cec5SDimitry Andric case UNW_X86_64_RDX:
4830b57cec5SDimitry Andric return "rdx";
4840b57cec5SDimitry Andric case UNW_X86_64_RCX:
4850b57cec5SDimitry Andric return "rcx";
4860b57cec5SDimitry Andric case UNW_X86_64_RBX:
4870b57cec5SDimitry Andric return "rbx";
4880b57cec5SDimitry Andric case UNW_X86_64_RSI:
4890b57cec5SDimitry Andric return "rsi";
4900b57cec5SDimitry Andric case UNW_X86_64_RDI:
4910b57cec5SDimitry Andric return "rdi";
4920b57cec5SDimitry Andric case UNW_X86_64_RBP:
4930b57cec5SDimitry Andric return "rbp";
4940b57cec5SDimitry Andric case UNW_X86_64_RSP:
4950b57cec5SDimitry Andric return "rsp";
4960b57cec5SDimitry Andric case UNW_X86_64_R8:
4970b57cec5SDimitry Andric return "r8";
4980b57cec5SDimitry Andric case UNW_X86_64_R9:
4990b57cec5SDimitry Andric return "r9";
5000b57cec5SDimitry Andric case UNW_X86_64_R10:
5010b57cec5SDimitry Andric return "r10";
5020b57cec5SDimitry Andric case UNW_X86_64_R11:
5030b57cec5SDimitry Andric return "r11";
5040b57cec5SDimitry Andric case UNW_X86_64_R12:
5050b57cec5SDimitry Andric return "r12";
5060b57cec5SDimitry Andric case UNW_X86_64_R13:
5070b57cec5SDimitry Andric return "r13";
5080b57cec5SDimitry Andric case UNW_X86_64_R14:
5090b57cec5SDimitry Andric return "r14";
5100b57cec5SDimitry Andric case UNW_X86_64_R15:
5110b57cec5SDimitry Andric return "r15";
5120b57cec5SDimitry Andric case UNW_X86_64_XMM0:
5130b57cec5SDimitry Andric return "xmm0";
5140b57cec5SDimitry Andric case UNW_X86_64_XMM1:
5150b57cec5SDimitry Andric return "xmm1";
5160b57cec5SDimitry Andric case UNW_X86_64_XMM2:
5170b57cec5SDimitry Andric return "xmm2";
5180b57cec5SDimitry Andric case UNW_X86_64_XMM3:
5190b57cec5SDimitry Andric return "xmm3";
5200b57cec5SDimitry Andric case UNW_X86_64_XMM4:
5210b57cec5SDimitry Andric return "xmm4";
5220b57cec5SDimitry Andric case UNW_X86_64_XMM5:
5230b57cec5SDimitry Andric return "xmm5";
5240b57cec5SDimitry Andric case UNW_X86_64_XMM6:
5250b57cec5SDimitry Andric return "xmm6";
5260b57cec5SDimitry Andric case UNW_X86_64_XMM7:
5270b57cec5SDimitry Andric return "xmm7";
5280b57cec5SDimitry Andric case UNW_X86_64_XMM8:
5290b57cec5SDimitry Andric return "xmm8";
5300b57cec5SDimitry Andric case UNW_X86_64_XMM9:
5310b57cec5SDimitry Andric return "xmm9";
5320b57cec5SDimitry Andric case UNW_X86_64_XMM10:
5330b57cec5SDimitry Andric return "xmm10";
5340b57cec5SDimitry Andric case UNW_X86_64_XMM11:
5350b57cec5SDimitry Andric return "xmm11";
5360b57cec5SDimitry Andric case UNW_X86_64_XMM12:
5370b57cec5SDimitry Andric return "xmm12";
5380b57cec5SDimitry Andric case UNW_X86_64_XMM13:
5390b57cec5SDimitry Andric return "xmm13";
5400b57cec5SDimitry Andric case UNW_X86_64_XMM14:
5410b57cec5SDimitry Andric return "xmm14";
5420b57cec5SDimitry Andric case UNW_X86_64_XMM15:
5430b57cec5SDimitry Andric return "xmm15";
5440b57cec5SDimitry Andric default:
5450b57cec5SDimitry Andric return "unknown register";
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric
getFloatRegister(int) const5490b57cec5SDimitry Andric inline double Registers_x86_64::getFloatRegister(int) const {
5500b57cec5SDimitry Andric _LIBUNWIND_ABORT("no x86_64 float registers");
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric
setFloatRegister(int,double)5530b57cec5SDimitry Andric inline void Registers_x86_64::setFloatRegister(int, double) {
5540b57cec5SDimitry Andric _LIBUNWIND_ABORT("no x86_64 float registers");
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric
validVectorRegister(int regNum) const5570b57cec5SDimitry Andric inline bool Registers_x86_64::validVectorRegister(int regNum) const {
5580b57cec5SDimitry Andric #if defined(_WIN64)
5590b57cec5SDimitry Andric if (regNum < UNW_X86_64_XMM0)
5600b57cec5SDimitry Andric return false;
5610b57cec5SDimitry Andric if (regNum > UNW_X86_64_XMM15)
5620b57cec5SDimitry Andric return false;
5630b57cec5SDimitry Andric return true;
5640b57cec5SDimitry Andric #else
5650b57cec5SDimitry Andric (void)regNum; // suppress unused parameter warning
5660b57cec5SDimitry Andric return false;
5670b57cec5SDimitry Andric #endif
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric
getVectorRegister(int regNum) const5700b57cec5SDimitry Andric inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
5710b57cec5SDimitry Andric #if defined(_WIN64)
5720b57cec5SDimitry Andric assert(validVectorRegister(regNum));
5730b57cec5SDimitry Andric return _xmm[regNum - UNW_X86_64_XMM0];
5740b57cec5SDimitry Andric #else
5750b57cec5SDimitry Andric (void)regNum; // suppress unused parameter warning
5760b57cec5SDimitry Andric _LIBUNWIND_ABORT("no x86_64 vector registers");
5770b57cec5SDimitry Andric #endif
5780b57cec5SDimitry Andric }
5790b57cec5SDimitry Andric
setVectorRegister(int regNum,v128 value)5800b57cec5SDimitry Andric inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
5810b57cec5SDimitry Andric #if defined(_WIN64)
5820b57cec5SDimitry Andric assert(validVectorRegister(regNum));
5830b57cec5SDimitry Andric _xmm[regNum - UNW_X86_64_XMM0] = value;
5840b57cec5SDimitry Andric #else
5850b57cec5SDimitry Andric (void)regNum; (void)value; // suppress unused parameter warnings
5860b57cec5SDimitry Andric _LIBUNWIND_ABORT("no x86_64 vector registers");
5870b57cec5SDimitry Andric #endif
5880b57cec5SDimitry Andric }
5890b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_X86_64
5900b57cec5SDimitry Andric
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_PPC)
5930b57cec5SDimitry Andric /// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
5940b57cec5SDimitry Andric /// process.
5950b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_ppc {
5960b57cec5SDimitry Andric public:
5970b57cec5SDimitry Andric Registers_ppc();
5980b57cec5SDimitry Andric Registers_ppc(const void *registers);
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric bool validRegister(int num) const;
6010b57cec5SDimitry Andric uint32_t getRegister(int num) const;
6020b57cec5SDimitry Andric void setRegister(int num, uint32_t value);
6030b57cec5SDimitry Andric bool validFloatRegister(int num) const;
6040b57cec5SDimitry Andric double getFloatRegister(int num) const;
6050b57cec5SDimitry Andric void setFloatRegister(int num, double value);
6060b57cec5SDimitry Andric bool validVectorRegister(int num) const;
6070b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
6080b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
6090b57cec5SDimitry Andric static const char *getRegisterName(int num);
6100b57cec5SDimitry Andric void jumpto();
lastDwarfRegNum()61181ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
61281ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC;
61381ad6265SDimitry Andric }
getArch()6140b57cec5SDimitry Andric static int getArch() { return REGISTERS_PPC; }
6150b57cec5SDimitry Andric
getSP() const6160b57cec5SDimitry Andric uint64_t getSP() const { return _registers.__r1; }
setSP(uint32_t value)6170b57cec5SDimitry Andric void setSP(uint32_t value) { _registers.__r1 = value; }
getIP() const6180b57cec5SDimitry Andric uint64_t getIP() const { return _registers.__srr0; }
setIP(uint32_t value)6190b57cec5SDimitry Andric void setIP(uint32_t value) { _registers.__srr0 = value; }
getCR() const62081ad6265SDimitry Andric uint64_t getCR() const { return _registers.__cr; }
setCR(uint32_t value)62181ad6265SDimitry Andric void setCR(uint32_t value) { _registers.__cr = value; }
getLR() const6225f757f3fSDimitry Andric uint64_t getLR() const { return _registers.__lr; }
setLR(uint32_t value)6235f757f3fSDimitry Andric void setLR(uint32_t value) { _registers.__lr = value; }
6240b57cec5SDimitry Andric
6250b57cec5SDimitry Andric private:
6260b57cec5SDimitry Andric struct ppc_thread_state_t {
6270b57cec5SDimitry Andric unsigned int __srr0; /* Instruction address register (PC) */
6280b57cec5SDimitry Andric unsigned int __srr1; /* Machine state register (supervisor) */
6290b57cec5SDimitry Andric unsigned int __r0;
6300b57cec5SDimitry Andric unsigned int __r1;
6310b57cec5SDimitry Andric unsigned int __r2;
6320b57cec5SDimitry Andric unsigned int __r3;
6330b57cec5SDimitry Andric unsigned int __r4;
6340b57cec5SDimitry Andric unsigned int __r5;
6350b57cec5SDimitry Andric unsigned int __r6;
6360b57cec5SDimitry Andric unsigned int __r7;
6370b57cec5SDimitry Andric unsigned int __r8;
6380b57cec5SDimitry Andric unsigned int __r9;
6390b57cec5SDimitry Andric unsigned int __r10;
6400b57cec5SDimitry Andric unsigned int __r11;
6410b57cec5SDimitry Andric unsigned int __r12;
6420b57cec5SDimitry Andric unsigned int __r13;
6430b57cec5SDimitry Andric unsigned int __r14;
6440b57cec5SDimitry Andric unsigned int __r15;
6450b57cec5SDimitry Andric unsigned int __r16;
6460b57cec5SDimitry Andric unsigned int __r17;
6470b57cec5SDimitry Andric unsigned int __r18;
6480b57cec5SDimitry Andric unsigned int __r19;
6490b57cec5SDimitry Andric unsigned int __r20;
6500b57cec5SDimitry Andric unsigned int __r21;
6510b57cec5SDimitry Andric unsigned int __r22;
6520b57cec5SDimitry Andric unsigned int __r23;
6530b57cec5SDimitry Andric unsigned int __r24;
6540b57cec5SDimitry Andric unsigned int __r25;
6550b57cec5SDimitry Andric unsigned int __r26;
6560b57cec5SDimitry Andric unsigned int __r27;
6570b57cec5SDimitry Andric unsigned int __r28;
6580b57cec5SDimitry Andric unsigned int __r29;
6590b57cec5SDimitry Andric unsigned int __r30;
6600b57cec5SDimitry Andric unsigned int __r31;
6610b57cec5SDimitry Andric unsigned int __cr; /* Condition register */
6620b57cec5SDimitry Andric unsigned int __xer; /* User's integer exception register */
6630b57cec5SDimitry Andric unsigned int __lr; /* Link register */
6640b57cec5SDimitry Andric unsigned int __ctr; /* Count register */
6650b57cec5SDimitry Andric unsigned int __mq; /* MQ register (601 only) */
6660b57cec5SDimitry Andric unsigned int __vrsave; /* Vector Save Register */
6670b57cec5SDimitry Andric };
6680b57cec5SDimitry Andric
6690b57cec5SDimitry Andric struct ppc_float_state_t {
6700b57cec5SDimitry Andric double __fpregs[32];
6710b57cec5SDimitry Andric
6720b57cec5SDimitry Andric unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
6730b57cec5SDimitry Andric unsigned int __fpscr; /* floating point status register */
6740b57cec5SDimitry Andric };
6750b57cec5SDimitry Andric
6760b57cec5SDimitry Andric ppc_thread_state_t _registers;
6770b57cec5SDimitry Andric ppc_float_state_t _floatRegisters;
6780b57cec5SDimitry Andric v128 _vectorRegisters[32]; // offset 424
6790b57cec5SDimitry Andric };
6800b57cec5SDimitry Andric
Registers_ppc(const void * registers)6810b57cec5SDimitry Andric inline Registers_ppc::Registers_ppc(const void *registers) {
6820b57cec5SDimitry Andric static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
6830b57cec5SDimitry Andric "ppc registers do not fit into unw_context_t");
6840b57cec5SDimitry Andric memcpy(&_registers, static_cast<const uint8_t *>(registers),
6850b57cec5SDimitry Andric sizeof(_registers));
6860b57cec5SDimitry Andric static_assert(sizeof(ppc_thread_state_t) == 160,
6870b57cec5SDimitry Andric "expected float register offset to be 160");
6880b57cec5SDimitry Andric memcpy(&_floatRegisters,
6890b57cec5SDimitry Andric static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
6900b57cec5SDimitry Andric sizeof(_floatRegisters));
6910b57cec5SDimitry Andric static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
6920b57cec5SDimitry Andric "expected vector register offset to be 424 bytes");
6930b57cec5SDimitry Andric memcpy(_vectorRegisters,
6940b57cec5SDimitry Andric static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
6950b57cec5SDimitry Andric sizeof(ppc_float_state_t),
6960b57cec5SDimitry Andric sizeof(_vectorRegisters));
6970b57cec5SDimitry Andric }
6980b57cec5SDimitry Andric
Registers_ppc()6990b57cec5SDimitry Andric inline Registers_ppc::Registers_ppc() {
7000b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
7010b57cec5SDimitry Andric memset(&_floatRegisters, 0, sizeof(_floatRegisters));
7020b57cec5SDimitry Andric memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
7030b57cec5SDimitry Andric }
7040b57cec5SDimitry Andric
validRegister(int regNum) const7050b57cec5SDimitry Andric inline bool Registers_ppc::validRegister(int regNum) const {
7060b57cec5SDimitry Andric if (regNum == UNW_REG_IP)
7070b57cec5SDimitry Andric return true;
7080b57cec5SDimitry Andric if (regNum == UNW_REG_SP)
7090b57cec5SDimitry Andric return true;
7100b57cec5SDimitry Andric if (regNum == UNW_PPC_VRSAVE)
7110b57cec5SDimitry Andric return true;
7120b57cec5SDimitry Andric if (regNum < 0)
7130b57cec5SDimitry Andric return false;
7140b57cec5SDimitry Andric if (regNum <= UNW_PPC_R31)
7150b57cec5SDimitry Andric return true;
7160b57cec5SDimitry Andric if (regNum == UNW_PPC_MQ)
7170b57cec5SDimitry Andric return true;
7180b57cec5SDimitry Andric if (regNum == UNW_PPC_LR)
7190b57cec5SDimitry Andric return true;
7200b57cec5SDimitry Andric if (regNum == UNW_PPC_CTR)
7210b57cec5SDimitry Andric return true;
7220b57cec5SDimitry Andric if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
7230b57cec5SDimitry Andric return true;
7240b57cec5SDimitry Andric return false;
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric
getRegister(int regNum) const7270b57cec5SDimitry Andric inline uint32_t Registers_ppc::getRegister(int regNum) const {
7280b57cec5SDimitry Andric switch (regNum) {
7290b57cec5SDimitry Andric case UNW_REG_IP:
7300b57cec5SDimitry Andric return _registers.__srr0;
7310b57cec5SDimitry Andric case UNW_REG_SP:
7320b57cec5SDimitry Andric return _registers.__r1;
7330b57cec5SDimitry Andric case UNW_PPC_R0:
7340b57cec5SDimitry Andric return _registers.__r0;
7350b57cec5SDimitry Andric case UNW_PPC_R1:
7360b57cec5SDimitry Andric return _registers.__r1;
7370b57cec5SDimitry Andric case UNW_PPC_R2:
7380b57cec5SDimitry Andric return _registers.__r2;
7390b57cec5SDimitry Andric case UNW_PPC_R3:
7400b57cec5SDimitry Andric return _registers.__r3;
7410b57cec5SDimitry Andric case UNW_PPC_R4:
7420b57cec5SDimitry Andric return _registers.__r4;
7430b57cec5SDimitry Andric case UNW_PPC_R5:
7440b57cec5SDimitry Andric return _registers.__r5;
7450b57cec5SDimitry Andric case UNW_PPC_R6:
7460b57cec5SDimitry Andric return _registers.__r6;
7470b57cec5SDimitry Andric case UNW_PPC_R7:
7480b57cec5SDimitry Andric return _registers.__r7;
7490b57cec5SDimitry Andric case UNW_PPC_R8:
7500b57cec5SDimitry Andric return _registers.__r8;
7510b57cec5SDimitry Andric case UNW_PPC_R9:
7520b57cec5SDimitry Andric return _registers.__r9;
7530b57cec5SDimitry Andric case UNW_PPC_R10:
7540b57cec5SDimitry Andric return _registers.__r10;
7550b57cec5SDimitry Andric case UNW_PPC_R11:
7560b57cec5SDimitry Andric return _registers.__r11;
7570b57cec5SDimitry Andric case UNW_PPC_R12:
7580b57cec5SDimitry Andric return _registers.__r12;
7590b57cec5SDimitry Andric case UNW_PPC_R13:
7600b57cec5SDimitry Andric return _registers.__r13;
7610b57cec5SDimitry Andric case UNW_PPC_R14:
7620b57cec5SDimitry Andric return _registers.__r14;
7630b57cec5SDimitry Andric case UNW_PPC_R15:
7640b57cec5SDimitry Andric return _registers.__r15;
7650b57cec5SDimitry Andric case UNW_PPC_R16:
7660b57cec5SDimitry Andric return _registers.__r16;
7670b57cec5SDimitry Andric case UNW_PPC_R17:
7680b57cec5SDimitry Andric return _registers.__r17;
7690b57cec5SDimitry Andric case UNW_PPC_R18:
7700b57cec5SDimitry Andric return _registers.__r18;
7710b57cec5SDimitry Andric case UNW_PPC_R19:
7720b57cec5SDimitry Andric return _registers.__r19;
7730b57cec5SDimitry Andric case UNW_PPC_R20:
7740b57cec5SDimitry Andric return _registers.__r20;
7750b57cec5SDimitry Andric case UNW_PPC_R21:
7760b57cec5SDimitry Andric return _registers.__r21;
7770b57cec5SDimitry Andric case UNW_PPC_R22:
7780b57cec5SDimitry Andric return _registers.__r22;
7790b57cec5SDimitry Andric case UNW_PPC_R23:
7800b57cec5SDimitry Andric return _registers.__r23;
7810b57cec5SDimitry Andric case UNW_PPC_R24:
7820b57cec5SDimitry Andric return _registers.__r24;
7830b57cec5SDimitry Andric case UNW_PPC_R25:
7840b57cec5SDimitry Andric return _registers.__r25;
7850b57cec5SDimitry Andric case UNW_PPC_R26:
7860b57cec5SDimitry Andric return _registers.__r26;
7870b57cec5SDimitry Andric case UNW_PPC_R27:
7880b57cec5SDimitry Andric return _registers.__r27;
7890b57cec5SDimitry Andric case UNW_PPC_R28:
7900b57cec5SDimitry Andric return _registers.__r28;
7910b57cec5SDimitry Andric case UNW_PPC_R29:
7920b57cec5SDimitry Andric return _registers.__r29;
7930b57cec5SDimitry Andric case UNW_PPC_R30:
7940b57cec5SDimitry Andric return _registers.__r30;
7950b57cec5SDimitry Andric case UNW_PPC_R31:
7960b57cec5SDimitry Andric return _registers.__r31;
7970b57cec5SDimitry Andric case UNW_PPC_LR:
7980b57cec5SDimitry Andric return _registers.__lr;
7990b57cec5SDimitry Andric case UNW_PPC_CR0:
8000b57cec5SDimitry Andric return (_registers.__cr & 0xF0000000);
8010b57cec5SDimitry Andric case UNW_PPC_CR1:
8020b57cec5SDimitry Andric return (_registers.__cr & 0x0F000000);
8030b57cec5SDimitry Andric case UNW_PPC_CR2:
8040b57cec5SDimitry Andric return (_registers.__cr & 0x00F00000);
8050b57cec5SDimitry Andric case UNW_PPC_CR3:
8060b57cec5SDimitry Andric return (_registers.__cr & 0x000F0000);
8070b57cec5SDimitry Andric case UNW_PPC_CR4:
8080b57cec5SDimitry Andric return (_registers.__cr & 0x0000F000);
8090b57cec5SDimitry Andric case UNW_PPC_CR5:
8100b57cec5SDimitry Andric return (_registers.__cr & 0x00000F00);
8110b57cec5SDimitry Andric case UNW_PPC_CR6:
8120b57cec5SDimitry Andric return (_registers.__cr & 0x000000F0);
8130b57cec5SDimitry Andric case UNW_PPC_CR7:
8140b57cec5SDimitry Andric return (_registers.__cr & 0x0000000F);
8150b57cec5SDimitry Andric case UNW_PPC_VRSAVE:
8160b57cec5SDimitry Andric return _registers.__vrsave;
8170b57cec5SDimitry Andric }
8180b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported ppc register");
8190b57cec5SDimitry Andric }
8200b57cec5SDimitry Andric
setRegister(int regNum,uint32_t value)8210b57cec5SDimitry Andric inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
8220b57cec5SDimitry Andric //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
8230b57cec5SDimitry Andric switch (regNum) {
8240b57cec5SDimitry Andric case UNW_REG_IP:
8250b57cec5SDimitry Andric _registers.__srr0 = value;
8260b57cec5SDimitry Andric return;
8270b57cec5SDimitry Andric case UNW_REG_SP:
8280b57cec5SDimitry Andric _registers.__r1 = value;
8290b57cec5SDimitry Andric return;
8300b57cec5SDimitry Andric case UNW_PPC_R0:
8310b57cec5SDimitry Andric _registers.__r0 = value;
8320b57cec5SDimitry Andric return;
8330b57cec5SDimitry Andric case UNW_PPC_R1:
8340b57cec5SDimitry Andric _registers.__r1 = value;
8350b57cec5SDimitry Andric return;
8360b57cec5SDimitry Andric case UNW_PPC_R2:
8370b57cec5SDimitry Andric _registers.__r2 = value;
8380b57cec5SDimitry Andric return;
8390b57cec5SDimitry Andric case UNW_PPC_R3:
8400b57cec5SDimitry Andric _registers.__r3 = value;
8410b57cec5SDimitry Andric return;
8420b57cec5SDimitry Andric case UNW_PPC_R4:
8430b57cec5SDimitry Andric _registers.__r4 = value;
8440b57cec5SDimitry Andric return;
8450b57cec5SDimitry Andric case UNW_PPC_R5:
8460b57cec5SDimitry Andric _registers.__r5 = value;
8470b57cec5SDimitry Andric return;
8480b57cec5SDimitry Andric case UNW_PPC_R6:
8490b57cec5SDimitry Andric _registers.__r6 = value;
8500b57cec5SDimitry Andric return;
8510b57cec5SDimitry Andric case UNW_PPC_R7:
8520b57cec5SDimitry Andric _registers.__r7 = value;
8530b57cec5SDimitry Andric return;
8540b57cec5SDimitry Andric case UNW_PPC_R8:
8550b57cec5SDimitry Andric _registers.__r8 = value;
8560b57cec5SDimitry Andric return;
8570b57cec5SDimitry Andric case UNW_PPC_R9:
8580b57cec5SDimitry Andric _registers.__r9 = value;
8590b57cec5SDimitry Andric return;
8600b57cec5SDimitry Andric case UNW_PPC_R10:
8610b57cec5SDimitry Andric _registers.__r10 = value;
8620b57cec5SDimitry Andric return;
8630b57cec5SDimitry Andric case UNW_PPC_R11:
8640b57cec5SDimitry Andric _registers.__r11 = value;
8650b57cec5SDimitry Andric return;
8660b57cec5SDimitry Andric case UNW_PPC_R12:
8670b57cec5SDimitry Andric _registers.__r12 = value;
8680b57cec5SDimitry Andric return;
8690b57cec5SDimitry Andric case UNW_PPC_R13:
8700b57cec5SDimitry Andric _registers.__r13 = value;
8710b57cec5SDimitry Andric return;
8720b57cec5SDimitry Andric case UNW_PPC_R14:
8730b57cec5SDimitry Andric _registers.__r14 = value;
8740b57cec5SDimitry Andric return;
8750b57cec5SDimitry Andric case UNW_PPC_R15:
8760b57cec5SDimitry Andric _registers.__r15 = value;
8770b57cec5SDimitry Andric return;
8780b57cec5SDimitry Andric case UNW_PPC_R16:
8790b57cec5SDimitry Andric _registers.__r16 = value;
8800b57cec5SDimitry Andric return;
8810b57cec5SDimitry Andric case UNW_PPC_R17:
8820b57cec5SDimitry Andric _registers.__r17 = value;
8830b57cec5SDimitry Andric return;
8840b57cec5SDimitry Andric case UNW_PPC_R18:
8850b57cec5SDimitry Andric _registers.__r18 = value;
8860b57cec5SDimitry Andric return;
8870b57cec5SDimitry Andric case UNW_PPC_R19:
8880b57cec5SDimitry Andric _registers.__r19 = value;
8890b57cec5SDimitry Andric return;
8900b57cec5SDimitry Andric case UNW_PPC_R20:
8910b57cec5SDimitry Andric _registers.__r20 = value;
8920b57cec5SDimitry Andric return;
8930b57cec5SDimitry Andric case UNW_PPC_R21:
8940b57cec5SDimitry Andric _registers.__r21 = value;
8950b57cec5SDimitry Andric return;
8960b57cec5SDimitry Andric case UNW_PPC_R22:
8970b57cec5SDimitry Andric _registers.__r22 = value;
8980b57cec5SDimitry Andric return;
8990b57cec5SDimitry Andric case UNW_PPC_R23:
9000b57cec5SDimitry Andric _registers.__r23 = value;
9010b57cec5SDimitry Andric return;
9020b57cec5SDimitry Andric case UNW_PPC_R24:
9030b57cec5SDimitry Andric _registers.__r24 = value;
9040b57cec5SDimitry Andric return;
9050b57cec5SDimitry Andric case UNW_PPC_R25:
9060b57cec5SDimitry Andric _registers.__r25 = value;
9070b57cec5SDimitry Andric return;
9080b57cec5SDimitry Andric case UNW_PPC_R26:
9090b57cec5SDimitry Andric _registers.__r26 = value;
9100b57cec5SDimitry Andric return;
9110b57cec5SDimitry Andric case UNW_PPC_R27:
9120b57cec5SDimitry Andric _registers.__r27 = value;
9130b57cec5SDimitry Andric return;
9140b57cec5SDimitry Andric case UNW_PPC_R28:
9150b57cec5SDimitry Andric _registers.__r28 = value;
9160b57cec5SDimitry Andric return;
9170b57cec5SDimitry Andric case UNW_PPC_R29:
9180b57cec5SDimitry Andric _registers.__r29 = value;
9190b57cec5SDimitry Andric return;
9200b57cec5SDimitry Andric case UNW_PPC_R30:
9210b57cec5SDimitry Andric _registers.__r30 = value;
9220b57cec5SDimitry Andric return;
9230b57cec5SDimitry Andric case UNW_PPC_R31:
9240b57cec5SDimitry Andric _registers.__r31 = value;
9250b57cec5SDimitry Andric return;
9260b57cec5SDimitry Andric case UNW_PPC_MQ:
9270b57cec5SDimitry Andric _registers.__mq = value;
9280b57cec5SDimitry Andric return;
9290b57cec5SDimitry Andric case UNW_PPC_LR:
9300b57cec5SDimitry Andric _registers.__lr = value;
9310b57cec5SDimitry Andric return;
9320b57cec5SDimitry Andric case UNW_PPC_CTR:
9330b57cec5SDimitry Andric _registers.__ctr = value;
9340b57cec5SDimitry Andric return;
9350b57cec5SDimitry Andric case UNW_PPC_CR0:
9360b57cec5SDimitry Andric _registers.__cr &= 0x0FFFFFFF;
9370b57cec5SDimitry Andric _registers.__cr |= (value & 0xF0000000);
9380b57cec5SDimitry Andric return;
9390b57cec5SDimitry Andric case UNW_PPC_CR1:
9400b57cec5SDimitry Andric _registers.__cr &= 0xF0FFFFFF;
9410b57cec5SDimitry Andric _registers.__cr |= (value & 0x0F000000);
9420b57cec5SDimitry Andric return;
9430b57cec5SDimitry Andric case UNW_PPC_CR2:
9440b57cec5SDimitry Andric _registers.__cr &= 0xFF0FFFFF;
9450b57cec5SDimitry Andric _registers.__cr |= (value & 0x00F00000);
9460b57cec5SDimitry Andric return;
9470b57cec5SDimitry Andric case UNW_PPC_CR3:
9480b57cec5SDimitry Andric _registers.__cr &= 0xFFF0FFFF;
9490b57cec5SDimitry Andric _registers.__cr |= (value & 0x000F0000);
9500b57cec5SDimitry Andric return;
9510b57cec5SDimitry Andric case UNW_PPC_CR4:
9520b57cec5SDimitry Andric _registers.__cr &= 0xFFFF0FFF;
9530b57cec5SDimitry Andric _registers.__cr |= (value & 0x0000F000);
9540b57cec5SDimitry Andric return;
9550b57cec5SDimitry Andric case UNW_PPC_CR5:
9560b57cec5SDimitry Andric _registers.__cr &= 0xFFFFF0FF;
9570b57cec5SDimitry Andric _registers.__cr |= (value & 0x00000F00);
9580b57cec5SDimitry Andric return;
9590b57cec5SDimitry Andric case UNW_PPC_CR6:
9600b57cec5SDimitry Andric _registers.__cr &= 0xFFFFFF0F;
9610b57cec5SDimitry Andric _registers.__cr |= (value & 0x000000F0);
9620b57cec5SDimitry Andric return;
9630b57cec5SDimitry Andric case UNW_PPC_CR7:
9640b57cec5SDimitry Andric _registers.__cr &= 0xFFFFFFF0;
9650b57cec5SDimitry Andric _registers.__cr |= (value & 0x0000000F);
9660b57cec5SDimitry Andric return;
9670b57cec5SDimitry Andric case UNW_PPC_VRSAVE:
9680b57cec5SDimitry Andric _registers.__vrsave = value;
9690b57cec5SDimitry Andric return;
9700b57cec5SDimitry Andric // not saved
9710b57cec5SDimitry Andric return;
9720b57cec5SDimitry Andric case UNW_PPC_XER:
9730b57cec5SDimitry Andric _registers.__xer = value;
9740b57cec5SDimitry Andric return;
9750b57cec5SDimitry Andric case UNW_PPC_AP:
9760b57cec5SDimitry Andric case UNW_PPC_VSCR:
9770b57cec5SDimitry Andric case UNW_PPC_SPEFSCR:
9780b57cec5SDimitry Andric // not saved
9790b57cec5SDimitry Andric return;
9800b57cec5SDimitry Andric }
9810b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported ppc register");
9820b57cec5SDimitry Andric }
9830b57cec5SDimitry Andric
validFloatRegister(int regNum) const9840b57cec5SDimitry Andric inline bool Registers_ppc::validFloatRegister(int regNum) const {
9850b57cec5SDimitry Andric if (regNum < UNW_PPC_F0)
9860b57cec5SDimitry Andric return false;
9870b57cec5SDimitry Andric if (regNum > UNW_PPC_F31)
9880b57cec5SDimitry Andric return false;
9890b57cec5SDimitry Andric return true;
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric
getFloatRegister(int regNum) const9920b57cec5SDimitry Andric inline double Registers_ppc::getFloatRegister(int regNum) const {
9930b57cec5SDimitry Andric assert(validFloatRegister(regNum));
9940b57cec5SDimitry Andric return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
9950b57cec5SDimitry Andric }
9960b57cec5SDimitry Andric
setFloatRegister(int regNum,double value)9970b57cec5SDimitry Andric inline void Registers_ppc::setFloatRegister(int regNum, double value) {
9980b57cec5SDimitry Andric assert(validFloatRegister(regNum));
9990b57cec5SDimitry Andric _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric
validVectorRegister(int regNum) const10020b57cec5SDimitry Andric inline bool Registers_ppc::validVectorRegister(int regNum) const {
10030b57cec5SDimitry Andric if (regNum < UNW_PPC_V0)
10040b57cec5SDimitry Andric return false;
10050b57cec5SDimitry Andric if (regNum > UNW_PPC_V31)
10060b57cec5SDimitry Andric return false;
10070b57cec5SDimitry Andric return true;
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric
getVectorRegister(int regNum) const10100b57cec5SDimitry Andric inline v128 Registers_ppc::getVectorRegister(int regNum) const {
10110b57cec5SDimitry Andric assert(validVectorRegister(regNum));
10120b57cec5SDimitry Andric v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
10130b57cec5SDimitry Andric return result;
10140b57cec5SDimitry Andric }
10150b57cec5SDimitry Andric
setVectorRegister(int regNum,v128 value)10160b57cec5SDimitry Andric inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
10170b57cec5SDimitry Andric assert(validVectorRegister(regNum));
10180b57cec5SDimitry Andric _vectorRegisters[regNum - UNW_PPC_V0] = value;
10190b57cec5SDimitry Andric }
10200b57cec5SDimitry Andric
getRegisterName(int regNum)10210b57cec5SDimitry Andric inline const char *Registers_ppc::getRegisterName(int regNum) {
10220b57cec5SDimitry Andric switch (regNum) {
10230b57cec5SDimitry Andric case UNW_REG_IP:
10240b57cec5SDimitry Andric return "ip";
10250b57cec5SDimitry Andric case UNW_REG_SP:
10260b57cec5SDimitry Andric return "sp";
10270b57cec5SDimitry Andric case UNW_PPC_R0:
10280b57cec5SDimitry Andric return "r0";
10290b57cec5SDimitry Andric case UNW_PPC_R1:
10300b57cec5SDimitry Andric return "r1";
10310b57cec5SDimitry Andric case UNW_PPC_R2:
10320b57cec5SDimitry Andric return "r2";
10330b57cec5SDimitry Andric case UNW_PPC_R3:
10340b57cec5SDimitry Andric return "r3";
10350b57cec5SDimitry Andric case UNW_PPC_R4:
10360b57cec5SDimitry Andric return "r4";
10370b57cec5SDimitry Andric case UNW_PPC_R5:
10380b57cec5SDimitry Andric return "r5";
10390b57cec5SDimitry Andric case UNW_PPC_R6:
10400b57cec5SDimitry Andric return "r6";
10410b57cec5SDimitry Andric case UNW_PPC_R7:
10420b57cec5SDimitry Andric return "r7";
10430b57cec5SDimitry Andric case UNW_PPC_R8:
10440b57cec5SDimitry Andric return "r8";
10450b57cec5SDimitry Andric case UNW_PPC_R9:
10460b57cec5SDimitry Andric return "r9";
10470b57cec5SDimitry Andric case UNW_PPC_R10:
10480b57cec5SDimitry Andric return "r10";
10490b57cec5SDimitry Andric case UNW_PPC_R11:
10500b57cec5SDimitry Andric return "r11";
10510b57cec5SDimitry Andric case UNW_PPC_R12:
10520b57cec5SDimitry Andric return "r12";
10530b57cec5SDimitry Andric case UNW_PPC_R13:
10540b57cec5SDimitry Andric return "r13";
10550b57cec5SDimitry Andric case UNW_PPC_R14:
10560b57cec5SDimitry Andric return "r14";
10570b57cec5SDimitry Andric case UNW_PPC_R15:
10580b57cec5SDimitry Andric return "r15";
10590b57cec5SDimitry Andric case UNW_PPC_R16:
10600b57cec5SDimitry Andric return "r16";
10610b57cec5SDimitry Andric case UNW_PPC_R17:
10620b57cec5SDimitry Andric return "r17";
10630b57cec5SDimitry Andric case UNW_PPC_R18:
10640b57cec5SDimitry Andric return "r18";
10650b57cec5SDimitry Andric case UNW_PPC_R19:
10660b57cec5SDimitry Andric return "r19";
10670b57cec5SDimitry Andric case UNW_PPC_R20:
10680b57cec5SDimitry Andric return "r20";
10690b57cec5SDimitry Andric case UNW_PPC_R21:
10700b57cec5SDimitry Andric return "r21";
10710b57cec5SDimitry Andric case UNW_PPC_R22:
10720b57cec5SDimitry Andric return "r22";
10730b57cec5SDimitry Andric case UNW_PPC_R23:
10740b57cec5SDimitry Andric return "r23";
10750b57cec5SDimitry Andric case UNW_PPC_R24:
10760b57cec5SDimitry Andric return "r24";
10770b57cec5SDimitry Andric case UNW_PPC_R25:
10780b57cec5SDimitry Andric return "r25";
10790b57cec5SDimitry Andric case UNW_PPC_R26:
10800b57cec5SDimitry Andric return "r26";
10810b57cec5SDimitry Andric case UNW_PPC_R27:
10820b57cec5SDimitry Andric return "r27";
10830b57cec5SDimitry Andric case UNW_PPC_R28:
10840b57cec5SDimitry Andric return "r28";
10850b57cec5SDimitry Andric case UNW_PPC_R29:
10860b57cec5SDimitry Andric return "r29";
10870b57cec5SDimitry Andric case UNW_PPC_R30:
10880b57cec5SDimitry Andric return "r30";
10890b57cec5SDimitry Andric case UNW_PPC_R31:
10900b57cec5SDimitry Andric return "r31";
10910b57cec5SDimitry Andric case UNW_PPC_F0:
10920b57cec5SDimitry Andric return "fp0";
10930b57cec5SDimitry Andric case UNW_PPC_F1:
10940b57cec5SDimitry Andric return "fp1";
10950b57cec5SDimitry Andric case UNW_PPC_F2:
10960b57cec5SDimitry Andric return "fp2";
10970b57cec5SDimitry Andric case UNW_PPC_F3:
10980b57cec5SDimitry Andric return "fp3";
10990b57cec5SDimitry Andric case UNW_PPC_F4:
11000b57cec5SDimitry Andric return "fp4";
11010b57cec5SDimitry Andric case UNW_PPC_F5:
11020b57cec5SDimitry Andric return "fp5";
11030b57cec5SDimitry Andric case UNW_PPC_F6:
11040b57cec5SDimitry Andric return "fp6";
11050b57cec5SDimitry Andric case UNW_PPC_F7:
11060b57cec5SDimitry Andric return "fp7";
11070b57cec5SDimitry Andric case UNW_PPC_F8:
11080b57cec5SDimitry Andric return "fp8";
11090b57cec5SDimitry Andric case UNW_PPC_F9:
11100b57cec5SDimitry Andric return "fp9";
11110b57cec5SDimitry Andric case UNW_PPC_F10:
11120b57cec5SDimitry Andric return "fp10";
11130b57cec5SDimitry Andric case UNW_PPC_F11:
11140b57cec5SDimitry Andric return "fp11";
11150b57cec5SDimitry Andric case UNW_PPC_F12:
11160b57cec5SDimitry Andric return "fp12";
11170b57cec5SDimitry Andric case UNW_PPC_F13:
11180b57cec5SDimitry Andric return "fp13";
11190b57cec5SDimitry Andric case UNW_PPC_F14:
11200b57cec5SDimitry Andric return "fp14";
11210b57cec5SDimitry Andric case UNW_PPC_F15:
11220b57cec5SDimitry Andric return "fp15";
11230b57cec5SDimitry Andric case UNW_PPC_F16:
11240b57cec5SDimitry Andric return "fp16";
11250b57cec5SDimitry Andric case UNW_PPC_F17:
11260b57cec5SDimitry Andric return "fp17";
11270b57cec5SDimitry Andric case UNW_PPC_F18:
11280b57cec5SDimitry Andric return "fp18";
11290b57cec5SDimitry Andric case UNW_PPC_F19:
11300b57cec5SDimitry Andric return "fp19";
11310b57cec5SDimitry Andric case UNW_PPC_F20:
11320b57cec5SDimitry Andric return "fp20";
11330b57cec5SDimitry Andric case UNW_PPC_F21:
11340b57cec5SDimitry Andric return "fp21";
11350b57cec5SDimitry Andric case UNW_PPC_F22:
11360b57cec5SDimitry Andric return "fp22";
11370b57cec5SDimitry Andric case UNW_PPC_F23:
11380b57cec5SDimitry Andric return "fp23";
11390b57cec5SDimitry Andric case UNW_PPC_F24:
11400b57cec5SDimitry Andric return "fp24";
11410b57cec5SDimitry Andric case UNW_PPC_F25:
11420b57cec5SDimitry Andric return "fp25";
11430b57cec5SDimitry Andric case UNW_PPC_F26:
11440b57cec5SDimitry Andric return "fp26";
11450b57cec5SDimitry Andric case UNW_PPC_F27:
11460b57cec5SDimitry Andric return "fp27";
11470b57cec5SDimitry Andric case UNW_PPC_F28:
11480b57cec5SDimitry Andric return "fp28";
11490b57cec5SDimitry Andric case UNW_PPC_F29:
11500b57cec5SDimitry Andric return "fp29";
11510b57cec5SDimitry Andric case UNW_PPC_F30:
11520b57cec5SDimitry Andric return "fp30";
11530b57cec5SDimitry Andric case UNW_PPC_F31:
11540b57cec5SDimitry Andric return "fp31";
11550b57cec5SDimitry Andric case UNW_PPC_LR:
11560b57cec5SDimitry Andric return "lr";
11570b57cec5SDimitry Andric default:
11580b57cec5SDimitry Andric return "unknown register";
11590b57cec5SDimitry Andric }
11600b57cec5SDimitry Andric
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_PPC
11630b57cec5SDimitry Andric
11640b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_PPC64)
11650b57cec5SDimitry Andric /// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
11660b57cec5SDimitry Andric /// process.
11670b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_ppc64 {
11680b57cec5SDimitry Andric public:
11690b57cec5SDimitry Andric Registers_ppc64();
11700b57cec5SDimitry Andric Registers_ppc64(const void *registers);
11710b57cec5SDimitry Andric
11720b57cec5SDimitry Andric bool validRegister(int num) const;
11730b57cec5SDimitry Andric uint64_t getRegister(int num) const;
11740b57cec5SDimitry Andric void setRegister(int num, uint64_t value);
11750b57cec5SDimitry Andric bool validFloatRegister(int num) const;
11760b57cec5SDimitry Andric double getFloatRegister(int num) const;
11770b57cec5SDimitry Andric void setFloatRegister(int num, double value);
11780b57cec5SDimitry Andric bool validVectorRegister(int num) const;
11790b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
11800b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
11810b57cec5SDimitry Andric static const char *getRegisterName(int num);
11820b57cec5SDimitry Andric void jumpto();
lastDwarfRegNum()118381ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
118481ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64;
118581ad6265SDimitry Andric }
getArch()11860b57cec5SDimitry Andric static int getArch() { return REGISTERS_PPC64; }
11870b57cec5SDimitry Andric
getSP() const11880b57cec5SDimitry Andric uint64_t getSP() const { return _registers.__r1; }
setSP(uint64_t value)11890b57cec5SDimitry Andric void setSP(uint64_t value) { _registers.__r1 = value; }
getIP() const11900b57cec5SDimitry Andric uint64_t getIP() const { return _registers.__srr0; }
setIP(uint64_t value)11910b57cec5SDimitry Andric void setIP(uint64_t value) { _registers.__srr0 = value; }
getCR() const119281ad6265SDimitry Andric uint64_t getCR() const { return _registers.__cr; }
setCR(uint64_t value)119381ad6265SDimitry Andric void setCR(uint64_t value) { _registers.__cr = value; }
getLR() const11945f757f3fSDimitry Andric uint64_t getLR() const { return _registers.__lr; }
setLR(uint64_t value)11955f757f3fSDimitry Andric void setLR(uint64_t value) { _registers.__lr = value; }
11960b57cec5SDimitry Andric
11970b57cec5SDimitry Andric private:
11980b57cec5SDimitry Andric struct ppc64_thread_state_t {
11990b57cec5SDimitry Andric uint64_t __srr0; // Instruction address register (PC)
12000b57cec5SDimitry Andric uint64_t __srr1; // Machine state register (supervisor)
12010b57cec5SDimitry Andric uint64_t __r0;
12020b57cec5SDimitry Andric uint64_t __r1;
12030b57cec5SDimitry Andric uint64_t __r2;
12040b57cec5SDimitry Andric uint64_t __r3;
12050b57cec5SDimitry Andric uint64_t __r4;
12060b57cec5SDimitry Andric uint64_t __r5;
12070b57cec5SDimitry Andric uint64_t __r6;
12080b57cec5SDimitry Andric uint64_t __r7;
12090b57cec5SDimitry Andric uint64_t __r8;
12100b57cec5SDimitry Andric uint64_t __r9;
12110b57cec5SDimitry Andric uint64_t __r10;
12120b57cec5SDimitry Andric uint64_t __r11;
12130b57cec5SDimitry Andric uint64_t __r12;
12140b57cec5SDimitry Andric uint64_t __r13;
12150b57cec5SDimitry Andric uint64_t __r14;
12160b57cec5SDimitry Andric uint64_t __r15;
12170b57cec5SDimitry Andric uint64_t __r16;
12180b57cec5SDimitry Andric uint64_t __r17;
12190b57cec5SDimitry Andric uint64_t __r18;
12200b57cec5SDimitry Andric uint64_t __r19;
12210b57cec5SDimitry Andric uint64_t __r20;
12220b57cec5SDimitry Andric uint64_t __r21;
12230b57cec5SDimitry Andric uint64_t __r22;
12240b57cec5SDimitry Andric uint64_t __r23;
12250b57cec5SDimitry Andric uint64_t __r24;
12260b57cec5SDimitry Andric uint64_t __r25;
12270b57cec5SDimitry Andric uint64_t __r26;
12280b57cec5SDimitry Andric uint64_t __r27;
12290b57cec5SDimitry Andric uint64_t __r28;
12300b57cec5SDimitry Andric uint64_t __r29;
12310b57cec5SDimitry Andric uint64_t __r30;
12320b57cec5SDimitry Andric uint64_t __r31;
12330b57cec5SDimitry Andric uint64_t __cr; // Condition register
12340b57cec5SDimitry Andric uint64_t __xer; // User's integer exception register
12350b57cec5SDimitry Andric uint64_t __lr; // Link register
12360b57cec5SDimitry Andric uint64_t __ctr; // Count register
12370b57cec5SDimitry Andric uint64_t __vrsave; // Vector Save Register
12380b57cec5SDimitry Andric };
12390b57cec5SDimitry Andric
12400b57cec5SDimitry Andric union ppc64_vsr_t {
12410b57cec5SDimitry Andric struct asfloat_s {
12420b57cec5SDimitry Andric double f;
12430b57cec5SDimitry Andric uint64_t v2;
12440b57cec5SDimitry Andric } asfloat;
12450b57cec5SDimitry Andric v128 v;
12460b57cec5SDimitry Andric };
12470b57cec5SDimitry Andric
12480b57cec5SDimitry Andric ppc64_thread_state_t _registers;
12490b57cec5SDimitry Andric ppc64_vsr_t _vectorScalarRegisters[64];
12500b57cec5SDimitry Andric
12510b57cec5SDimitry Andric static int getVectorRegNum(int num);
12520b57cec5SDimitry Andric };
12530b57cec5SDimitry Andric
Registers_ppc64(const void * registers)12540b57cec5SDimitry Andric inline Registers_ppc64::Registers_ppc64(const void *registers) {
12550b57cec5SDimitry Andric static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),
12560b57cec5SDimitry Andric "ppc64 registers do not fit into unw_context_t");
12570b57cec5SDimitry Andric memcpy(&_registers, static_cast<const uint8_t *>(registers),
12580b57cec5SDimitry Andric sizeof(_registers));
12590b57cec5SDimitry Andric static_assert(sizeof(_registers) == 312,
12600b57cec5SDimitry Andric "expected vector scalar register offset to be 312");
12610b57cec5SDimitry Andric memcpy(&_vectorScalarRegisters,
12620b57cec5SDimitry Andric static_cast<const uint8_t *>(registers) + sizeof(_registers),
12630b57cec5SDimitry Andric sizeof(_vectorScalarRegisters));
12640b57cec5SDimitry Andric static_assert(sizeof(_registers) +
12650b57cec5SDimitry Andric sizeof(_vectorScalarRegisters) == 1336,
12660b57cec5SDimitry Andric "expected vector register offset to be 1336 bytes");
12670b57cec5SDimitry Andric }
12680b57cec5SDimitry Andric
Registers_ppc64()12690b57cec5SDimitry Andric inline Registers_ppc64::Registers_ppc64() {
12700b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
12710b57cec5SDimitry Andric memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric
validRegister(int regNum) const12740b57cec5SDimitry Andric inline bool Registers_ppc64::validRegister(int regNum) const {
12750b57cec5SDimitry Andric switch (regNum) {
12760b57cec5SDimitry Andric case UNW_REG_IP:
12770b57cec5SDimitry Andric case UNW_REG_SP:
12780b57cec5SDimitry Andric case UNW_PPC64_XER:
12790b57cec5SDimitry Andric case UNW_PPC64_LR:
12800b57cec5SDimitry Andric case UNW_PPC64_CTR:
12810b57cec5SDimitry Andric case UNW_PPC64_VRSAVE:
12820b57cec5SDimitry Andric return true;
12830b57cec5SDimitry Andric }
12840b57cec5SDimitry Andric
12850b57cec5SDimitry Andric if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
12860b57cec5SDimitry Andric return true;
12870b57cec5SDimitry Andric if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
12880b57cec5SDimitry Andric return true;
12890b57cec5SDimitry Andric
12900b57cec5SDimitry Andric return false;
12910b57cec5SDimitry Andric }
12920b57cec5SDimitry Andric
getRegister(int regNum) const12930b57cec5SDimitry Andric inline uint64_t Registers_ppc64::getRegister(int regNum) const {
12940b57cec5SDimitry Andric switch (regNum) {
12950b57cec5SDimitry Andric case UNW_REG_IP:
12960b57cec5SDimitry Andric return _registers.__srr0;
12970b57cec5SDimitry Andric case UNW_PPC64_R0:
12980b57cec5SDimitry Andric return _registers.__r0;
12990b57cec5SDimitry Andric case UNW_PPC64_R1:
13000b57cec5SDimitry Andric case UNW_REG_SP:
13010b57cec5SDimitry Andric return _registers.__r1;
13020b57cec5SDimitry Andric case UNW_PPC64_R2:
13030b57cec5SDimitry Andric return _registers.__r2;
13040b57cec5SDimitry Andric case UNW_PPC64_R3:
13050b57cec5SDimitry Andric return _registers.__r3;
13060b57cec5SDimitry Andric case UNW_PPC64_R4:
13070b57cec5SDimitry Andric return _registers.__r4;
13080b57cec5SDimitry Andric case UNW_PPC64_R5:
13090b57cec5SDimitry Andric return _registers.__r5;
13100b57cec5SDimitry Andric case UNW_PPC64_R6:
13110b57cec5SDimitry Andric return _registers.__r6;
13120b57cec5SDimitry Andric case UNW_PPC64_R7:
13130b57cec5SDimitry Andric return _registers.__r7;
13140b57cec5SDimitry Andric case UNW_PPC64_R8:
13150b57cec5SDimitry Andric return _registers.__r8;
13160b57cec5SDimitry Andric case UNW_PPC64_R9:
13170b57cec5SDimitry Andric return _registers.__r9;
13180b57cec5SDimitry Andric case UNW_PPC64_R10:
13190b57cec5SDimitry Andric return _registers.__r10;
13200b57cec5SDimitry Andric case UNW_PPC64_R11:
13210b57cec5SDimitry Andric return _registers.__r11;
13220b57cec5SDimitry Andric case UNW_PPC64_R12:
13230b57cec5SDimitry Andric return _registers.__r12;
13240b57cec5SDimitry Andric case UNW_PPC64_R13:
13250b57cec5SDimitry Andric return _registers.__r13;
13260b57cec5SDimitry Andric case UNW_PPC64_R14:
13270b57cec5SDimitry Andric return _registers.__r14;
13280b57cec5SDimitry Andric case UNW_PPC64_R15:
13290b57cec5SDimitry Andric return _registers.__r15;
13300b57cec5SDimitry Andric case UNW_PPC64_R16:
13310b57cec5SDimitry Andric return _registers.__r16;
13320b57cec5SDimitry Andric case UNW_PPC64_R17:
13330b57cec5SDimitry Andric return _registers.__r17;
13340b57cec5SDimitry Andric case UNW_PPC64_R18:
13350b57cec5SDimitry Andric return _registers.__r18;
13360b57cec5SDimitry Andric case UNW_PPC64_R19:
13370b57cec5SDimitry Andric return _registers.__r19;
13380b57cec5SDimitry Andric case UNW_PPC64_R20:
13390b57cec5SDimitry Andric return _registers.__r20;
13400b57cec5SDimitry Andric case UNW_PPC64_R21:
13410b57cec5SDimitry Andric return _registers.__r21;
13420b57cec5SDimitry Andric case UNW_PPC64_R22:
13430b57cec5SDimitry Andric return _registers.__r22;
13440b57cec5SDimitry Andric case UNW_PPC64_R23:
13450b57cec5SDimitry Andric return _registers.__r23;
13460b57cec5SDimitry Andric case UNW_PPC64_R24:
13470b57cec5SDimitry Andric return _registers.__r24;
13480b57cec5SDimitry Andric case UNW_PPC64_R25:
13490b57cec5SDimitry Andric return _registers.__r25;
13500b57cec5SDimitry Andric case UNW_PPC64_R26:
13510b57cec5SDimitry Andric return _registers.__r26;
13520b57cec5SDimitry Andric case UNW_PPC64_R27:
13530b57cec5SDimitry Andric return _registers.__r27;
13540b57cec5SDimitry Andric case UNW_PPC64_R28:
13550b57cec5SDimitry Andric return _registers.__r28;
13560b57cec5SDimitry Andric case UNW_PPC64_R29:
13570b57cec5SDimitry Andric return _registers.__r29;
13580b57cec5SDimitry Andric case UNW_PPC64_R30:
13590b57cec5SDimitry Andric return _registers.__r30;
13600b57cec5SDimitry Andric case UNW_PPC64_R31:
13610b57cec5SDimitry Andric return _registers.__r31;
13620b57cec5SDimitry Andric case UNW_PPC64_CR0:
13630b57cec5SDimitry Andric return (_registers.__cr & 0xF0000000);
13640b57cec5SDimitry Andric case UNW_PPC64_CR1:
13650b57cec5SDimitry Andric return (_registers.__cr & 0x0F000000);
13660b57cec5SDimitry Andric case UNW_PPC64_CR2:
13670b57cec5SDimitry Andric return (_registers.__cr & 0x00F00000);
13680b57cec5SDimitry Andric case UNW_PPC64_CR3:
13690b57cec5SDimitry Andric return (_registers.__cr & 0x000F0000);
13700b57cec5SDimitry Andric case UNW_PPC64_CR4:
13710b57cec5SDimitry Andric return (_registers.__cr & 0x0000F000);
13720b57cec5SDimitry Andric case UNW_PPC64_CR5:
13730b57cec5SDimitry Andric return (_registers.__cr & 0x00000F00);
13740b57cec5SDimitry Andric case UNW_PPC64_CR6:
13750b57cec5SDimitry Andric return (_registers.__cr & 0x000000F0);
13760b57cec5SDimitry Andric case UNW_PPC64_CR7:
13770b57cec5SDimitry Andric return (_registers.__cr & 0x0000000F);
13780b57cec5SDimitry Andric case UNW_PPC64_XER:
13790b57cec5SDimitry Andric return _registers.__xer;
13800b57cec5SDimitry Andric case UNW_PPC64_LR:
13810b57cec5SDimitry Andric return _registers.__lr;
13820b57cec5SDimitry Andric case UNW_PPC64_CTR:
13830b57cec5SDimitry Andric return _registers.__ctr;
13840b57cec5SDimitry Andric case UNW_PPC64_VRSAVE:
13850b57cec5SDimitry Andric return _registers.__vrsave;
13860b57cec5SDimitry Andric }
13870b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported ppc64 register");
13880b57cec5SDimitry Andric }
13890b57cec5SDimitry Andric
setRegister(int regNum,uint64_t value)13900b57cec5SDimitry Andric inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
13910b57cec5SDimitry Andric switch (regNum) {
13920b57cec5SDimitry Andric case UNW_REG_IP:
13930b57cec5SDimitry Andric _registers.__srr0 = value;
13940b57cec5SDimitry Andric return;
13950b57cec5SDimitry Andric case UNW_PPC64_R0:
13960b57cec5SDimitry Andric _registers.__r0 = value;
13970b57cec5SDimitry Andric return;
13980b57cec5SDimitry Andric case UNW_PPC64_R1:
13990b57cec5SDimitry Andric case UNW_REG_SP:
14000b57cec5SDimitry Andric _registers.__r1 = value;
14010b57cec5SDimitry Andric return;
14020b57cec5SDimitry Andric case UNW_PPC64_R2:
14030b57cec5SDimitry Andric _registers.__r2 = value;
14040b57cec5SDimitry Andric return;
14050b57cec5SDimitry Andric case UNW_PPC64_R3:
14060b57cec5SDimitry Andric _registers.__r3 = value;
14070b57cec5SDimitry Andric return;
14080b57cec5SDimitry Andric case UNW_PPC64_R4:
14090b57cec5SDimitry Andric _registers.__r4 = value;
14100b57cec5SDimitry Andric return;
14110b57cec5SDimitry Andric case UNW_PPC64_R5:
14120b57cec5SDimitry Andric _registers.__r5 = value;
14130b57cec5SDimitry Andric return;
14140b57cec5SDimitry Andric case UNW_PPC64_R6:
14150b57cec5SDimitry Andric _registers.__r6 = value;
14160b57cec5SDimitry Andric return;
14170b57cec5SDimitry Andric case UNW_PPC64_R7:
14180b57cec5SDimitry Andric _registers.__r7 = value;
14190b57cec5SDimitry Andric return;
14200b57cec5SDimitry Andric case UNW_PPC64_R8:
14210b57cec5SDimitry Andric _registers.__r8 = value;
14220b57cec5SDimitry Andric return;
14230b57cec5SDimitry Andric case UNW_PPC64_R9:
14240b57cec5SDimitry Andric _registers.__r9 = value;
14250b57cec5SDimitry Andric return;
14260b57cec5SDimitry Andric case UNW_PPC64_R10:
14270b57cec5SDimitry Andric _registers.__r10 = value;
14280b57cec5SDimitry Andric return;
14290b57cec5SDimitry Andric case UNW_PPC64_R11:
14300b57cec5SDimitry Andric _registers.__r11 = value;
14310b57cec5SDimitry Andric return;
14320b57cec5SDimitry Andric case UNW_PPC64_R12:
14330b57cec5SDimitry Andric _registers.__r12 = value;
14340b57cec5SDimitry Andric return;
14350b57cec5SDimitry Andric case UNW_PPC64_R13:
14360b57cec5SDimitry Andric _registers.__r13 = value;
14370b57cec5SDimitry Andric return;
14380b57cec5SDimitry Andric case UNW_PPC64_R14:
14390b57cec5SDimitry Andric _registers.__r14 = value;
14400b57cec5SDimitry Andric return;
14410b57cec5SDimitry Andric case UNW_PPC64_R15:
14420b57cec5SDimitry Andric _registers.__r15 = value;
14430b57cec5SDimitry Andric return;
14440b57cec5SDimitry Andric case UNW_PPC64_R16:
14450b57cec5SDimitry Andric _registers.__r16 = value;
14460b57cec5SDimitry Andric return;
14470b57cec5SDimitry Andric case UNW_PPC64_R17:
14480b57cec5SDimitry Andric _registers.__r17 = value;
14490b57cec5SDimitry Andric return;
14500b57cec5SDimitry Andric case UNW_PPC64_R18:
14510b57cec5SDimitry Andric _registers.__r18 = value;
14520b57cec5SDimitry Andric return;
14530b57cec5SDimitry Andric case UNW_PPC64_R19:
14540b57cec5SDimitry Andric _registers.__r19 = value;
14550b57cec5SDimitry Andric return;
14560b57cec5SDimitry Andric case UNW_PPC64_R20:
14570b57cec5SDimitry Andric _registers.__r20 = value;
14580b57cec5SDimitry Andric return;
14590b57cec5SDimitry Andric case UNW_PPC64_R21:
14600b57cec5SDimitry Andric _registers.__r21 = value;
14610b57cec5SDimitry Andric return;
14620b57cec5SDimitry Andric case UNW_PPC64_R22:
14630b57cec5SDimitry Andric _registers.__r22 = value;
14640b57cec5SDimitry Andric return;
14650b57cec5SDimitry Andric case UNW_PPC64_R23:
14660b57cec5SDimitry Andric _registers.__r23 = value;
14670b57cec5SDimitry Andric return;
14680b57cec5SDimitry Andric case UNW_PPC64_R24:
14690b57cec5SDimitry Andric _registers.__r24 = value;
14700b57cec5SDimitry Andric return;
14710b57cec5SDimitry Andric case UNW_PPC64_R25:
14720b57cec5SDimitry Andric _registers.__r25 = value;
14730b57cec5SDimitry Andric return;
14740b57cec5SDimitry Andric case UNW_PPC64_R26:
14750b57cec5SDimitry Andric _registers.__r26 = value;
14760b57cec5SDimitry Andric return;
14770b57cec5SDimitry Andric case UNW_PPC64_R27:
14780b57cec5SDimitry Andric _registers.__r27 = value;
14790b57cec5SDimitry Andric return;
14800b57cec5SDimitry Andric case UNW_PPC64_R28:
14810b57cec5SDimitry Andric _registers.__r28 = value;
14820b57cec5SDimitry Andric return;
14830b57cec5SDimitry Andric case UNW_PPC64_R29:
14840b57cec5SDimitry Andric _registers.__r29 = value;
14850b57cec5SDimitry Andric return;
14860b57cec5SDimitry Andric case UNW_PPC64_R30:
14870b57cec5SDimitry Andric _registers.__r30 = value;
14880b57cec5SDimitry Andric return;
14890b57cec5SDimitry Andric case UNW_PPC64_R31:
14900b57cec5SDimitry Andric _registers.__r31 = value;
14910b57cec5SDimitry Andric return;
14920b57cec5SDimitry Andric case UNW_PPC64_CR0:
14930b57cec5SDimitry Andric _registers.__cr &= 0x0FFFFFFF;
14940b57cec5SDimitry Andric _registers.__cr |= (value & 0xF0000000);
14950b57cec5SDimitry Andric return;
14960b57cec5SDimitry Andric case UNW_PPC64_CR1:
14970b57cec5SDimitry Andric _registers.__cr &= 0xF0FFFFFF;
14980b57cec5SDimitry Andric _registers.__cr |= (value & 0x0F000000);
14990b57cec5SDimitry Andric return;
15000b57cec5SDimitry Andric case UNW_PPC64_CR2:
15010b57cec5SDimitry Andric _registers.__cr &= 0xFF0FFFFF;
15020b57cec5SDimitry Andric _registers.__cr |= (value & 0x00F00000);
15030b57cec5SDimitry Andric return;
15040b57cec5SDimitry Andric case UNW_PPC64_CR3:
15050b57cec5SDimitry Andric _registers.__cr &= 0xFFF0FFFF;
15060b57cec5SDimitry Andric _registers.__cr |= (value & 0x000F0000);
15070b57cec5SDimitry Andric return;
15080b57cec5SDimitry Andric case UNW_PPC64_CR4:
15090b57cec5SDimitry Andric _registers.__cr &= 0xFFFF0FFF;
15100b57cec5SDimitry Andric _registers.__cr |= (value & 0x0000F000);
15110b57cec5SDimitry Andric return;
15120b57cec5SDimitry Andric case UNW_PPC64_CR5:
15130b57cec5SDimitry Andric _registers.__cr &= 0xFFFFF0FF;
15140b57cec5SDimitry Andric _registers.__cr |= (value & 0x00000F00);
15150b57cec5SDimitry Andric return;
15160b57cec5SDimitry Andric case UNW_PPC64_CR6:
15170b57cec5SDimitry Andric _registers.__cr &= 0xFFFFFF0F;
15180b57cec5SDimitry Andric _registers.__cr |= (value & 0x000000F0);
15190b57cec5SDimitry Andric return;
15200b57cec5SDimitry Andric case UNW_PPC64_CR7:
15210b57cec5SDimitry Andric _registers.__cr &= 0xFFFFFFF0;
15220b57cec5SDimitry Andric _registers.__cr |= (value & 0x0000000F);
15230b57cec5SDimitry Andric return;
15240b57cec5SDimitry Andric case UNW_PPC64_XER:
15250b57cec5SDimitry Andric _registers.__xer = value;
15260b57cec5SDimitry Andric return;
15270b57cec5SDimitry Andric case UNW_PPC64_LR:
15280b57cec5SDimitry Andric _registers.__lr = value;
15290b57cec5SDimitry Andric return;
15300b57cec5SDimitry Andric case UNW_PPC64_CTR:
15310b57cec5SDimitry Andric _registers.__ctr = value;
15320b57cec5SDimitry Andric return;
15330b57cec5SDimitry Andric case UNW_PPC64_VRSAVE:
15340b57cec5SDimitry Andric _registers.__vrsave = value;
15350b57cec5SDimitry Andric return;
15360b57cec5SDimitry Andric }
15370b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported ppc64 register");
15380b57cec5SDimitry Andric }
15390b57cec5SDimitry Andric
validFloatRegister(int regNum) const15400b57cec5SDimitry Andric inline bool Registers_ppc64::validFloatRegister(int regNum) const {
15410b57cec5SDimitry Andric return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
15420b57cec5SDimitry Andric }
15430b57cec5SDimitry Andric
getFloatRegister(int regNum) const15440b57cec5SDimitry Andric inline double Registers_ppc64::getFloatRegister(int regNum) const {
15450b57cec5SDimitry Andric assert(validFloatRegister(regNum));
15460b57cec5SDimitry Andric return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
15470b57cec5SDimitry Andric }
15480b57cec5SDimitry Andric
setFloatRegister(int regNum,double value)15490b57cec5SDimitry Andric inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
15500b57cec5SDimitry Andric assert(validFloatRegister(regNum));
15510b57cec5SDimitry Andric _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
15520b57cec5SDimitry Andric }
15530b57cec5SDimitry Andric
validVectorRegister(int regNum) const15540b57cec5SDimitry Andric inline bool Registers_ppc64::validVectorRegister(int regNum) const {
1555e8d8bef9SDimitry Andric #if defined(__VSX__)
15560b57cec5SDimitry Andric if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
15570b57cec5SDimitry Andric return true;
15580b57cec5SDimitry Andric if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
15590b57cec5SDimitry Andric return true;
1560e8d8bef9SDimitry Andric #elif defined(__ALTIVEC__)
15610b57cec5SDimitry Andric if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
15620b57cec5SDimitry Andric return true;
15630b57cec5SDimitry Andric #endif
15640b57cec5SDimitry Andric return false;
15650b57cec5SDimitry Andric }
15660b57cec5SDimitry Andric
getVectorRegNum(int num)15670b57cec5SDimitry Andric inline int Registers_ppc64::getVectorRegNum(int num)
15680b57cec5SDimitry Andric {
15690b57cec5SDimitry Andric if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
15700b57cec5SDimitry Andric return num - UNW_PPC64_VS0;
15710b57cec5SDimitry Andric else
15720b57cec5SDimitry Andric return num - UNW_PPC64_VS32 + 32;
15730b57cec5SDimitry Andric }
15740b57cec5SDimitry Andric
getVectorRegister(int regNum) const15750b57cec5SDimitry Andric inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
15760b57cec5SDimitry Andric assert(validVectorRegister(regNum));
15770b57cec5SDimitry Andric return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
15780b57cec5SDimitry Andric }
15790b57cec5SDimitry Andric
setVectorRegister(int regNum,v128 value)15800b57cec5SDimitry Andric inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
15810b57cec5SDimitry Andric assert(validVectorRegister(regNum));
15820b57cec5SDimitry Andric _vectorScalarRegisters[getVectorRegNum(regNum)].v = value;
15830b57cec5SDimitry Andric }
15840b57cec5SDimitry Andric
getRegisterName(int regNum)15850b57cec5SDimitry Andric inline const char *Registers_ppc64::getRegisterName(int regNum) {
15860b57cec5SDimitry Andric switch (regNum) {
15870b57cec5SDimitry Andric case UNW_REG_IP:
15880b57cec5SDimitry Andric return "ip";
15890b57cec5SDimitry Andric case UNW_REG_SP:
15900b57cec5SDimitry Andric return "sp";
15910b57cec5SDimitry Andric case UNW_PPC64_R0:
15920b57cec5SDimitry Andric return "r0";
15930b57cec5SDimitry Andric case UNW_PPC64_R1:
15940b57cec5SDimitry Andric return "r1";
15950b57cec5SDimitry Andric case UNW_PPC64_R2:
15960b57cec5SDimitry Andric return "r2";
15970b57cec5SDimitry Andric case UNW_PPC64_R3:
15980b57cec5SDimitry Andric return "r3";
15990b57cec5SDimitry Andric case UNW_PPC64_R4:
16000b57cec5SDimitry Andric return "r4";
16010b57cec5SDimitry Andric case UNW_PPC64_R5:
16020b57cec5SDimitry Andric return "r5";
16030b57cec5SDimitry Andric case UNW_PPC64_R6:
16040b57cec5SDimitry Andric return "r6";
16050b57cec5SDimitry Andric case UNW_PPC64_R7:
16060b57cec5SDimitry Andric return "r7";
16070b57cec5SDimitry Andric case UNW_PPC64_R8:
16080b57cec5SDimitry Andric return "r8";
16090b57cec5SDimitry Andric case UNW_PPC64_R9:
16100b57cec5SDimitry Andric return "r9";
16110b57cec5SDimitry Andric case UNW_PPC64_R10:
16120b57cec5SDimitry Andric return "r10";
16130b57cec5SDimitry Andric case UNW_PPC64_R11:
16140b57cec5SDimitry Andric return "r11";
16150b57cec5SDimitry Andric case UNW_PPC64_R12:
16160b57cec5SDimitry Andric return "r12";
16170b57cec5SDimitry Andric case UNW_PPC64_R13:
16180b57cec5SDimitry Andric return "r13";
16190b57cec5SDimitry Andric case UNW_PPC64_R14:
16200b57cec5SDimitry Andric return "r14";
16210b57cec5SDimitry Andric case UNW_PPC64_R15:
16220b57cec5SDimitry Andric return "r15";
16230b57cec5SDimitry Andric case UNW_PPC64_R16:
16240b57cec5SDimitry Andric return "r16";
16250b57cec5SDimitry Andric case UNW_PPC64_R17:
16260b57cec5SDimitry Andric return "r17";
16270b57cec5SDimitry Andric case UNW_PPC64_R18:
16280b57cec5SDimitry Andric return "r18";
16290b57cec5SDimitry Andric case UNW_PPC64_R19:
16300b57cec5SDimitry Andric return "r19";
16310b57cec5SDimitry Andric case UNW_PPC64_R20:
16320b57cec5SDimitry Andric return "r20";
16330b57cec5SDimitry Andric case UNW_PPC64_R21:
16340b57cec5SDimitry Andric return "r21";
16350b57cec5SDimitry Andric case UNW_PPC64_R22:
16360b57cec5SDimitry Andric return "r22";
16370b57cec5SDimitry Andric case UNW_PPC64_R23:
16380b57cec5SDimitry Andric return "r23";
16390b57cec5SDimitry Andric case UNW_PPC64_R24:
16400b57cec5SDimitry Andric return "r24";
16410b57cec5SDimitry Andric case UNW_PPC64_R25:
16420b57cec5SDimitry Andric return "r25";
16430b57cec5SDimitry Andric case UNW_PPC64_R26:
16440b57cec5SDimitry Andric return "r26";
16450b57cec5SDimitry Andric case UNW_PPC64_R27:
16460b57cec5SDimitry Andric return "r27";
16470b57cec5SDimitry Andric case UNW_PPC64_R28:
16480b57cec5SDimitry Andric return "r28";
16490b57cec5SDimitry Andric case UNW_PPC64_R29:
16500b57cec5SDimitry Andric return "r29";
16510b57cec5SDimitry Andric case UNW_PPC64_R30:
16520b57cec5SDimitry Andric return "r30";
16530b57cec5SDimitry Andric case UNW_PPC64_R31:
16540b57cec5SDimitry Andric return "r31";
16550b57cec5SDimitry Andric case UNW_PPC64_CR0:
16560b57cec5SDimitry Andric return "cr0";
16570b57cec5SDimitry Andric case UNW_PPC64_CR1:
16580b57cec5SDimitry Andric return "cr1";
16590b57cec5SDimitry Andric case UNW_PPC64_CR2:
16600b57cec5SDimitry Andric return "cr2";
16610b57cec5SDimitry Andric case UNW_PPC64_CR3:
16620b57cec5SDimitry Andric return "cr3";
16630b57cec5SDimitry Andric case UNW_PPC64_CR4:
16640b57cec5SDimitry Andric return "cr4";
16650b57cec5SDimitry Andric case UNW_PPC64_CR5:
16660b57cec5SDimitry Andric return "cr5";
16670b57cec5SDimitry Andric case UNW_PPC64_CR6:
16680b57cec5SDimitry Andric return "cr6";
16690b57cec5SDimitry Andric case UNW_PPC64_CR7:
16700b57cec5SDimitry Andric return "cr7";
16710b57cec5SDimitry Andric case UNW_PPC64_XER:
16720b57cec5SDimitry Andric return "xer";
16730b57cec5SDimitry Andric case UNW_PPC64_LR:
16740b57cec5SDimitry Andric return "lr";
16750b57cec5SDimitry Andric case UNW_PPC64_CTR:
16760b57cec5SDimitry Andric return "ctr";
16770b57cec5SDimitry Andric case UNW_PPC64_VRSAVE:
16780b57cec5SDimitry Andric return "vrsave";
16790b57cec5SDimitry Andric case UNW_PPC64_F0:
16800b57cec5SDimitry Andric return "fp0";
16810b57cec5SDimitry Andric case UNW_PPC64_F1:
16820b57cec5SDimitry Andric return "fp1";
16830b57cec5SDimitry Andric case UNW_PPC64_F2:
16840b57cec5SDimitry Andric return "fp2";
16850b57cec5SDimitry Andric case UNW_PPC64_F3:
16860b57cec5SDimitry Andric return "fp3";
16870b57cec5SDimitry Andric case UNW_PPC64_F4:
16880b57cec5SDimitry Andric return "fp4";
16890b57cec5SDimitry Andric case UNW_PPC64_F5:
16900b57cec5SDimitry Andric return "fp5";
16910b57cec5SDimitry Andric case UNW_PPC64_F6:
16920b57cec5SDimitry Andric return "fp6";
16930b57cec5SDimitry Andric case UNW_PPC64_F7:
16940b57cec5SDimitry Andric return "fp7";
16950b57cec5SDimitry Andric case UNW_PPC64_F8:
16960b57cec5SDimitry Andric return "fp8";
16970b57cec5SDimitry Andric case UNW_PPC64_F9:
16980b57cec5SDimitry Andric return "fp9";
16990b57cec5SDimitry Andric case UNW_PPC64_F10:
17000b57cec5SDimitry Andric return "fp10";
17010b57cec5SDimitry Andric case UNW_PPC64_F11:
17020b57cec5SDimitry Andric return "fp11";
17030b57cec5SDimitry Andric case UNW_PPC64_F12:
17040b57cec5SDimitry Andric return "fp12";
17050b57cec5SDimitry Andric case UNW_PPC64_F13:
17060b57cec5SDimitry Andric return "fp13";
17070b57cec5SDimitry Andric case UNW_PPC64_F14:
17080b57cec5SDimitry Andric return "fp14";
17090b57cec5SDimitry Andric case UNW_PPC64_F15:
17100b57cec5SDimitry Andric return "fp15";
17110b57cec5SDimitry Andric case UNW_PPC64_F16:
17120b57cec5SDimitry Andric return "fp16";
17130b57cec5SDimitry Andric case UNW_PPC64_F17:
17140b57cec5SDimitry Andric return "fp17";
17150b57cec5SDimitry Andric case UNW_PPC64_F18:
17160b57cec5SDimitry Andric return "fp18";
17170b57cec5SDimitry Andric case UNW_PPC64_F19:
17180b57cec5SDimitry Andric return "fp19";
17190b57cec5SDimitry Andric case UNW_PPC64_F20:
17200b57cec5SDimitry Andric return "fp20";
17210b57cec5SDimitry Andric case UNW_PPC64_F21:
17220b57cec5SDimitry Andric return "fp21";
17230b57cec5SDimitry Andric case UNW_PPC64_F22:
17240b57cec5SDimitry Andric return "fp22";
17250b57cec5SDimitry Andric case UNW_PPC64_F23:
17260b57cec5SDimitry Andric return "fp23";
17270b57cec5SDimitry Andric case UNW_PPC64_F24:
17280b57cec5SDimitry Andric return "fp24";
17290b57cec5SDimitry Andric case UNW_PPC64_F25:
17300b57cec5SDimitry Andric return "fp25";
17310b57cec5SDimitry Andric case UNW_PPC64_F26:
17320b57cec5SDimitry Andric return "fp26";
17330b57cec5SDimitry Andric case UNW_PPC64_F27:
17340b57cec5SDimitry Andric return "fp27";
17350b57cec5SDimitry Andric case UNW_PPC64_F28:
17360b57cec5SDimitry Andric return "fp28";
17370b57cec5SDimitry Andric case UNW_PPC64_F29:
17380b57cec5SDimitry Andric return "fp29";
17390b57cec5SDimitry Andric case UNW_PPC64_F30:
17400b57cec5SDimitry Andric return "fp30";
17410b57cec5SDimitry Andric case UNW_PPC64_F31:
17420b57cec5SDimitry Andric return "fp31";
17430b57cec5SDimitry Andric case UNW_PPC64_V0:
17440b57cec5SDimitry Andric return "v0";
17450b57cec5SDimitry Andric case UNW_PPC64_V1:
17460b57cec5SDimitry Andric return "v1";
17470b57cec5SDimitry Andric case UNW_PPC64_V2:
17480b57cec5SDimitry Andric return "v2";
17490b57cec5SDimitry Andric case UNW_PPC64_V3:
17500b57cec5SDimitry Andric return "v3";
17510b57cec5SDimitry Andric case UNW_PPC64_V4:
17520b57cec5SDimitry Andric return "v4";
17530b57cec5SDimitry Andric case UNW_PPC64_V5:
17540b57cec5SDimitry Andric return "v5";
17550b57cec5SDimitry Andric case UNW_PPC64_V6:
17560b57cec5SDimitry Andric return "v6";
17570b57cec5SDimitry Andric case UNW_PPC64_V7:
17580b57cec5SDimitry Andric return "v7";
17590b57cec5SDimitry Andric case UNW_PPC64_V8:
17600b57cec5SDimitry Andric return "v8";
17610b57cec5SDimitry Andric case UNW_PPC64_V9:
17620b57cec5SDimitry Andric return "v9";
17630b57cec5SDimitry Andric case UNW_PPC64_V10:
17640b57cec5SDimitry Andric return "v10";
17650b57cec5SDimitry Andric case UNW_PPC64_V11:
17660b57cec5SDimitry Andric return "v11";
17670b57cec5SDimitry Andric case UNW_PPC64_V12:
17680b57cec5SDimitry Andric return "v12";
17690b57cec5SDimitry Andric case UNW_PPC64_V13:
17700b57cec5SDimitry Andric return "v13";
17710b57cec5SDimitry Andric case UNW_PPC64_V14:
17720b57cec5SDimitry Andric return "v14";
17730b57cec5SDimitry Andric case UNW_PPC64_V15:
17740b57cec5SDimitry Andric return "v15";
17750b57cec5SDimitry Andric case UNW_PPC64_V16:
17760b57cec5SDimitry Andric return "v16";
17770b57cec5SDimitry Andric case UNW_PPC64_V17:
17780b57cec5SDimitry Andric return "v17";
17790b57cec5SDimitry Andric case UNW_PPC64_V18:
17800b57cec5SDimitry Andric return "v18";
17810b57cec5SDimitry Andric case UNW_PPC64_V19:
17820b57cec5SDimitry Andric return "v19";
17830b57cec5SDimitry Andric case UNW_PPC64_V20:
17840b57cec5SDimitry Andric return "v20";
17850b57cec5SDimitry Andric case UNW_PPC64_V21:
17860b57cec5SDimitry Andric return "v21";
17870b57cec5SDimitry Andric case UNW_PPC64_V22:
17880b57cec5SDimitry Andric return "v22";
17890b57cec5SDimitry Andric case UNW_PPC64_V23:
17900b57cec5SDimitry Andric return "v23";
17910b57cec5SDimitry Andric case UNW_PPC64_V24:
17920b57cec5SDimitry Andric return "v24";
17930b57cec5SDimitry Andric case UNW_PPC64_V25:
17940b57cec5SDimitry Andric return "v25";
17950b57cec5SDimitry Andric case UNW_PPC64_V26:
17960b57cec5SDimitry Andric return "v26";
17970b57cec5SDimitry Andric case UNW_PPC64_V27:
17980b57cec5SDimitry Andric return "v27";
17990b57cec5SDimitry Andric case UNW_PPC64_V28:
18000b57cec5SDimitry Andric return "v28";
18010b57cec5SDimitry Andric case UNW_PPC64_V29:
18020b57cec5SDimitry Andric return "v29";
18030b57cec5SDimitry Andric case UNW_PPC64_V30:
18040b57cec5SDimitry Andric return "v30";
18050b57cec5SDimitry Andric case UNW_PPC64_V31:
18060b57cec5SDimitry Andric return "v31";
18070b57cec5SDimitry Andric }
18080b57cec5SDimitry Andric return "unknown register";
18090b57cec5SDimitry Andric }
18100b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_PPC64
18110b57cec5SDimitry Andric
18120b57cec5SDimitry Andric
18130b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_AARCH64)
18140b57cec5SDimitry Andric /// Registers_arm64 holds the register state of a thread in a 64-bit arm
18150b57cec5SDimitry Andric /// process.
1816e8d8bef9SDimitry Andric class _LIBUNWIND_HIDDEN Registers_arm64;
1817e8d8bef9SDimitry Andric extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
1818*62987288SDimitry Andric
1819*62987288SDimitry Andric #if defined(_LIBUNWIND_USE_GCS)
__libunwind_cet_get_jump_target()1820*62987288SDimitry Andric extern "C" void *__libunwind_cet_get_jump_target() {
1821*62987288SDimitry Andric return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto);
1822*62987288SDimitry Andric }
1823*62987288SDimitry Andric #endif
1824*62987288SDimitry Andric
18250b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_arm64 {
18260b57cec5SDimitry Andric public:
18270b57cec5SDimitry Andric Registers_arm64();
18280b57cec5SDimitry Andric Registers_arm64(const void *registers);
18290b57cec5SDimitry Andric
18300b57cec5SDimitry Andric bool validRegister(int num) const;
18310b57cec5SDimitry Andric uint64_t getRegister(int num) const;
18320b57cec5SDimitry Andric void setRegister(int num, uint64_t value);
18330b57cec5SDimitry Andric bool validFloatRegister(int num) const;
18340b57cec5SDimitry Andric double getFloatRegister(int num) const;
18350b57cec5SDimitry Andric void setFloatRegister(int num, double value);
18360b57cec5SDimitry Andric bool validVectorRegister(int num) const;
18370b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
18380b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
18390b57cec5SDimitry Andric static const char *getRegisterName(int num);
jumpto()1840e8d8bef9SDimitry Andric void jumpto() { __libunwind_Registers_arm64_jumpto(this); }
lastDwarfRegNum()184181ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
184281ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
184381ad6265SDimitry Andric }
getArch()18440b57cec5SDimitry Andric static int getArch() { return REGISTERS_ARM64; }
18450b57cec5SDimitry Andric
getSP() const18460b57cec5SDimitry Andric uint64_t getSP() const { return _registers.__sp; }
setSP(uint64_t value)18470b57cec5SDimitry Andric void setSP(uint64_t value) { _registers.__sp = value; }
getIP() const18480b57cec5SDimitry Andric uint64_t getIP() const { return _registers.__pc; }
setIP(uint64_t value)18490b57cec5SDimitry Andric void setIP(uint64_t value) { _registers.__pc = value; }
getFP() const18500b57cec5SDimitry Andric uint64_t getFP() const { return _registers.__fp; }
setFP(uint64_t value)18510b57cec5SDimitry Andric void setFP(uint64_t value) { _registers.__fp = value; }
18520b57cec5SDimitry Andric
18530b57cec5SDimitry Andric private:
18540b57cec5SDimitry Andric struct GPRs {
18550b57cec5SDimitry Andric uint64_t __x[29]; // x0-x28
18560b57cec5SDimitry Andric uint64_t __fp; // Frame pointer x29
18570b57cec5SDimitry Andric uint64_t __lr; // Link register x30
18580b57cec5SDimitry Andric uint64_t __sp; // Stack pointer x31
18590b57cec5SDimitry Andric uint64_t __pc; // Program counter
18600b57cec5SDimitry Andric uint64_t __ra_sign_state; // RA sign state register
18610b57cec5SDimitry Andric };
18620b57cec5SDimitry Andric
18630b57cec5SDimitry Andric GPRs _registers;
18640b57cec5SDimitry Andric double _vectorHalfRegisters[32];
18650b57cec5SDimitry Andric // Currently only the lower double in 128-bit vectore registers
18660b57cec5SDimitry Andric // is perserved during unwinding. We could define new register
18670b57cec5SDimitry Andric // numbers (> 96) which mean whole vector registers, then this
18680b57cec5SDimitry Andric // struct would need to change to contain whole vector registers.
18690b57cec5SDimitry Andric };
18700b57cec5SDimitry Andric
Registers_arm64(const void * registers)18710b57cec5SDimitry Andric inline Registers_arm64::Registers_arm64(const void *registers) {
18720b57cec5SDimitry Andric static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
18730b57cec5SDimitry Andric "arm64 registers do not fit into unw_context_t");
18740b57cec5SDimitry Andric memcpy(&_registers, registers, sizeof(_registers));
18750b57cec5SDimitry Andric static_assert(sizeof(GPRs) == 0x110,
18760b57cec5SDimitry Andric "expected VFP registers to be at offset 272");
18770b57cec5SDimitry Andric memcpy(_vectorHalfRegisters,
18780b57cec5SDimitry Andric static_cast<const uint8_t *>(registers) + sizeof(GPRs),
18790b57cec5SDimitry Andric sizeof(_vectorHalfRegisters));
18800b57cec5SDimitry Andric }
18810b57cec5SDimitry Andric
Registers_arm64()18820b57cec5SDimitry Andric inline Registers_arm64::Registers_arm64() {
18830b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
18840b57cec5SDimitry Andric memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
18850b57cec5SDimitry Andric }
18860b57cec5SDimitry Andric
validRegister(int regNum) const18870b57cec5SDimitry Andric inline bool Registers_arm64::validRegister(int regNum) const {
18880b57cec5SDimitry Andric if (regNum == UNW_REG_IP)
18890b57cec5SDimitry Andric return true;
18900b57cec5SDimitry Andric if (regNum == UNW_REG_SP)
18910b57cec5SDimitry Andric return true;
18920b57cec5SDimitry Andric if (regNum < 0)
18930b57cec5SDimitry Andric return false;
18940b57cec5SDimitry Andric if (regNum > 95)
18950b57cec5SDimitry Andric return false;
1896349cc55cSDimitry Andric if (regNum == UNW_AARCH64_RA_SIGN_STATE)
18970b57cec5SDimitry Andric return true;
1898fe6060f1SDimitry Andric if ((regNum > 32) && (regNum < 64))
18990b57cec5SDimitry Andric return false;
19000b57cec5SDimitry Andric return true;
19010b57cec5SDimitry Andric }
19020b57cec5SDimitry Andric
getRegister(int regNum) const19030b57cec5SDimitry Andric inline uint64_t Registers_arm64::getRegister(int regNum) const {
1904349cc55cSDimitry Andric if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
19050b57cec5SDimitry Andric return _registers.__pc;
1906349cc55cSDimitry Andric if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
19070b57cec5SDimitry Andric return _registers.__sp;
1908349cc55cSDimitry Andric if (regNum == UNW_AARCH64_RA_SIGN_STATE)
19090b57cec5SDimitry Andric return _registers.__ra_sign_state;
1910349cc55cSDimitry Andric if (regNum == UNW_AARCH64_FP)
1911fe6060f1SDimitry Andric return _registers.__fp;
1912349cc55cSDimitry Andric if (regNum == UNW_AARCH64_LR)
1913fe6060f1SDimitry Andric return _registers.__lr;
1914fe6060f1SDimitry Andric if ((regNum >= 0) && (regNum < 29))
19150b57cec5SDimitry Andric return _registers.__x[regNum];
19160b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported arm64 register");
19170b57cec5SDimitry Andric }
19180b57cec5SDimitry Andric
setRegister(int regNum,uint64_t value)19190b57cec5SDimitry Andric inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1920349cc55cSDimitry Andric if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
19210b57cec5SDimitry Andric _registers.__pc = value;
1922349cc55cSDimitry Andric else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
19230b57cec5SDimitry Andric _registers.__sp = value;
1924349cc55cSDimitry Andric else if (regNum == UNW_AARCH64_RA_SIGN_STATE)
19250b57cec5SDimitry Andric _registers.__ra_sign_state = value;
1926349cc55cSDimitry Andric else if (regNum == UNW_AARCH64_FP)
1927fe6060f1SDimitry Andric _registers.__fp = value;
1928349cc55cSDimitry Andric else if (regNum == UNW_AARCH64_LR)
1929fe6060f1SDimitry Andric _registers.__lr = value;
1930fe6060f1SDimitry Andric else if ((regNum >= 0) && (regNum < 29))
19310b57cec5SDimitry Andric _registers.__x[regNum] = value;
19320b57cec5SDimitry Andric else
19330b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported arm64 register");
19340b57cec5SDimitry Andric }
19350b57cec5SDimitry Andric
getRegisterName(int regNum)19360b57cec5SDimitry Andric inline const char *Registers_arm64::getRegisterName(int regNum) {
19370b57cec5SDimitry Andric switch (regNum) {
19380b57cec5SDimitry Andric case UNW_REG_IP:
19390b57cec5SDimitry Andric return "pc";
19400b57cec5SDimitry Andric case UNW_REG_SP:
19410b57cec5SDimitry Andric return "sp";
1942349cc55cSDimitry Andric case UNW_AARCH64_X0:
19430b57cec5SDimitry Andric return "x0";
1944349cc55cSDimitry Andric case UNW_AARCH64_X1:
19450b57cec5SDimitry Andric return "x1";
1946349cc55cSDimitry Andric case UNW_AARCH64_X2:
19470b57cec5SDimitry Andric return "x2";
1948349cc55cSDimitry Andric case UNW_AARCH64_X3:
19490b57cec5SDimitry Andric return "x3";
1950349cc55cSDimitry Andric case UNW_AARCH64_X4:
19510b57cec5SDimitry Andric return "x4";
1952349cc55cSDimitry Andric case UNW_AARCH64_X5:
19530b57cec5SDimitry Andric return "x5";
1954349cc55cSDimitry Andric case UNW_AARCH64_X6:
19550b57cec5SDimitry Andric return "x6";
1956349cc55cSDimitry Andric case UNW_AARCH64_X7:
19570b57cec5SDimitry Andric return "x7";
1958349cc55cSDimitry Andric case UNW_AARCH64_X8:
19590b57cec5SDimitry Andric return "x8";
1960349cc55cSDimitry Andric case UNW_AARCH64_X9:
19610b57cec5SDimitry Andric return "x9";
1962349cc55cSDimitry Andric case UNW_AARCH64_X10:
19630b57cec5SDimitry Andric return "x10";
1964349cc55cSDimitry Andric case UNW_AARCH64_X11:
19650b57cec5SDimitry Andric return "x11";
1966349cc55cSDimitry Andric case UNW_AARCH64_X12:
19670b57cec5SDimitry Andric return "x12";
1968349cc55cSDimitry Andric case UNW_AARCH64_X13:
19690b57cec5SDimitry Andric return "x13";
1970349cc55cSDimitry Andric case UNW_AARCH64_X14:
19710b57cec5SDimitry Andric return "x14";
1972349cc55cSDimitry Andric case UNW_AARCH64_X15:
19730b57cec5SDimitry Andric return "x15";
1974349cc55cSDimitry Andric case UNW_AARCH64_X16:
19750b57cec5SDimitry Andric return "x16";
1976349cc55cSDimitry Andric case UNW_AARCH64_X17:
19770b57cec5SDimitry Andric return "x17";
1978349cc55cSDimitry Andric case UNW_AARCH64_X18:
19790b57cec5SDimitry Andric return "x18";
1980349cc55cSDimitry Andric case UNW_AARCH64_X19:
19810b57cec5SDimitry Andric return "x19";
1982349cc55cSDimitry Andric case UNW_AARCH64_X20:
19830b57cec5SDimitry Andric return "x20";
1984349cc55cSDimitry Andric case UNW_AARCH64_X21:
19850b57cec5SDimitry Andric return "x21";
1986349cc55cSDimitry Andric case UNW_AARCH64_X22:
19870b57cec5SDimitry Andric return "x22";
1988349cc55cSDimitry Andric case UNW_AARCH64_X23:
19890b57cec5SDimitry Andric return "x23";
1990349cc55cSDimitry Andric case UNW_AARCH64_X24:
19910b57cec5SDimitry Andric return "x24";
1992349cc55cSDimitry Andric case UNW_AARCH64_X25:
19930b57cec5SDimitry Andric return "x25";
1994349cc55cSDimitry Andric case UNW_AARCH64_X26:
19950b57cec5SDimitry Andric return "x26";
1996349cc55cSDimitry Andric case UNW_AARCH64_X27:
19970b57cec5SDimitry Andric return "x27";
1998349cc55cSDimitry Andric case UNW_AARCH64_X28:
19990b57cec5SDimitry Andric return "x28";
2000349cc55cSDimitry Andric case UNW_AARCH64_FP:
20010b57cec5SDimitry Andric return "fp";
2002349cc55cSDimitry Andric case UNW_AARCH64_LR:
20030b57cec5SDimitry Andric return "lr";
2004349cc55cSDimitry Andric case UNW_AARCH64_SP:
20050b57cec5SDimitry Andric return "sp";
2006349cc55cSDimitry Andric case UNW_AARCH64_PC:
2007fe6060f1SDimitry Andric return "pc";
2008349cc55cSDimitry Andric case UNW_AARCH64_V0:
20090b57cec5SDimitry Andric return "d0";
2010349cc55cSDimitry Andric case UNW_AARCH64_V1:
20110b57cec5SDimitry Andric return "d1";
2012349cc55cSDimitry Andric case UNW_AARCH64_V2:
20130b57cec5SDimitry Andric return "d2";
2014349cc55cSDimitry Andric case UNW_AARCH64_V3:
20150b57cec5SDimitry Andric return "d3";
2016349cc55cSDimitry Andric case UNW_AARCH64_V4:
20170b57cec5SDimitry Andric return "d4";
2018349cc55cSDimitry Andric case UNW_AARCH64_V5:
20190b57cec5SDimitry Andric return "d5";
2020349cc55cSDimitry Andric case UNW_AARCH64_V6:
20210b57cec5SDimitry Andric return "d6";
2022349cc55cSDimitry Andric case UNW_AARCH64_V7:
20230b57cec5SDimitry Andric return "d7";
2024349cc55cSDimitry Andric case UNW_AARCH64_V8:
20250b57cec5SDimitry Andric return "d8";
2026349cc55cSDimitry Andric case UNW_AARCH64_V9:
20270b57cec5SDimitry Andric return "d9";
2028349cc55cSDimitry Andric case UNW_AARCH64_V10:
20290b57cec5SDimitry Andric return "d10";
2030349cc55cSDimitry Andric case UNW_AARCH64_V11:
20310b57cec5SDimitry Andric return "d11";
2032349cc55cSDimitry Andric case UNW_AARCH64_V12:
20330b57cec5SDimitry Andric return "d12";
2034349cc55cSDimitry Andric case UNW_AARCH64_V13:
20350b57cec5SDimitry Andric return "d13";
2036349cc55cSDimitry Andric case UNW_AARCH64_V14:
20370b57cec5SDimitry Andric return "d14";
2038349cc55cSDimitry Andric case UNW_AARCH64_V15:
20390b57cec5SDimitry Andric return "d15";
2040349cc55cSDimitry Andric case UNW_AARCH64_V16:
20410b57cec5SDimitry Andric return "d16";
2042349cc55cSDimitry Andric case UNW_AARCH64_V17:
20430b57cec5SDimitry Andric return "d17";
2044349cc55cSDimitry Andric case UNW_AARCH64_V18:
20450b57cec5SDimitry Andric return "d18";
2046349cc55cSDimitry Andric case UNW_AARCH64_V19:
20470b57cec5SDimitry Andric return "d19";
2048349cc55cSDimitry Andric case UNW_AARCH64_V20:
20490b57cec5SDimitry Andric return "d20";
2050349cc55cSDimitry Andric case UNW_AARCH64_V21:
20510b57cec5SDimitry Andric return "d21";
2052349cc55cSDimitry Andric case UNW_AARCH64_V22:
20530b57cec5SDimitry Andric return "d22";
2054349cc55cSDimitry Andric case UNW_AARCH64_V23:
20550b57cec5SDimitry Andric return "d23";
2056349cc55cSDimitry Andric case UNW_AARCH64_V24:
20570b57cec5SDimitry Andric return "d24";
2058349cc55cSDimitry Andric case UNW_AARCH64_V25:
20590b57cec5SDimitry Andric return "d25";
2060349cc55cSDimitry Andric case UNW_AARCH64_V26:
20610b57cec5SDimitry Andric return "d26";
2062349cc55cSDimitry Andric case UNW_AARCH64_V27:
20630b57cec5SDimitry Andric return "d27";
2064349cc55cSDimitry Andric case UNW_AARCH64_V28:
20650b57cec5SDimitry Andric return "d28";
2066349cc55cSDimitry Andric case UNW_AARCH64_V29:
20670b57cec5SDimitry Andric return "d29";
2068349cc55cSDimitry Andric case UNW_AARCH64_V30:
20690b57cec5SDimitry Andric return "d30";
2070349cc55cSDimitry Andric case UNW_AARCH64_V31:
20710b57cec5SDimitry Andric return "d31";
20720b57cec5SDimitry Andric default:
20730b57cec5SDimitry Andric return "unknown register";
20740b57cec5SDimitry Andric }
20750b57cec5SDimitry Andric }
20760b57cec5SDimitry Andric
validFloatRegister(int regNum) const20770b57cec5SDimitry Andric inline bool Registers_arm64::validFloatRegister(int regNum) const {
2078349cc55cSDimitry Andric if (regNum < UNW_AARCH64_V0)
20790b57cec5SDimitry Andric return false;
2080349cc55cSDimitry Andric if (regNum > UNW_AARCH64_V31)
20810b57cec5SDimitry Andric return false;
20820b57cec5SDimitry Andric return true;
20830b57cec5SDimitry Andric }
20840b57cec5SDimitry Andric
getFloatRegister(int regNum) const20850b57cec5SDimitry Andric inline double Registers_arm64::getFloatRegister(int regNum) const {
20860b57cec5SDimitry Andric assert(validFloatRegister(regNum));
2087349cc55cSDimitry Andric return _vectorHalfRegisters[regNum - UNW_AARCH64_V0];
20880b57cec5SDimitry Andric }
20890b57cec5SDimitry Andric
setFloatRegister(int regNum,double value)20900b57cec5SDimitry Andric inline void Registers_arm64::setFloatRegister(int regNum, double value) {
20910b57cec5SDimitry Andric assert(validFloatRegister(regNum));
2092349cc55cSDimitry Andric _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value;
20930b57cec5SDimitry Andric }
20940b57cec5SDimitry Andric
validVectorRegister(int) const20950b57cec5SDimitry Andric inline bool Registers_arm64::validVectorRegister(int) const {
20960b57cec5SDimitry Andric return false;
20970b57cec5SDimitry Andric }
20980b57cec5SDimitry Andric
getVectorRegister(int) const20990b57cec5SDimitry Andric inline v128 Registers_arm64::getVectorRegister(int) const {
21000b57cec5SDimitry Andric _LIBUNWIND_ABORT("no arm64 vector register support yet");
21010b57cec5SDimitry Andric }
21020b57cec5SDimitry Andric
setVectorRegister(int,v128)21030b57cec5SDimitry Andric inline void Registers_arm64::setVectorRegister(int, v128) {
21040b57cec5SDimitry Andric _LIBUNWIND_ABORT("no arm64 vector register support yet");
21050b57cec5SDimitry Andric }
21060b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_AARCH64
21070b57cec5SDimitry Andric
21080b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_ARM)
21090b57cec5SDimitry Andric /// Registers_arm holds the register state of a thread in a 32-bit arm
21100b57cec5SDimitry Andric /// process.
21110b57cec5SDimitry Andric ///
21120b57cec5SDimitry Andric /// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
21130b57cec5SDimitry Andric /// this uses more memory than required.
21140b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_arm {
21150b57cec5SDimitry Andric public:
21160b57cec5SDimitry Andric Registers_arm();
21170b57cec5SDimitry Andric Registers_arm(const void *registers);
21180b57cec5SDimitry Andric
21190b57cec5SDimitry Andric bool validRegister(int num) const;
21200b57cec5SDimitry Andric uint32_t getRegister(int num) const;
21210b57cec5SDimitry Andric void setRegister(int num, uint32_t value);
21220b57cec5SDimitry Andric bool validFloatRegister(int num) const;
21230b57cec5SDimitry Andric unw_fpreg_t getFloatRegister(int num);
21240b57cec5SDimitry Andric void setFloatRegister(int num, unw_fpreg_t value);
21250b57cec5SDimitry Andric bool validVectorRegister(int num) const;
21260b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
21270b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
21280b57cec5SDimitry Andric static const char *getRegisterName(int num);
jumpto()21290b57cec5SDimitry Andric void jumpto() {
21300b57cec5SDimitry Andric restoreSavedFloatRegisters();
21310b57cec5SDimitry Andric restoreCoreAndJumpTo();
21320b57cec5SDimitry Andric }
lastDwarfRegNum()213381ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
213481ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM;
213581ad6265SDimitry Andric }
getArch()21360b57cec5SDimitry Andric static int getArch() { return REGISTERS_ARM; }
21370b57cec5SDimitry Andric
getSP() const21380b57cec5SDimitry Andric uint32_t getSP() const { return _registers.__sp; }
setSP(uint32_t value)21390b57cec5SDimitry Andric void setSP(uint32_t value) { _registers.__sp = value; }
getIP() const21400b57cec5SDimitry Andric uint32_t getIP() const { return _registers.__pc; }
setIP(uint32_t value)21410b57cec5SDimitry Andric void setIP(uint32_t value) { _registers.__pc = value; }
21420b57cec5SDimitry Andric
saveVFPAsX()21430b57cec5SDimitry Andric void saveVFPAsX() {
21440b57cec5SDimitry Andric assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
21450b57cec5SDimitry Andric _use_X_for_vfp_save = true;
21460b57cec5SDimitry Andric }
21470b57cec5SDimitry Andric
restoreSavedFloatRegisters()21480b57cec5SDimitry Andric void restoreSavedFloatRegisters() {
21490b57cec5SDimitry Andric if (_saved_vfp_d0_d15) {
21500b57cec5SDimitry Andric if (_use_X_for_vfp_save)
21510b57cec5SDimitry Andric restoreVFPWithFLDMX(_vfp_d0_d15_pad);
21520b57cec5SDimitry Andric else
21530b57cec5SDimitry Andric restoreVFPWithFLDMD(_vfp_d0_d15_pad);
21540b57cec5SDimitry Andric }
21550b57cec5SDimitry Andric if (_saved_vfp_d16_d31)
21560b57cec5SDimitry Andric restoreVFPv3(_vfp_d16_d31);
21570b57cec5SDimitry Andric #if defined(__ARM_WMMX)
21580b57cec5SDimitry Andric if (_saved_iwmmx)
21590b57cec5SDimitry Andric restoreiWMMX(_iwmmx);
21600b57cec5SDimitry Andric if (_saved_iwmmx_control)
21610b57cec5SDimitry Andric restoreiWMMXControl(_iwmmx_control);
21620b57cec5SDimitry Andric #endif
21630b57cec5SDimitry Andric }
21640b57cec5SDimitry Andric
21650b57cec5SDimitry Andric private:
21660b57cec5SDimitry Andric struct GPRs {
21670b57cec5SDimitry Andric uint32_t __r[13]; // r0-r12
21680b57cec5SDimitry Andric uint32_t __sp; // Stack pointer r13
21690b57cec5SDimitry Andric uint32_t __lr; // Link register r14
21700b57cec5SDimitry Andric uint32_t __pc; // Program counter r15
21710b57cec5SDimitry Andric };
21720b57cec5SDimitry Andric
21730eae32dcSDimitry Andric struct PseudoRegisters {
21740eae32dcSDimitry Andric uint32_t __pac; // Return Authentication Code (PAC)
21750eae32dcSDimitry Andric };
21760eae32dcSDimitry Andric
21770b57cec5SDimitry Andric static void saveVFPWithFSTMD(void*);
21780b57cec5SDimitry Andric static void saveVFPWithFSTMX(void*);
21790b57cec5SDimitry Andric static void saveVFPv3(void*);
21800b57cec5SDimitry Andric static void restoreVFPWithFLDMD(void*);
21810b57cec5SDimitry Andric static void restoreVFPWithFLDMX(void*);
21820b57cec5SDimitry Andric static void restoreVFPv3(void*);
21830b57cec5SDimitry Andric #if defined(__ARM_WMMX)
21840b57cec5SDimitry Andric static void saveiWMMX(void*);
21850b57cec5SDimitry Andric static void saveiWMMXControl(uint32_t*);
21860b57cec5SDimitry Andric static void restoreiWMMX(void*);
21870b57cec5SDimitry Andric static void restoreiWMMXControl(uint32_t*);
21880b57cec5SDimitry Andric #endif
21890b57cec5SDimitry Andric void restoreCoreAndJumpTo();
21900b57cec5SDimitry Andric
21910b57cec5SDimitry Andric // ARM registers
21920b57cec5SDimitry Andric GPRs _registers;
21930eae32dcSDimitry Andric PseudoRegisters _pseudo_registers;
21940b57cec5SDimitry Andric
21950b57cec5SDimitry Andric // We save floating point registers lazily because we can't know ahead of
21960b57cec5SDimitry Andric // time which ones are used. See EHABI #4.7.
21970b57cec5SDimitry Andric
21980b57cec5SDimitry Andric // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
21990b57cec5SDimitry Andric //
22000b57cec5SDimitry Andric // See EHABI #7.5 that explains how matching instruction sequences for load
22010b57cec5SDimitry Andric // and store need to be used to correctly restore the exact register bits.
22020b57cec5SDimitry Andric bool _use_X_for_vfp_save;
22030b57cec5SDimitry Andric // Whether VFP D0-D15 are saved.
22040b57cec5SDimitry Andric bool _saved_vfp_d0_d15;
22050b57cec5SDimitry Andric // Whether VFPv3 D16-D31 are saved.
22060b57cec5SDimitry Andric bool _saved_vfp_d16_d31;
22070b57cec5SDimitry Andric // VFP registers D0-D15, + padding if saved using FSTMX
22080b57cec5SDimitry Andric unw_fpreg_t _vfp_d0_d15_pad[17];
22090b57cec5SDimitry Andric // VFPv3 registers D16-D31, always saved using FSTMD
22100b57cec5SDimitry Andric unw_fpreg_t _vfp_d16_d31[16];
22110b57cec5SDimitry Andric #if defined(__ARM_WMMX)
22120b57cec5SDimitry Andric // Whether iWMMX data registers are saved.
22130b57cec5SDimitry Andric bool _saved_iwmmx;
22140b57cec5SDimitry Andric // Whether iWMMX control registers are saved.
22150b57cec5SDimitry Andric mutable bool _saved_iwmmx_control;
22160b57cec5SDimitry Andric // iWMMX registers
22170b57cec5SDimitry Andric unw_fpreg_t _iwmmx[16];
22180b57cec5SDimitry Andric // iWMMX control registers
22190b57cec5SDimitry Andric mutable uint32_t _iwmmx_control[4];
22200b57cec5SDimitry Andric #endif
22210b57cec5SDimitry Andric };
22220b57cec5SDimitry Andric
Registers_arm(const void * registers)22230b57cec5SDimitry Andric inline Registers_arm::Registers_arm(const void *registers)
22240b57cec5SDimitry Andric : _use_X_for_vfp_save(false),
22250b57cec5SDimitry Andric _saved_vfp_d0_d15(false),
22260b57cec5SDimitry Andric _saved_vfp_d16_d31(false) {
22270b57cec5SDimitry Andric static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
22280b57cec5SDimitry Andric "arm registers do not fit into unw_context_t");
22290b57cec5SDimitry Andric // See __unw_getcontext() note about data.
22300b57cec5SDimitry Andric memcpy(&_registers, registers, sizeof(_registers));
22310eae32dcSDimitry Andric memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));
22320b57cec5SDimitry Andric memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
22330b57cec5SDimitry Andric memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
22340b57cec5SDimitry Andric #if defined(__ARM_WMMX)
22350b57cec5SDimitry Andric _saved_iwmmx = false;
22360b57cec5SDimitry Andric _saved_iwmmx_control = false;
22370b57cec5SDimitry Andric memset(&_iwmmx, 0, sizeof(_iwmmx));
22380b57cec5SDimitry Andric memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
22390b57cec5SDimitry Andric #endif
22400b57cec5SDimitry Andric }
22410b57cec5SDimitry Andric
Registers_arm()22420b57cec5SDimitry Andric inline Registers_arm::Registers_arm()
22430b57cec5SDimitry Andric : _use_X_for_vfp_save(false),
22440b57cec5SDimitry Andric _saved_vfp_d0_d15(false),
22450b57cec5SDimitry Andric _saved_vfp_d16_d31(false) {
22460b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
22470eae32dcSDimitry Andric memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));
22480b57cec5SDimitry Andric memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
22490b57cec5SDimitry Andric memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
22500b57cec5SDimitry Andric #if defined(__ARM_WMMX)
22510b57cec5SDimitry Andric _saved_iwmmx = false;
22520b57cec5SDimitry Andric _saved_iwmmx_control = false;
22530b57cec5SDimitry Andric memset(&_iwmmx, 0, sizeof(_iwmmx));
22540b57cec5SDimitry Andric memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
22550b57cec5SDimitry Andric #endif
22560b57cec5SDimitry Andric }
22570b57cec5SDimitry Andric
validRegister(int regNum) const22580b57cec5SDimitry Andric inline bool Registers_arm::validRegister(int regNum) const {
22590b57cec5SDimitry Andric // Returns true for all non-VFP registers supported by the EHABI
22600b57cec5SDimitry Andric // virtual register set (VRS).
22610b57cec5SDimitry Andric if (regNum == UNW_REG_IP)
22620b57cec5SDimitry Andric return true;
22630b57cec5SDimitry Andric
22640b57cec5SDimitry Andric if (regNum == UNW_REG_SP)
22650b57cec5SDimitry Andric return true;
22660b57cec5SDimitry Andric
22670b57cec5SDimitry Andric if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
22680b57cec5SDimitry Andric return true;
22690b57cec5SDimitry Andric
22700b57cec5SDimitry Andric #if defined(__ARM_WMMX)
22710b57cec5SDimitry Andric if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
22720b57cec5SDimitry Andric return true;
22730b57cec5SDimitry Andric #endif
22740b57cec5SDimitry Andric
22750eae32dcSDimitry Andric #ifdef __ARM_FEATURE_PAUTH
22760eae32dcSDimitry Andric if (regNum == UNW_ARM_RA_AUTH_CODE)
22770eae32dcSDimitry Andric return true;
22780eae32dcSDimitry Andric #endif
22790eae32dcSDimitry Andric
22800b57cec5SDimitry Andric return false;
22810b57cec5SDimitry Andric }
22820b57cec5SDimitry Andric
getRegister(int regNum) const22830b57cec5SDimitry Andric inline uint32_t Registers_arm::getRegister(int regNum) const {
22840b57cec5SDimitry Andric if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
22850b57cec5SDimitry Andric return _registers.__sp;
22860b57cec5SDimitry Andric
22870b57cec5SDimitry Andric if (regNum == UNW_ARM_LR)
22880b57cec5SDimitry Andric return _registers.__lr;
22890b57cec5SDimitry Andric
22900b57cec5SDimitry Andric if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
22910b57cec5SDimitry Andric return _registers.__pc;
22920b57cec5SDimitry Andric
22930b57cec5SDimitry Andric if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
22940b57cec5SDimitry Andric return _registers.__r[regNum];
22950b57cec5SDimitry Andric
22960b57cec5SDimitry Andric #if defined(__ARM_WMMX)
22970b57cec5SDimitry Andric if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
22980b57cec5SDimitry Andric if (!_saved_iwmmx_control) {
22990b57cec5SDimitry Andric _saved_iwmmx_control = true;
23000b57cec5SDimitry Andric saveiWMMXControl(_iwmmx_control);
23010b57cec5SDimitry Andric }
23020b57cec5SDimitry Andric return _iwmmx_control[regNum - UNW_ARM_WC0];
23030b57cec5SDimitry Andric }
23040b57cec5SDimitry Andric #endif
23050b57cec5SDimitry Andric
23060eae32dcSDimitry Andric #ifdef __ARM_FEATURE_PAUTH
23070eae32dcSDimitry Andric if (regNum == UNW_ARM_RA_AUTH_CODE)
23080eae32dcSDimitry Andric return _pseudo_registers.__pac;
23090eae32dcSDimitry Andric #endif
23100eae32dcSDimitry Andric
23110b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported arm register");
23120b57cec5SDimitry Andric }
23130b57cec5SDimitry Andric
setRegister(int regNum,uint32_t value)23140b57cec5SDimitry Andric inline void Registers_arm::setRegister(int regNum, uint32_t value) {
23150b57cec5SDimitry Andric if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
23160b57cec5SDimitry Andric _registers.__sp = value;
23170b57cec5SDimitry Andric return;
23180b57cec5SDimitry Andric }
23190b57cec5SDimitry Andric
23200b57cec5SDimitry Andric if (regNum == UNW_ARM_LR) {
23210b57cec5SDimitry Andric _registers.__lr = value;
23220b57cec5SDimitry Andric return;
23230b57cec5SDimitry Andric }
23240b57cec5SDimitry Andric
23250b57cec5SDimitry Andric if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
23260b57cec5SDimitry Andric _registers.__pc = value;
23270b57cec5SDimitry Andric return;
23280b57cec5SDimitry Andric }
23290b57cec5SDimitry Andric
23300b57cec5SDimitry Andric if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
23310b57cec5SDimitry Andric _registers.__r[regNum] = value;
23320b57cec5SDimitry Andric return;
23330b57cec5SDimitry Andric }
23340b57cec5SDimitry Andric
23350b57cec5SDimitry Andric #if defined(__ARM_WMMX)
23360b57cec5SDimitry Andric if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
23370b57cec5SDimitry Andric if (!_saved_iwmmx_control) {
23380b57cec5SDimitry Andric _saved_iwmmx_control = true;
23390b57cec5SDimitry Andric saveiWMMXControl(_iwmmx_control);
23400b57cec5SDimitry Andric }
23410b57cec5SDimitry Andric _iwmmx_control[regNum - UNW_ARM_WC0] = value;
23420b57cec5SDimitry Andric return;
23430b57cec5SDimitry Andric }
23440b57cec5SDimitry Andric #endif
23450b57cec5SDimitry Andric
23460eae32dcSDimitry Andric if (regNum == UNW_ARM_RA_AUTH_CODE) {
23470eae32dcSDimitry Andric _pseudo_registers.__pac = value;
23480eae32dcSDimitry Andric return;
23490eae32dcSDimitry Andric }
23500eae32dcSDimitry Andric
23510b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported arm register");
23520b57cec5SDimitry Andric }
23530b57cec5SDimitry Andric
getRegisterName(int regNum)23540b57cec5SDimitry Andric inline const char *Registers_arm::getRegisterName(int regNum) {
23550b57cec5SDimitry Andric switch (regNum) {
23560b57cec5SDimitry Andric case UNW_REG_IP:
23570b57cec5SDimitry Andric case UNW_ARM_IP: // UNW_ARM_R15 is alias
23580b57cec5SDimitry Andric return "pc";
23590b57cec5SDimitry Andric case UNW_ARM_LR: // UNW_ARM_R14 is alias
23600b57cec5SDimitry Andric return "lr";
23610b57cec5SDimitry Andric case UNW_REG_SP:
23620b57cec5SDimitry Andric case UNW_ARM_SP: // UNW_ARM_R13 is alias
23630b57cec5SDimitry Andric return "sp";
23640b57cec5SDimitry Andric case UNW_ARM_R0:
23650b57cec5SDimitry Andric return "r0";
23660b57cec5SDimitry Andric case UNW_ARM_R1:
23670b57cec5SDimitry Andric return "r1";
23680b57cec5SDimitry Andric case UNW_ARM_R2:
23690b57cec5SDimitry Andric return "r2";
23700b57cec5SDimitry Andric case UNW_ARM_R3:
23710b57cec5SDimitry Andric return "r3";
23720b57cec5SDimitry Andric case UNW_ARM_R4:
23730b57cec5SDimitry Andric return "r4";
23740b57cec5SDimitry Andric case UNW_ARM_R5:
23750b57cec5SDimitry Andric return "r5";
23760b57cec5SDimitry Andric case UNW_ARM_R6:
23770b57cec5SDimitry Andric return "r6";
23780b57cec5SDimitry Andric case UNW_ARM_R7:
23790b57cec5SDimitry Andric return "r7";
23800b57cec5SDimitry Andric case UNW_ARM_R8:
23810b57cec5SDimitry Andric return "r8";
23820b57cec5SDimitry Andric case UNW_ARM_R9:
23830b57cec5SDimitry Andric return "r9";
23840b57cec5SDimitry Andric case UNW_ARM_R10:
23850b57cec5SDimitry Andric return "r10";
23860b57cec5SDimitry Andric case UNW_ARM_R11:
23870b57cec5SDimitry Andric return "r11";
23880b57cec5SDimitry Andric case UNW_ARM_R12:
23890b57cec5SDimitry Andric return "r12";
23900b57cec5SDimitry Andric case UNW_ARM_S0:
23910b57cec5SDimitry Andric return "s0";
23920b57cec5SDimitry Andric case UNW_ARM_S1:
23930b57cec5SDimitry Andric return "s1";
23940b57cec5SDimitry Andric case UNW_ARM_S2:
23950b57cec5SDimitry Andric return "s2";
23960b57cec5SDimitry Andric case UNW_ARM_S3:
23970b57cec5SDimitry Andric return "s3";
23980b57cec5SDimitry Andric case UNW_ARM_S4:
23990b57cec5SDimitry Andric return "s4";
24000b57cec5SDimitry Andric case UNW_ARM_S5:
24010b57cec5SDimitry Andric return "s5";
24020b57cec5SDimitry Andric case UNW_ARM_S6:
24030b57cec5SDimitry Andric return "s6";
24040b57cec5SDimitry Andric case UNW_ARM_S7:
24050b57cec5SDimitry Andric return "s7";
24060b57cec5SDimitry Andric case UNW_ARM_S8:
24070b57cec5SDimitry Andric return "s8";
24080b57cec5SDimitry Andric case UNW_ARM_S9:
24090b57cec5SDimitry Andric return "s9";
24100b57cec5SDimitry Andric case UNW_ARM_S10:
24110b57cec5SDimitry Andric return "s10";
24120b57cec5SDimitry Andric case UNW_ARM_S11:
24130b57cec5SDimitry Andric return "s11";
24140b57cec5SDimitry Andric case UNW_ARM_S12:
24150b57cec5SDimitry Andric return "s12";
24160b57cec5SDimitry Andric case UNW_ARM_S13:
24170b57cec5SDimitry Andric return "s13";
24180b57cec5SDimitry Andric case UNW_ARM_S14:
24190b57cec5SDimitry Andric return "s14";
24200b57cec5SDimitry Andric case UNW_ARM_S15:
24210b57cec5SDimitry Andric return "s15";
24220b57cec5SDimitry Andric case UNW_ARM_S16:
24230b57cec5SDimitry Andric return "s16";
24240b57cec5SDimitry Andric case UNW_ARM_S17:
24250b57cec5SDimitry Andric return "s17";
24260b57cec5SDimitry Andric case UNW_ARM_S18:
24270b57cec5SDimitry Andric return "s18";
24280b57cec5SDimitry Andric case UNW_ARM_S19:
24290b57cec5SDimitry Andric return "s19";
24300b57cec5SDimitry Andric case UNW_ARM_S20:
24310b57cec5SDimitry Andric return "s20";
24320b57cec5SDimitry Andric case UNW_ARM_S21:
24330b57cec5SDimitry Andric return "s21";
24340b57cec5SDimitry Andric case UNW_ARM_S22:
24350b57cec5SDimitry Andric return "s22";
24360b57cec5SDimitry Andric case UNW_ARM_S23:
24370b57cec5SDimitry Andric return "s23";
24380b57cec5SDimitry Andric case UNW_ARM_S24:
24390b57cec5SDimitry Andric return "s24";
24400b57cec5SDimitry Andric case UNW_ARM_S25:
24410b57cec5SDimitry Andric return "s25";
24420b57cec5SDimitry Andric case UNW_ARM_S26:
24430b57cec5SDimitry Andric return "s26";
24440b57cec5SDimitry Andric case UNW_ARM_S27:
24450b57cec5SDimitry Andric return "s27";
24460b57cec5SDimitry Andric case UNW_ARM_S28:
24470b57cec5SDimitry Andric return "s28";
24480b57cec5SDimitry Andric case UNW_ARM_S29:
24490b57cec5SDimitry Andric return "s29";
24500b57cec5SDimitry Andric case UNW_ARM_S30:
24510b57cec5SDimitry Andric return "s30";
24520b57cec5SDimitry Andric case UNW_ARM_S31:
24530b57cec5SDimitry Andric return "s31";
24540b57cec5SDimitry Andric case UNW_ARM_D0:
24550b57cec5SDimitry Andric return "d0";
24560b57cec5SDimitry Andric case UNW_ARM_D1:
24570b57cec5SDimitry Andric return "d1";
24580b57cec5SDimitry Andric case UNW_ARM_D2:
24590b57cec5SDimitry Andric return "d2";
24600b57cec5SDimitry Andric case UNW_ARM_D3:
24610b57cec5SDimitry Andric return "d3";
24620b57cec5SDimitry Andric case UNW_ARM_D4:
24630b57cec5SDimitry Andric return "d4";
24640b57cec5SDimitry Andric case UNW_ARM_D5:
24650b57cec5SDimitry Andric return "d5";
24660b57cec5SDimitry Andric case UNW_ARM_D6:
24670b57cec5SDimitry Andric return "d6";
24680b57cec5SDimitry Andric case UNW_ARM_D7:
24690b57cec5SDimitry Andric return "d7";
24700b57cec5SDimitry Andric case UNW_ARM_D8:
24710b57cec5SDimitry Andric return "d8";
24720b57cec5SDimitry Andric case UNW_ARM_D9:
24730b57cec5SDimitry Andric return "d9";
24740b57cec5SDimitry Andric case UNW_ARM_D10:
24750b57cec5SDimitry Andric return "d10";
24760b57cec5SDimitry Andric case UNW_ARM_D11:
24770b57cec5SDimitry Andric return "d11";
24780b57cec5SDimitry Andric case UNW_ARM_D12:
24790b57cec5SDimitry Andric return "d12";
24800b57cec5SDimitry Andric case UNW_ARM_D13:
24810b57cec5SDimitry Andric return "d13";
24820b57cec5SDimitry Andric case UNW_ARM_D14:
24830b57cec5SDimitry Andric return "d14";
24840b57cec5SDimitry Andric case UNW_ARM_D15:
24850b57cec5SDimitry Andric return "d15";
24860b57cec5SDimitry Andric case UNW_ARM_D16:
24870b57cec5SDimitry Andric return "d16";
24880b57cec5SDimitry Andric case UNW_ARM_D17:
24890b57cec5SDimitry Andric return "d17";
24900b57cec5SDimitry Andric case UNW_ARM_D18:
24910b57cec5SDimitry Andric return "d18";
24920b57cec5SDimitry Andric case UNW_ARM_D19:
24930b57cec5SDimitry Andric return "d19";
24940b57cec5SDimitry Andric case UNW_ARM_D20:
24950b57cec5SDimitry Andric return "d20";
24960b57cec5SDimitry Andric case UNW_ARM_D21:
24970b57cec5SDimitry Andric return "d21";
24980b57cec5SDimitry Andric case UNW_ARM_D22:
24990b57cec5SDimitry Andric return "d22";
25000b57cec5SDimitry Andric case UNW_ARM_D23:
25010b57cec5SDimitry Andric return "d23";
25020b57cec5SDimitry Andric case UNW_ARM_D24:
25030b57cec5SDimitry Andric return "d24";
25040b57cec5SDimitry Andric case UNW_ARM_D25:
25050b57cec5SDimitry Andric return "d25";
25060b57cec5SDimitry Andric case UNW_ARM_D26:
25070b57cec5SDimitry Andric return "d26";
25080b57cec5SDimitry Andric case UNW_ARM_D27:
25090b57cec5SDimitry Andric return "d27";
25100b57cec5SDimitry Andric case UNW_ARM_D28:
25110b57cec5SDimitry Andric return "d28";
25120b57cec5SDimitry Andric case UNW_ARM_D29:
25130b57cec5SDimitry Andric return "d29";
25140b57cec5SDimitry Andric case UNW_ARM_D30:
25150b57cec5SDimitry Andric return "d30";
25160b57cec5SDimitry Andric case UNW_ARM_D31:
25170b57cec5SDimitry Andric return "d31";
25180b57cec5SDimitry Andric default:
25190b57cec5SDimitry Andric return "unknown register";
25200b57cec5SDimitry Andric }
25210b57cec5SDimitry Andric }
25220b57cec5SDimitry Andric
validFloatRegister(int regNum) const25230b57cec5SDimitry Andric inline bool Registers_arm::validFloatRegister(int regNum) const {
25240b57cec5SDimitry Andric // NOTE: Consider the intel MMX registers floating points so the
25250b57cec5SDimitry Andric // __unw_get_fpreg can be used to transmit the 64-bit data back.
25260b57cec5SDimitry Andric return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
25270b57cec5SDimitry Andric #if defined(__ARM_WMMX)
25280b57cec5SDimitry Andric || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
25290b57cec5SDimitry Andric #endif
25300b57cec5SDimitry Andric ;
25310b57cec5SDimitry Andric }
25320b57cec5SDimitry Andric
getFloatRegister(int regNum)25330b57cec5SDimitry Andric inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
25340b57cec5SDimitry Andric if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
25350b57cec5SDimitry Andric if (!_saved_vfp_d0_d15) {
25360b57cec5SDimitry Andric _saved_vfp_d0_d15 = true;
25370b57cec5SDimitry Andric if (_use_X_for_vfp_save)
25380b57cec5SDimitry Andric saveVFPWithFSTMX(_vfp_d0_d15_pad);
25390b57cec5SDimitry Andric else
25400b57cec5SDimitry Andric saveVFPWithFSTMD(_vfp_d0_d15_pad);
25410b57cec5SDimitry Andric }
25420b57cec5SDimitry Andric return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
25430b57cec5SDimitry Andric }
25440b57cec5SDimitry Andric
25450b57cec5SDimitry Andric if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
25460b57cec5SDimitry Andric if (!_saved_vfp_d16_d31) {
25470b57cec5SDimitry Andric _saved_vfp_d16_d31 = true;
25480b57cec5SDimitry Andric saveVFPv3(_vfp_d16_d31);
25490b57cec5SDimitry Andric }
25500b57cec5SDimitry Andric return _vfp_d16_d31[regNum - UNW_ARM_D16];
25510b57cec5SDimitry Andric }
25520b57cec5SDimitry Andric
25530b57cec5SDimitry Andric #if defined(__ARM_WMMX)
25540b57cec5SDimitry Andric if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
25550b57cec5SDimitry Andric if (!_saved_iwmmx) {
25560b57cec5SDimitry Andric _saved_iwmmx = true;
25570b57cec5SDimitry Andric saveiWMMX(_iwmmx);
25580b57cec5SDimitry Andric }
25590b57cec5SDimitry Andric return _iwmmx[regNum - UNW_ARM_WR0];
25600b57cec5SDimitry Andric }
25610b57cec5SDimitry Andric #endif
25620b57cec5SDimitry Andric
25630b57cec5SDimitry Andric _LIBUNWIND_ABORT("Unknown ARM float register");
25640b57cec5SDimitry Andric }
25650b57cec5SDimitry Andric
setFloatRegister(int regNum,unw_fpreg_t value)25660b57cec5SDimitry Andric inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
25670b57cec5SDimitry Andric if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
25680b57cec5SDimitry Andric if (!_saved_vfp_d0_d15) {
25690b57cec5SDimitry Andric _saved_vfp_d0_d15 = true;
25700b57cec5SDimitry Andric if (_use_X_for_vfp_save)
25710b57cec5SDimitry Andric saveVFPWithFSTMX(_vfp_d0_d15_pad);
25720b57cec5SDimitry Andric else
25730b57cec5SDimitry Andric saveVFPWithFSTMD(_vfp_d0_d15_pad);
25740b57cec5SDimitry Andric }
25750b57cec5SDimitry Andric _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
25760b57cec5SDimitry Andric return;
25770b57cec5SDimitry Andric }
25780b57cec5SDimitry Andric
25790b57cec5SDimitry Andric if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
25800b57cec5SDimitry Andric if (!_saved_vfp_d16_d31) {
25810b57cec5SDimitry Andric _saved_vfp_d16_d31 = true;
25820b57cec5SDimitry Andric saveVFPv3(_vfp_d16_d31);
25830b57cec5SDimitry Andric }
25840b57cec5SDimitry Andric _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
25850b57cec5SDimitry Andric return;
25860b57cec5SDimitry Andric }
25870b57cec5SDimitry Andric
25880b57cec5SDimitry Andric #if defined(__ARM_WMMX)
25890b57cec5SDimitry Andric if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
25900b57cec5SDimitry Andric if (!_saved_iwmmx) {
25910b57cec5SDimitry Andric _saved_iwmmx = true;
25920b57cec5SDimitry Andric saveiWMMX(_iwmmx);
25930b57cec5SDimitry Andric }
25940b57cec5SDimitry Andric _iwmmx[regNum - UNW_ARM_WR0] = value;
25950b57cec5SDimitry Andric return;
25960b57cec5SDimitry Andric }
25970b57cec5SDimitry Andric #endif
25980b57cec5SDimitry Andric
25990b57cec5SDimitry Andric _LIBUNWIND_ABORT("Unknown ARM float register");
26000b57cec5SDimitry Andric }
26010b57cec5SDimitry Andric
validVectorRegister(int) const26020b57cec5SDimitry Andric inline bool Registers_arm::validVectorRegister(int) const {
26030b57cec5SDimitry Andric return false;
26040b57cec5SDimitry Andric }
26050b57cec5SDimitry Andric
getVectorRegister(int) const26060b57cec5SDimitry Andric inline v128 Registers_arm::getVectorRegister(int) const {
26070b57cec5SDimitry Andric _LIBUNWIND_ABORT("ARM vector support not implemented");
26080b57cec5SDimitry Andric }
26090b57cec5SDimitry Andric
setVectorRegister(int,v128)26100b57cec5SDimitry Andric inline void Registers_arm::setVectorRegister(int, v128) {
26110b57cec5SDimitry Andric _LIBUNWIND_ABORT("ARM vector support not implemented");
26120b57cec5SDimitry Andric }
26130b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_ARM
26140b57cec5SDimitry Andric
26150b57cec5SDimitry Andric
26160b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_OR1K)
26170b57cec5SDimitry Andric /// Registers_or1k holds the register state of a thread in an OpenRISC1000
26180b57cec5SDimitry Andric /// process.
26190b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_or1k {
26200b57cec5SDimitry Andric public:
26210b57cec5SDimitry Andric Registers_or1k();
26220b57cec5SDimitry Andric Registers_or1k(const void *registers);
26230b57cec5SDimitry Andric
26240b57cec5SDimitry Andric bool validRegister(int num) const;
26250b57cec5SDimitry Andric uint32_t getRegister(int num) const;
26260b57cec5SDimitry Andric void setRegister(int num, uint32_t value);
26270b57cec5SDimitry Andric bool validFloatRegister(int num) const;
26280b57cec5SDimitry Andric double getFloatRegister(int num) const;
26290b57cec5SDimitry Andric void setFloatRegister(int num, double value);
26300b57cec5SDimitry Andric bool validVectorRegister(int num) const;
26310b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
26320b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
26330b57cec5SDimitry Andric static const char *getRegisterName(int num);
26340b57cec5SDimitry Andric void jumpto();
lastDwarfRegNum()263581ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
263681ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K;
263781ad6265SDimitry Andric }
getArch()26380b57cec5SDimitry Andric static int getArch() { return REGISTERS_OR1K; }
26390b57cec5SDimitry Andric
getSP() const26400b57cec5SDimitry Andric uint64_t getSP() const { return _registers.__r[1]; }
setSP(uint32_t value)26410b57cec5SDimitry Andric void setSP(uint32_t value) { _registers.__r[1] = value; }
getIP() const26420b57cec5SDimitry Andric uint64_t getIP() const { return _registers.__pc; }
setIP(uint32_t value)26430b57cec5SDimitry Andric void setIP(uint32_t value) { _registers.__pc = value; }
26440b57cec5SDimitry Andric
26450b57cec5SDimitry Andric private:
26460b57cec5SDimitry Andric struct or1k_thread_state_t {
26470b57cec5SDimitry Andric unsigned int __r[32]; // r0-r31
26480b57cec5SDimitry Andric unsigned int __pc; // Program counter
26490b57cec5SDimitry Andric unsigned int __epcr; // Program counter at exception
26500b57cec5SDimitry Andric };
26510b57cec5SDimitry Andric
26520b57cec5SDimitry Andric or1k_thread_state_t _registers;
26530b57cec5SDimitry Andric };
26540b57cec5SDimitry Andric
Registers_or1k(const void * registers)26550b57cec5SDimitry Andric inline Registers_or1k::Registers_or1k(const void *registers) {
26560b57cec5SDimitry Andric static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
26570b57cec5SDimitry Andric "or1k registers do not fit into unw_context_t");
26580b57cec5SDimitry Andric memcpy(&_registers, static_cast<const uint8_t *>(registers),
26590b57cec5SDimitry Andric sizeof(_registers));
26600b57cec5SDimitry Andric }
26610b57cec5SDimitry Andric
Registers_or1k()26620b57cec5SDimitry Andric inline Registers_or1k::Registers_or1k() {
26630b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
26640b57cec5SDimitry Andric }
26650b57cec5SDimitry Andric
validRegister(int regNum) const26660b57cec5SDimitry Andric inline bool Registers_or1k::validRegister(int regNum) const {
26670b57cec5SDimitry Andric if (regNum == UNW_REG_IP)
26680b57cec5SDimitry Andric return true;
26690b57cec5SDimitry Andric if (regNum == UNW_REG_SP)
26700b57cec5SDimitry Andric return true;
26710b57cec5SDimitry Andric if (regNum < 0)
26720b57cec5SDimitry Andric return false;
26730b57cec5SDimitry Andric if (regNum <= UNW_OR1K_R31)
26740b57cec5SDimitry Andric return true;
26750b57cec5SDimitry Andric if (regNum == UNW_OR1K_EPCR)
26760b57cec5SDimitry Andric return true;
26770b57cec5SDimitry Andric return false;
26780b57cec5SDimitry Andric }
26790b57cec5SDimitry Andric
getRegister(int regNum) const26800b57cec5SDimitry Andric inline uint32_t Registers_or1k::getRegister(int regNum) const {
26810b57cec5SDimitry Andric if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
26820b57cec5SDimitry Andric return _registers.__r[regNum - UNW_OR1K_R0];
26830b57cec5SDimitry Andric
26840b57cec5SDimitry Andric switch (regNum) {
26850b57cec5SDimitry Andric case UNW_REG_IP:
26860b57cec5SDimitry Andric return _registers.__pc;
26870b57cec5SDimitry Andric case UNW_REG_SP:
26880b57cec5SDimitry Andric return _registers.__r[1];
26890b57cec5SDimitry Andric case UNW_OR1K_EPCR:
26900b57cec5SDimitry Andric return _registers.__epcr;
26910b57cec5SDimitry Andric }
26920b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported or1k register");
26930b57cec5SDimitry Andric }
26940b57cec5SDimitry Andric
setRegister(int regNum,uint32_t value)26950b57cec5SDimitry Andric inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
26960b57cec5SDimitry Andric if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
26970b57cec5SDimitry Andric _registers.__r[regNum - UNW_OR1K_R0] = value;
26980b57cec5SDimitry Andric return;
26990b57cec5SDimitry Andric }
27000b57cec5SDimitry Andric
27010b57cec5SDimitry Andric switch (regNum) {
27020b57cec5SDimitry Andric case UNW_REG_IP:
27030b57cec5SDimitry Andric _registers.__pc = value;
27040b57cec5SDimitry Andric return;
27050b57cec5SDimitry Andric case UNW_REG_SP:
27060b57cec5SDimitry Andric _registers.__r[1] = value;
27070b57cec5SDimitry Andric return;
27080b57cec5SDimitry Andric case UNW_OR1K_EPCR:
27090b57cec5SDimitry Andric _registers.__epcr = value;
27100b57cec5SDimitry Andric return;
27110b57cec5SDimitry Andric }
27120b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported or1k register");
27130b57cec5SDimitry Andric }
27140b57cec5SDimitry Andric
validFloatRegister(int) const27150b57cec5SDimitry Andric inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
27160b57cec5SDimitry Andric return false;
27170b57cec5SDimitry Andric }
27180b57cec5SDimitry Andric
getFloatRegister(int) const27190b57cec5SDimitry Andric inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
27200b57cec5SDimitry Andric _LIBUNWIND_ABORT("or1k float support not implemented");
27210b57cec5SDimitry Andric }
27220b57cec5SDimitry Andric
setFloatRegister(int,double)27230b57cec5SDimitry Andric inline void Registers_or1k::setFloatRegister(int /* regNum */,
27240b57cec5SDimitry Andric double /* value */) {
27250b57cec5SDimitry Andric _LIBUNWIND_ABORT("or1k float support not implemented");
27260b57cec5SDimitry Andric }
27270b57cec5SDimitry Andric
validVectorRegister(int) const27280b57cec5SDimitry Andric inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
27290b57cec5SDimitry Andric return false;
27300b57cec5SDimitry Andric }
27310b57cec5SDimitry Andric
getVectorRegister(int) const27320b57cec5SDimitry Andric inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
27330b57cec5SDimitry Andric _LIBUNWIND_ABORT("or1k vector support not implemented");
27340b57cec5SDimitry Andric }
27350b57cec5SDimitry Andric
setVectorRegister(int,v128)27360b57cec5SDimitry Andric inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
27370b57cec5SDimitry Andric _LIBUNWIND_ABORT("or1k vector support not implemented");
27380b57cec5SDimitry Andric }
27390b57cec5SDimitry Andric
getRegisterName(int regNum)27400b57cec5SDimitry Andric inline const char *Registers_or1k::getRegisterName(int regNum) {
27410b57cec5SDimitry Andric switch (regNum) {
27420b57cec5SDimitry Andric case UNW_OR1K_R0:
27430b57cec5SDimitry Andric return "r0";
27440b57cec5SDimitry Andric case UNW_OR1K_R1:
27450b57cec5SDimitry Andric return "r1";
27460b57cec5SDimitry Andric case UNW_OR1K_R2:
27470b57cec5SDimitry Andric return "r2";
27480b57cec5SDimitry Andric case UNW_OR1K_R3:
27490b57cec5SDimitry Andric return "r3";
27500b57cec5SDimitry Andric case UNW_OR1K_R4:
27510b57cec5SDimitry Andric return "r4";
27520b57cec5SDimitry Andric case UNW_OR1K_R5:
27530b57cec5SDimitry Andric return "r5";
27540b57cec5SDimitry Andric case UNW_OR1K_R6:
27550b57cec5SDimitry Andric return "r6";
27560b57cec5SDimitry Andric case UNW_OR1K_R7:
27570b57cec5SDimitry Andric return "r7";
27580b57cec5SDimitry Andric case UNW_OR1K_R8:
27590b57cec5SDimitry Andric return "r8";
27600b57cec5SDimitry Andric case UNW_OR1K_R9:
27610b57cec5SDimitry Andric return "r9";
27620b57cec5SDimitry Andric case UNW_OR1K_R10:
27630b57cec5SDimitry Andric return "r10";
27640b57cec5SDimitry Andric case UNW_OR1K_R11:
27650b57cec5SDimitry Andric return "r11";
27660b57cec5SDimitry Andric case UNW_OR1K_R12:
27670b57cec5SDimitry Andric return "r12";
27680b57cec5SDimitry Andric case UNW_OR1K_R13:
27690b57cec5SDimitry Andric return "r13";
27700b57cec5SDimitry Andric case UNW_OR1K_R14:
27710b57cec5SDimitry Andric return "r14";
27720b57cec5SDimitry Andric case UNW_OR1K_R15:
27730b57cec5SDimitry Andric return "r15";
27740b57cec5SDimitry Andric case UNW_OR1K_R16:
27750b57cec5SDimitry Andric return "r16";
27760b57cec5SDimitry Andric case UNW_OR1K_R17:
27770b57cec5SDimitry Andric return "r17";
27780b57cec5SDimitry Andric case UNW_OR1K_R18:
27790b57cec5SDimitry Andric return "r18";
27800b57cec5SDimitry Andric case UNW_OR1K_R19:
27810b57cec5SDimitry Andric return "r19";
27820b57cec5SDimitry Andric case UNW_OR1K_R20:
27830b57cec5SDimitry Andric return "r20";
27840b57cec5SDimitry Andric case UNW_OR1K_R21:
27850b57cec5SDimitry Andric return "r21";
27860b57cec5SDimitry Andric case UNW_OR1K_R22:
27870b57cec5SDimitry Andric return "r22";
27880b57cec5SDimitry Andric case UNW_OR1K_R23:
27890b57cec5SDimitry Andric return "r23";
27900b57cec5SDimitry Andric case UNW_OR1K_R24:
27910b57cec5SDimitry Andric return "r24";
27920b57cec5SDimitry Andric case UNW_OR1K_R25:
27930b57cec5SDimitry Andric return "r25";
27940b57cec5SDimitry Andric case UNW_OR1K_R26:
27950b57cec5SDimitry Andric return "r26";
27960b57cec5SDimitry Andric case UNW_OR1K_R27:
27970b57cec5SDimitry Andric return "r27";
27980b57cec5SDimitry Andric case UNW_OR1K_R28:
27990b57cec5SDimitry Andric return "r28";
28000b57cec5SDimitry Andric case UNW_OR1K_R29:
28010b57cec5SDimitry Andric return "r29";
28020b57cec5SDimitry Andric case UNW_OR1K_R30:
28030b57cec5SDimitry Andric return "r30";
28040b57cec5SDimitry Andric case UNW_OR1K_R31:
28050b57cec5SDimitry Andric return "r31";
28060b57cec5SDimitry Andric case UNW_OR1K_EPCR:
28070b57cec5SDimitry Andric return "EPCR";
28080b57cec5SDimitry Andric default:
28090b57cec5SDimitry Andric return "unknown register";
28100b57cec5SDimitry Andric }
28110b57cec5SDimitry Andric
28120b57cec5SDimitry Andric }
28130b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_OR1K
28140b57cec5SDimitry Andric
28150b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_MIPS_O32)
28160b57cec5SDimitry Andric /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
28170b57cec5SDimitry Andric /// process.
28180b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_mips_o32 {
28190b57cec5SDimitry Andric public:
28200b57cec5SDimitry Andric Registers_mips_o32();
28210b57cec5SDimitry Andric Registers_mips_o32(const void *registers);
28220b57cec5SDimitry Andric
28230b57cec5SDimitry Andric bool validRegister(int num) const;
28240b57cec5SDimitry Andric uint32_t getRegister(int num) const;
28250b57cec5SDimitry Andric void setRegister(int num, uint32_t value);
28260b57cec5SDimitry Andric bool validFloatRegister(int num) const;
28270b57cec5SDimitry Andric double getFloatRegister(int num) const;
28280b57cec5SDimitry Andric void setFloatRegister(int num, double value);
28290b57cec5SDimitry Andric bool validVectorRegister(int num) const;
28300b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
28310b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
28320b57cec5SDimitry Andric static const char *getRegisterName(int num);
28330b57cec5SDimitry Andric void jumpto();
lastDwarfRegNum()283481ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
283581ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
283681ad6265SDimitry Andric }
getArch()28370b57cec5SDimitry Andric static int getArch() { return REGISTERS_MIPS_O32; }
28380b57cec5SDimitry Andric
getSP() const28390b57cec5SDimitry Andric uint32_t getSP() const { return _registers.__r[29]; }
setSP(uint32_t value)28400b57cec5SDimitry Andric void setSP(uint32_t value) { _registers.__r[29] = value; }
getIP() const28410b57cec5SDimitry Andric uint32_t getIP() const { return _registers.__pc; }
setIP(uint32_t value)28420b57cec5SDimitry Andric void setIP(uint32_t value) { _registers.__pc = value; }
28430b57cec5SDimitry Andric
28440b57cec5SDimitry Andric private:
28450b57cec5SDimitry Andric struct mips_o32_thread_state_t {
28460b57cec5SDimitry Andric uint32_t __r[32];
28470b57cec5SDimitry Andric uint32_t __pc;
28480b57cec5SDimitry Andric uint32_t __hi;
28490b57cec5SDimitry Andric uint32_t __lo;
28500b57cec5SDimitry Andric };
28510b57cec5SDimitry Andric
28520b57cec5SDimitry Andric mips_o32_thread_state_t _registers;
28530b57cec5SDimitry Andric #ifdef __mips_hard_float
28540b57cec5SDimitry Andric /// O32 with 32-bit floating point registers only uses half of this
28550b57cec5SDimitry Andric /// space. However, using the same layout for 32-bit vs 64-bit
28560b57cec5SDimitry Andric /// floating point registers results in a single context size for
28570b57cec5SDimitry Andric /// O32 with hard float.
28580b57cec5SDimitry Andric uint32_t _padding;
28590b57cec5SDimitry Andric double _floats[32];
28600b57cec5SDimitry Andric #endif
28610b57cec5SDimitry Andric };
28620b57cec5SDimitry Andric
Registers_mips_o32(const void * registers)28630b57cec5SDimitry Andric inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
28640b57cec5SDimitry Andric static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
28650b57cec5SDimitry Andric "mips_o32 registers do not fit into unw_context_t");
28660b57cec5SDimitry Andric memcpy(&_registers, static_cast<const uint8_t *>(registers),
28670b57cec5SDimitry Andric sizeof(_registers));
28680b57cec5SDimitry Andric }
28690b57cec5SDimitry Andric
Registers_mips_o32()28700b57cec5SDimitry Andric inline Registers_mips_o32::Registers_mips_o32() {
28710b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
28720b57cec5SDimitry Andric }
28730b57cec5SDimitry Andric
validRegister(int regNum) const28740b57cec5SDimitry Andric inline bool Registers_mips_o32::validRegister(int regNum) const {
28750b57cec5SDimitry Andric if (regNum == UNW_REG_IP)
28760b57cec5SDimitry Andric return true;
28770b57cec5SDimitry Andric if (regNum == UNW_REG_SP)
28780b57cec5SDimitry Andric return true;
28790b57cec5SDimitry Andric if (regNum < 0)
28800b57cec5SDimitry Andric return false;
28810b57cec5SDimitry Andric if (regNum <= UNW_MIPS_R31)
28820b57cec5SDimitry Andric return true;
28835f757f3fSDimitry Andric #if __mips_isa_rev < 6
28840b57cec5SDimitry Andric if (regNum == UNW_MIPS_HI)
28850b57cec5SDimitry Andric return true;
28860b57cec5SDimitry Andric if (regNum == UNW_MIPS_LO)
28870b57cec5SDimitry Andric return true;
28880b57cec5SDimitry Andric #endif
28890b57cec5SDimitry Andric #if defined(__mips_hard_float) && __mips_fpr == 32
28900b57cec5SDimitry Andric if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
28910b57cec5SDimitry Andric return true;
28920b57cec5SDimitry Andric #endif
28930b57cec5SDimitry Andric // FIXME: DSP accumulator registers, MSA registers
28940b57cec5SDimitry Andric return false;
28950b57cec5SDimitry Andric }
28960b57cec5SDimitry Andric
getRegister(int regNum) const28970b57cec5SDimitry Andric inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
28980b57cec5SDimitry Andric if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
28990b57cec5SDimitry Andric return _registers.__r[regNum - UNW_MIPS_R0];
29000b57cec5SDimitry Andric #if defined(__mips_hard_float) && __mips_fpr == 32
29010b57cec5SDimitry Andric if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
29020b57cec5SDimitry Andric uint32_t *p;
29030b57cec5SDimitry Andric
29040b57cec5SDimitry Andric if (regNum % 2 == 0)
29050b57cec5SDimitry Andric p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
29060b57cec5SDimitry Andric else
29070b57cec5SDimitry Andric p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
29080b57cec5SDimitry Andric return *p;
29090b57cec5SDimitry Andric }
29100b57cec5SDimitry Andric #endif
29110b57cec5SDimitry Andric
29120b57cec5SDimitry Andric switch (regNum) {
29130b57cec5SDimitry Andric case UNW_REG_IP:
29140b57cec5SDimitry Andric return _registers.__pc;
29150b57cec5SDimitry Andric case UNW_REG_SP:
29160b57cec5SDimitry Andric return _registers.__r[29];
29175f757f3fSDimitry Andric #if __mips_isa_rev < 6
29180b57cec5SDimitry Andric case UNW_MIPS_HI:
29190b57cec5SDimitry Andric return _registers.__hi;
29200b57cec5SDimitry Andric case UNW_MIPS_LO:
29210b57cec5SDimitry Andric return _registers.__lo;
29225f757f3fSDimitry Andric #endif
29230b57cec5SDimitry Andric }
29240b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported mips_o32 register");
29250b57cec5SDimitry Andric }
29260b57cec5SDimitry Andric
setRegister(int regNum,uint32_t value)29270b57cec5SDimitry Andric inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
29280b57cec5SDimitry Andric if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
29290b57cec5SDimitry Andric _registers.__r[regNum - UNW_MIPS_R0] = value;
29300b57cec5SDimitry Andric return;
29310b57cec5SDimitry Andric }
29320b57cec5SDimitry Andric #if defined(__mips_hard_float) && __mips_fpr == 32
29330b57cec5SDimitry Andric if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
29340b57cec5SDimitry Andric uint32_t *p;
29350b57cec5SDimitry Andric
29360b57cec5SDimitry Andric if (regNum % 2 == 0)
29370b57cec5SDimitry Andric p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
29380b57cec5SDimitry Andric else
29390b57cec5SDimitry Andric p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
29400b57cec5SDimitry Andric *p = value;
29410b57cec5SDimitry Andric return;
29420b57cec5SDimitry Andric }
29430b57cec5SDimitry Andric #endif
29440b57cec5SDimitry Andric
29450b57cec5SDimitry Andric switch (regNum) {
29460b57cec5SDimitry Andric case UNW_REG_IP:
29470b57cec5SDimitry Andric _registers.__pc = value;
29480b57cec5SDimitry Andric return;
29490b57cec5SDimitry Andric case UNW_REG_SP:
29500b57cec5SDimitry Andric _registers.__r[29] = value;
29510b57cec5SDimitry Andric return;
29525f757f3fSDimitry Andric #if __mips_isa_rev < 6
29530b57cec5SDimitry Andric case UNW_MIPS_HI:
29540b57cec5SDimitry Andric _registers.__hi = value;
29550b57cec5SDimitry Andric return;
29560b57cec5SDimitry Andric case UNW_MIPS_LO:
29570b57cec5SDimitry Andric _registers.__lo = value;
29585f757f3fSDimitry Andric #endif
29590b57cec5SDimitry Andric return;
29600b57cec5SDimitry Andric }
29610b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported mips_o32 register");
29620b57cec5SDimitry Andric }
29630b57cec5SDimitry Andric
validFloatRegister(int regNum) const29640b57cec5SDimitry Andric inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
29650b57cec5SDimitry Andric #if defined(__mips_hard_float) && __mips_fpr == 64
29660b57cec5SDimitry Andric if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
29670b57cec5SDimitry Andric return true;
29685ffd83dbSDimitry Andric #else
29695ffd83dbSDimitry Andric (void)regNum;
29700b57cec5SDimitry Andric #endif
29710b57cec5SDimitry Andric return false;
29720b57cec5SDimitry Andric }
29730b57cec5SDimitry Andric
getFloatRegister(int regNum) const29740b57cec5SDimitry Andric inline double Registers_mips_o32::getFloatRegister(int regNum) const {
29750b57cec5SDimitry Andric #if defined(__mips_hard_float) && __mips_fpr == 64
29760b57cec5SDimitry Andric assert(validFloatRegister(regNum));
29770b57cec5SDimitry Andric return _floats[regNum - UNW_MIPS_F0];
29780b57cec5SDimitry Andric #else
29795ffd83dbSDimitry Andric (void)regNum;
29800b57cec5SDimitry Andric _LIBUNWIND_ABORT("mips_o32 float support not implemented");
29810b57cec5SDimitry Andric #endif
29820b57cec5SDimitry Andric }
29830b57cec5SDimitry Andric
setFloatRegister(int regNum,double value)29840b57cec5SDimitry Andric inline void Registers_mips_o32::setFloatRegister(int regNum,
29850b57cec5SDimitry Andric double value) {
29860b57cec5SDimitry Andric #if defined(__mips_hard_float) && __mips_fpr == 64
29870b57cec5SDimitry Andric assert(validFloatRegister(regNum));
29880b57cec5SDimitry Andric _floats[regNum - UNW_MIPS_F0] = value;
29890b57cec5SDimitry Andric #else
29905ffd83dbSDimitry Andric (void)regNum;
29915ffd83dbSDimitry Andric (void)value;
29920b57cec5SDimitry Andric _LIBUNWIND_ABORT("mips_o32 float support not implemented");
29930b57cec5SDimitry Andric #endif
29940b57cec5SDimitry Andric }
29950b57cec5SDimitry Andric
validVectorRegister(int) const29960b57cec5SDimitry Andric inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
29970b57cec5SDimitry Andric return false;
29980b57cec5SDimitry Andric }
29990b57cec5SDimitry Andric
getVectorRegister(int) const30000b57cec5SDimitry Andric inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
30010b57cec5SDimitry Andric _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
30020b57cec5SDimitry Andric }
30030b57cec5SDimitry Andric
setVectorRegister(int,v128)30040b57cec5SDimitry Andric inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
30050b57cec5SDimitry Andric _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
30060b57cec5SDimitry Andric }
30070b57cec5SDimitry Andric
getRegisterName(int regNum)30080b57cec5SDimitry Andric inline const char *Registers_mips_o32::getRegisterName(int regNum) {
30090b57cec5SDimitry Andric switch (regNum) {
30100b57cec5SDimitry Andric case UNW_MIPS_R0:
30110b57cec5SDimitry Andric return "$0";
30120b57cec5SDimitry Andric case UNW_MIPS_R1:
30130b57cec5SDimitry Andric return "$1";
30140b57cec5SDimitry Andric case UNW_MIPS_R2:
30150b57cec5SDimitry Andric return "$2";
30160b57cec5SDimitry Andric case UNW_MIPS_R3:
30170b57cec5SDimitry Andric return "$3";
30180b57cec5SDimitry Andric case UNW_MIPS_R4:
30190b57cec5SDimitry Andric return "$4";
30200b57cec5SDimitry Andric case UNW_MIPS_R5:
30210b57cec5SDimitry Andric return "$5";
30220b57cec5SDimitry Andric case UNW_MIPS_R6:
30230b57cec5SDimitry Andric return "$6";
30240b57cec5SDimitry Andric case UNW_MIPS_R7:
30250b57cec5SDimitry Andric return "$7";
30260b57cec5SDimitry Andric case UNW_MIPS_R8:
30270b57cec5SDimitry Andric return "$8";
30280b57cec5SDimitry Andric case UNW_MIPS_R9:
30290b57cec5SDimitry Andric return "$9";
30300b57cec5SDimitry Andric case UNW_MIPS_R10:
30310b57cec5SDimitry Andric return "$10";
30320b57cec5SDimitry Andric case UNW_MIPS_R11:
30330b57cec5SDimitry Andric return "$11";
30340b57cec5SDimitry Andric case UNW_MIPS_R12:
30350b57cec5SDimitry Andric return "$12";
30360b57cec5SDimitry Andric case UNW_MIPS_R13:
30370b57cec5SDimitry Andric return "$13";
30380b57cec5SDimitry Andric case UNW_MIPS_R14:
30390b57cec5SDimitry Andric return "$14";
30400b57cec5SDimitry Andric case UNW_MIPS_R15:
30410b57cec5SDimitry Andric return "$15";
30420b57cec5SDimitry Andric case UNW_MIPS_R16:
30430b57cec5SDimitry Andric return "$16";
30440b57cec5SDimitry Andric case UNW_MIPS_R17:
30450b57cec5SDimitry Andric return "$17";
30460b57cec5SDimitry Andric case UNW_MIPS_R18:
30470b57cec5SDimitry Andric return "$18";
30480b57cec5SDimitry Andric case UNW_MIPS_R19:
30490b57cec5SDimitry Andric return "$19";
30500b57cec5SDimitry Andric case UNW_MIPS_R20:
30510b57cec5SDimitry Andric return "$20";
30520b57cec5SDimitry Andric case UNW_MIPS_R21:
30530b57cec5SDimitry Andric return "$21";
30540b57cec5SDimitry Andric case UNW_MIPS_R22:
30550b57cec5SDimitry Andric return "$22";
30560b57cec5SDimitry Andric case UNW_MIPS_R23:
30570b57cec5SDimitry Andric return "$23";
30580b57cec5SDimitry Andric case UNW_MIPS_R24:
30590b57cec5SDimitry Andric return "$24";
30600b57cec5SDimitry Andric case UNW_MIPS_R25:
30610b57cec5SDimitry Andric return "$25";
30620b57cec5SDimitry Andric case UNW_MIPS_R26:
30630b57cec5SDimitry Andric return "$26";
30640b57cec5SDimitry Andric case UNW_MIPS_R27:
30650b57cec5SDimitry Andric return "$27";
30660b57cec5SDimitry Andric case UNW_MIPS_R28:
30670b57cec5SDimitry Andric return "$28";
30680b57cec5SDimitry Andric case UNW_MIPS_R29:
30690b57cec5SDimitry Andric return "$29";
30700b57cec5SDimitry Andric case UNW_MIPS_R30:
30710b57cec5SDimitry Andric return "$30";
30720b57cec5SDimitry Andric case UNW_MIPS_R31:
30730b57cec5SDimitry Andric return "$31";
30740b57cec5SDimitry Andric case UNW_MIPS_F0:
30750b57cec5SDimitry Andric return "$f0";
30760b57cec5SDimitry Andric case UNW_MIPS_F1:
30770b57cec5SDimitry Andric return "$f1";
30780b57cec5SDimitry Andric case UNW_MIPS_F2:
30790b57cec5SDimitry Andric return "$f2";
30800b57cec5SDimitry Andric case UNW_MIPS_F3:
30810b57cec5SDimitry Andric return "$f3";
30820b57cec5SDimitry Andric case UNW_MIPS_F4:
30830b57cec5SDimitry Andric return "$f4";
30840b57cec5SDimitry Andric case UNW_MIPS_F5:
30850b57cec5SDimitry Andric return "$f5";
30860b57cec5SDimitry Andric case UNW_MIPS_F6:
30870b57cec5SDimitry Andric return "$f6";
30880b57cec5SDimitry Andric case UNW_MIPS_F7:
30890b57cec5SDimitry Andric return "$f7";
30900b57cec5SDimitry Andric case UNW_MIPS_F8:
30910b57cec5SDimitry Andric return "$f8";
30920b57cec5SDimitry Andric case UNW_MIPS_F9:
30930b57cec5SDimitry Andric return "$f9";
30940b57cec5SDimitry Andric case UNW_MIPS_F10:
30950b57cec5SDimitry Andric return "$f10";
30960b57cec5SDimitry Andric case UNW_MIPS_F11:
30970b57cec5SDimitry Andric return "$f11";
30980b57cec5SDimitry Andric case UNW_MIPS_F12:
30990b57cec5SDimitry Andric return "$f12";
31000b57cec5SDimitry Andric case UNW_MIPS_F13:
31010b57cec5SDimitry Andric return "$f13";
31020b57cec5SDimitry Andric case UNW_MIPS_F14:
31030b57cec5SDimitry Andric return "$f14";
31040b57cec5SDimitry Andric case UNW_MIPS_F15:
31050b57cec5SDimitry Andric return "$f15";
31060b57cec5SDimitry Andric case UNW_MIPS_F16:
31070b57cec5SDimitry Andric return "$f16";
31080b57cec5SDimitry Andric case UNW_MIPS_F17:
31090b57cec5SDimitry Andric return "$f17";
31100b57cec5SDimitry Andric case UNW_MIPS_F18:
31110b57cec5SDimitry Andric return "$f18";
31120b57cec5SDimitry Andric case UNW_MIPS_F19:
31130b57cec5SDimitry Andric return "$f19";
31140b57cec5SDimitry Andric case UNW_MIPS_F20:
31150b57cec5SDimitry Andric return "$f20";
31160b57cec5SDimitry Andric case UNW_MIPS_F21:
31170b57cec5SDimitry Andric return "$f21";
31180b57cec5SDimitry Andric case UNW_MIPS_F22:
31190b57cec5SDimitry Andric return "$f22";
31200b57cec5SDimitry Andric case UNW_MIPS_F23:
31210b57cec5SDimitry Andric return "$f23";
31220b57cec5SDimitry Andric case UNW_MIPS_F24:
31230b57cec5SDimitry Andric return "$f24";
31240b57cec5SDimitry Andric case UNW_MIPS_F25:
31250b57cec5SDimitry Andric return "$f25";
31260b57cec5SDimitry Andric case UNW_MIPS_F26:
31270b57cec5SDimitry Andric return "$f26";
31280b57cec5SDimitry Andric case UNW_MIPS_F27:
31290b57cec5SDimitry Andric return "$f27";
31300b57cec5SDimitry Andric case UNW_MIPS_F28:
31310b57cec5SDimitry Andric return "$f28";
31320b57cec5SDimitry Andric case UNW_MIPS_F29:
31330b57cec5SDimitry Andric return "$f29";
31340b57cec5SDimitry Andric case UNW_MIPS_F30:
31350b57cec5SDimitry Andric return "$f30";
31360b57cec5SDimitry Andric case UNW_MIPS_F31:
31370b57cec5SDimitry Andric return "$f31";
31385f757f3fSDimitry Andric #if __mips_isa_rev < 6
31390b57cec5SDimitry Andric case UNW_MIPS_HI:
31400b57cec5SDimitry Andric return "$hi";
31410b57cec5SDimitry Andric case UNW_MIPS_LO:
31420b57cec5SDimitry Andric return "$lo";
31435f757f3fSDimitry Andric #endif
31440b57cec5SDimitry Andric default:
31450b57cec5SDimitry Andric return "unknown register";
31460b57cec5SDimitry Andric }
31470b57cec5SDimitry Andric }
31480b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_MIPS_O32
31490b57cec5SDimitry Andric
31500b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
31510b57cec5SDimitry Andric /// Registers_mips_newabi holds the register state of a thread in a
31520b57cec5SDimitry Andric /// MIPS process using NEWABI (the N32 or N64 ABIs).
31530b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_mips_newabi {
31540b57cec5SDimitry Andric public:
31550b57cec5SDimitry Andric Registers_mips_newabi();
31560b57cec5SDimitry Andric Registers_mips_newabi(const void *registers);
31570b57cec5SDimitry Andric
31580b57cec5SDimitry Andric bool validRegister(int num) const;
31590b57cec5SDimitry Andric uint64_t getRegister(int num) const;
31600b57cec5SDimitry Andric void setRegister(int num, uint64_t value);
31610b57cec5SDimitry Andric bool validFloatRegister(int num) const;
31620b57cec5SDimitry Andric double getFloatRegister(int num) const;
31630b57cec5SDimitry Andric void setFloatRegister(int num, double value);
31640b57cec5SDimitry Andric bool validVectorRegister(int num) const;
31650b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
31660b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
31670b57cec5SDimitry Andric static const char *getRegisterName(int num);
31680b57cec5SDimitry Andric void jumpto();
lastDwarfRegNum()316981ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
317081ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
317181ad6265SDimitry Andric }
getArch()31720b57cec5SDimitry Andric static int getArch() { return REGISTERS_MIPS_NEWABI; }
31730b57cec5SDimitry Andric
getSP() const31740b57cec5SDimitry Andric uint64_t getSP() const { return _registers.__r[29]; }
setSP(uint64_t value)31750b57cec5SDimitry Andric void setSP(uint64_t value) { _registers.__r[29] = value; }
getIP() const31760b57cec5SDimitry Andric uint64_t getIP() const { return _registers.__pc; }
setIP(uint64_t value)31770b57cec5SDimitry Andric void setIP(uint64_t value) { _registers.__pc = value; }
31780b57cec5SDimitry Andric
31790b57cec5SDimitry Andric private:
31800b57cec5SDimitry Andric struct mips_newabi_thread_state_t {
31810b57cec5SDimitry Andric uint64_t __r[32];
31820b57cec5SDimitry Andric uint64_t __pc;
31830b57cec5SDimitry Andric uint64_t __hi;
31840b57cec5SDimitry Andric uint64_t __lo;
31850b57cec5SDimitry Andric };
31860b57cec5SDimitry Andric
31870b57cec5SDimitry Andric mips_newabi_thread_state_t _registers;
31880b57cec5SDimitry Andric #ifdef __mips_hard_float
31890b57cec5SDimitry Andric double _floats[32];
31900b57cec5SDimitry Andric #endif
31910b57cec5SDimitry Andric };
31920b57cec5SDimitry Andric
Registers_mips_newabi(const void * registers)31930b57cec5SDimitry Andric inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
31940b57cec5SDimitry Andric static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
31950b57cec5SDimitry Andric "mips_newabi registers do not fit into unw_context_t");
31960b57cec5SDimitry Andric memcpy(&_registers, static_cast<const uint8_t *>(registers),
31970b57cec5SDimitry Andric sizeof(_registers));
31980b57cec5SDimitry Andric }
31990b57cec5SDimitry Andric
Registers_mips_newabi()32000b57cec5SDimitry Andric inline Registers_mips_newabi::Registers_mips_newabi() {
32010b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
32020b57cec5SDimitry Andric }
32030b57cec5SDimitry Andric
validRegister(int regNum) const32040b57cec5SDimitry Andric inline bool Registers_mips_newabi::validRegister(int regNum) const {
32050b57cec5SDimitry Andric if (regNum == UNW_REG_IP)
32060b57cec5SDimitry Andric return true;
32070b57cec5SDimitry Andric if (regNum == UNW_REG_SP)
32080b57cec5SDimitry Andric return true;
32090b57cec5SDimitry Andric if (regNum < 0)
32100b57cec5SDimitry Andric return false;
32110b57cec5SDimitry Andric if (regNum <= UNW_MIPS_R31)
32120b57cec5SDimitry Andric return true;
32135f757f3fSDimitry Andric #if __mips_isa_rev < 6
32140b57cec5SDimitry Andric if (regNum == UNW_MIPS_HI)
32150b57cec5SDimitry Andric return true;
32160b57cec5SDimitry Andric if (regNum == UNW_MIPS_LO)
32170b57cec5SDimitry Andric return true;
32180b57cec5SDimitry Andric #endif
32190b57cec5SDimitry Andric // FIXME: Hard float, DSP accumulator registers, MSA registers
32200b57cec5SDimitry Andric return false;
32210b57cec5SDimitry Andric }
32220b57cec5SDimitry Andric
getRegister(int regNum) const32230b57cec5SDimitry Andric inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
32240b57cec5SDimitry Andric if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
32250b57cec5SDimitry Andric return _registers.__r[regNum - UNW_MIPS_R0];
32260b57cec5SDimitry Andric
32270b57cec5SDimitry Andric switch (regNum) {
32280b57cec5SDimitry Andric case UNW_REG_IP:
32290b57cec5SDimitry Andric return _registers.__pc;
32300b57cec5SDimitry Andric case UNW_REG_SP:
32310b57cec5SDimitry Andric return _registers.__r[29];
32325f757f3fSDimitry Andric #if __mips_isa_rev < 6
32330b57cec5SDimitry Andric case UNW_MIPS_HI:
32340b57cec5SDimitry Andric return _registers.__hi;
32350b57cec5SDimitry Andric case UNW_MIPS_LO:
32360b57cec5SDimitry Andric return _registers.__lo;
32375f757f3fSDimitry Andric #endif
32380b57cec5SDimitry Andric }
32390b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported mips_newabi register");
32400b57cec5SDimitry Andric }
32410b57cec5SDimitry Andric
setRegister(int regNum,uint64_t value)32420b57cec5SDimitry Andric inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
32430b57cec5SDimitry Andric if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
32440b57cec5SDimitry Andric _registers.__r[regNum - UNW_MIPS_R0] = value;
32450b57cec5SDimitry Andric return;
32460b57cec5SDimitry Andric }
32470b57cec5SDimitry Andric
32480b57cec5SDimitry Andric switch (regNum) {
32490b57cec5SDimitry Andric case UNW_REG_IP:
32500b57cec5SDimitry Andric _registers.__pc = value;
32510b57cec5SDimitry Andric return;
32520b57cec5SDimitry Andric case UNW_REG_SP:
32530b57cec5SDimitry Andric _registers.__r[29] = value;
32540b57cec5SDimitry Andric return;
32555f757f3fSDimitry Andric #if __mips_isa_rev < 6
32560b57cec5SDimitry Andric case UNW_MIPS_HI:
32570b57cec5SDimitry Andric _registers.__hi = value;
32580b57cec5SDimitry Andric return;
32590b57cec5SDimitry Andric case UNW_MIPS_LO:
32600b57cec5SDimitry Andric _registers.__lo = value;
32610b57cec5SDimitry Andric return;
32625f757f3fSDimitry Andric #endif
32630b57cec5SDimitry Andric }
32640b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported mips_newabi register");
32650b57cec5SDimitry Andric }
32660b57cec5SDimitry Andric
validFloatRegister(int regNum) const32670b57cec5SDimitry Andric inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
32680b57cec5SDimitry Andric #ifdef __mips_hard_float
32690b57cec5SDimitry Andric if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
32700b57cec5SDimitry Andric return true;
32715ffd83dbSDimitry Andric #else
32725ffd83dbSDimitry Andric (void)regNum;
32730b57cec5SDimitry Andric #endif
32740b57cec5SDimitry Andric return false;
32750b57cec5SDimitry Andric }
32760b57cec5SDimitry Andric
getFloatRegister(int regNum) const32770b57cec5SDimitry Andric inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
32780b57cec5SDimitry Andric #ifdef __mips_hard_float
32790b57cec5SDimitry Andric assert(validFloatRegister(regNum));
32800b57cec5SDimitry Andric return _floats[regNum - UNW_MIPS_F0];
32810b57cec5SDimitry Andric #else
32825ffd83dbSDimitry Andric (void)regNum;
32830b57cec5SDimitry Andric _LIBUNWIND_ABORT("mips_newabi float support not implemented");
32840b57cec5SDimitry Andric #endif
32850b57cec5SDimitry Andric }
32860b57cec5SDimitry Andric
setFloatRegister(int regNum,double value)32870b57cec5SDimitry Andric inline void Registers_mips_newabi::setFloatRegister(int regNum,
32880b57cec5SDimitry Andric double value) {
32890b57cec5SDimitry Andric #ifdef __mips_hard_float
32900b57cec5SDimitry Andric assert(validFloatRegister(regNum));
32910b57cec5SDimitry Andric _floats[regNum - UNW_MIPS_F0] = value;
32920b57cec5SDimitry Andric #else
32935ffd83dbSDimitry Andric (void)regNum;
32945ffd83dbSDimitry Andric (void)value;
32950b57cec5SDimitry Andric _LIBUNWIND_ABORT("mips_newabi float support not implemented");
32960b57cec5SDimitry Andric #endif
32970b57cec5SDimitry Andric }
32980b57cec5SDimitry Andric
validVectorRegister(int) const32990b57cec5SDimitry Andric inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
33000b57cec5SDimitry Andric return false;
33010b57cec5SDimitry Andric }
33020b57cec5SDimitry Andric
getVectorRegister(int) const33030b57cec5SDimitry Andric inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
33040b57cec5SDimitry Andric _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
33050b57cec5SDimitry Andric }
33060b57cec5SDimitry Andric
setVectorRegister(int,v128)33070b57cec5SDimitry Andric inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
33080b57cec5SDimitry Andric _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
33090b57cec5SDimitry Andric }
33100b57cec5SDimitry Andric
getRegisterName(int regNum)33110b57cec5SDimitry Andric inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
33120b57cec5SDimitry Andric switch (regNum) {
33130b57cec5SDimitry Andric case UNW_MIPS_R0:
33140b57cec5SDimitry Andric return "$0";
33150b57cec5SDimitry Andric case UNW_MIPS_R1:
33160b57cec5SDimitry Andric return "$1";
33170b57cec5SDimitry Andric case UNW_MIPS_R2:
33180b57cec5SDimitry Andric return "$2";
33190b57cec5SDimitry Andric case UNW_MIPS_R3:
33200b57cec5SDimitry Andric return "$3";
33210b57cec5SDimitry Andric case UNW_MIPS_R4:
33220b57cec5SDimitry Andric return "$4";
33230b57cec5SDimitry Andric case UNW_MIPS_R5:
33240b57cec5SDimitry Andric return "$5";
33250b57cec5SDimitry Andric case UNW_MIPS_R6:
33260b57cec5SDimitry Andric return "$6";
33270b57cec5SDimitry Andric case UNW_MIPS_R7:
33280b57cec5SDimitry Andric return "$7";
33290b57cec5SDimitry Andric case UNW_MIPS_R8:
33300b57cec5SDimitry Andric return "$8";
33310b57cec5SDimitry Andric case UNW_MIPS_R9:
33320b57cec5SDimitry Andric return "$9";
33330b57cec5SDimitry Andric case UNW_MIPS_R10:
33340b57cec5SDimitry Andric return "$10";
33350b57cec5SDimitry Andric case UNW_MIPS_R11:
33360b57cec5SDimitry Andric return "$11";
33370b57cec5SDimitry Andric case UNW_MIPS_R12:
33380b57cec5SDimitry Andric return "$12";
33390b57cec5SDimitry Andric case UNW_MIPS_R13:
33400b57cec5SDimitry Andric return "$13";
33410b57cec5SDimitry Andric case UNW_MIPS_R14:
33420b57cec5SDimitry Andric return "$14";
33430b57cec5SDimitry Andric case UNW_MIPS_R15:
33440b57cec5SDimitry Andric return "$15";
33450b57cec5SDimitry Andric case UNW_MIPS_R16:
33460b57cec5SDimitry Andric return "$16";
33470b57cec5SDimitry Andric case UNW_MIPS_R17:
33480b57cec5SDimitry Andric return "$17";
33490b57cec5SDimitry Andric case UNW_MIPS_R18:
33500b57cec5SDimitry Andric return "$18";
33510b57cec5SDimitry Andric case UNW_MIPS_R19:
33520b57cec5SDimitry Andric return "$19";
33530b57cec5SDimitry Andric case UNW_MIPS_R20:
33540b57cec5SDimitry Andric return "$20";
33550b57cec5SDimitry Andric case UNW_MIPS_R21:
33560b57cec5SDimitry Andric return "$21";
33570b57cec5SDimitry Andric case UNW_MIPS_R22:
33580b57cec5SDimitry Andric return "$22";
33590b57cec5SDimitry Andric case UNW_MIPS_R23:
33600b57cec5SDimitry Andric return "$23";
33610b57cec5SDimitry Andric case UNW_MIPS_R24:
33620b57cec5SDimitry Andric return "$24";
33630b57cec5SDimitry Andric case UNW_MIPS_R25:
33640b57cec5SDimitry Andric return "$25";
33650b57cec5SDimitry Andric case UNW_MIPS_R26:
33660b57cec5SDimitry Andric return "$26";
33670b57cec5SDimitry Andric case UNW_MIPS_R27:
33680b57cec5SDimitry Andric return "$27";
33690b57cec5SDimitry Andric case UNW_MIPS_R28:
33700b57cec5SDimitry Andric return "$28";
33710b57cec5SDimitry Andric case UNW_MIPS_R29:
33720b57cec5SDimitry Andric return "$29";
33730b57cec5SDimitry Andric case UNW_MIPS_R30:
33740b57cec5SDimitry Andric return "$30";
33750b57cec5SDimitry Andric case UNW_MIPS_R31:
33760b57cec5SDimitry Andric return "$31";
33770b57cec5SDimitry Andric case UNW_MIPS_F0:
33780b57cec5SDimitry Andric return "$f0";
33790b57cec5SDimitry Andric case UNW_MIPS_F1:
33800b57cec5SDimitry Andric return "$f1";
33810b57cec5SDimitry Andric case UNW_MIPS_F2:
33820b57cec5SDimitry Andric return "$f2";
33830b57cec5SDimitry Andric case UNW_MIPS_F3:
33840b57cec5SDimitry Andric return "$f3";
33850b57cec5SDimitry Andric case UNW_MIPS_F4:
33860b57cec5SDimitry Andric return "$f4";
33870b57cec5SDimitry Andric case UNW_MIPS_F5:
33880b57cec5SDimitry Andric return "$f5";
33890b57cec5SDimitry Andric case UNW_MIPS_F6:
33900b57cec5SDimitry Andric return "$f6";
33910b57cec5SDimitry Andric case UNW_MIPS_F7:
33920b57cec5SDimitry Andric return "$f7";
33930b57cec5SDimitry Andric case UNW_MIPS_F8:
33940b57cec5SDimitry Andric return "$f8";
33950b57cec5SDimitry Andric case UNW_MIPS_F9:
33960b57cec5SDimitry Andric return "$f9";
33970b57cec5SDimitry Andric case UNW_MIPS_F10:
33980b57cec5SDimitry Andric return "$f10";
33990b57cec5SDimitry Andric case UNW_MIPS_F11:
34000b57cec5SDimitry Andric return "$f11";
34010b57cec5SDimitry Andric case UNW_MIPS_F12:
34020b57cec5SDimitry Andric return "$f12";
34030b57cec5SDimitry Andric case UNW_MIPS_F13:
34040b57cec5SDimitry Andric return "$f13";
34050b57cec5SDimitry Andric case UNW_MIPS_F14:
34060b57cec5SDimitry Andric return "$f14";
34070b57cec5SDimitry Andric case UNW_MIPS_F15:
34080b57cec5SDimitry Andric return "$f15";
34090b57cec5SDimitry Andric case UNW_MIPS_F16:
34100b57cec5SDimitry Andric return "$f16";
34110b57cec5SDimitry Andric case UNW_MIPS_F17:
34120b57cec5SDimitry Andric return "$f17";
34130b57cec5SDimitry Andric case UNW_MIPS_F18:
34140b57cec5SDimitry Andric return "$f18";
34150b57cec5SDimitry Andric case UNW_MIPS_F19:
34160b57cec5SDimitry Andric return "$f19";
34170b57cec5SDimitry Andric case UNW_MIPS_F20:
34180b57cec5SDimitry Andric return "$f20";
34190b57cec5SDimitry Andric case UNW_MIPS_F21:
34200b57cec5SDimitry Andric return "$f21";
34210b57cec5SDimitry Andric case UNW_MIPS_F22:
34220b57cec5SDimitry Andric return "$f22";
34230b57cec5SDimitry Andric case UNW_MIPS_F23:
34240b57cec5SDimitry Andric return "$f23";
34250b57cec5SDimitry Andric case UNW_MIPS_F24:
34260b57cec5SDimitry Andric return "$f24";
34270b57cec5SDimitry Andric case UNW_MIPS_F25:
34280b57cec5SDimitry Andric return "$f25";
34290b57cec5SDimitry Andric case UNW_MIPS_F26:
34300b57cec5SDimitry Andric return "$f26";
34310b57cec5SDimitry Andric case UNW_MIPS_F27:
34320b57cec5SDimitry Andric return "$f27";
34330b57cec5SDimitry Andric case UNW_MIPS_F28:
34340b57cec5SDimitry Andric return "$f28";
34350b57cec5SDimitry Andric case UNW_MIPS_F29:
34360b57cec5SDimitry Andric return "$f29";
34370b57cec5SDimitry Andric case UNW_MIPS_F30:
34380b57cec5SDimitry Andric return "$f30";
34390b57cec5SDimitry Andric case UNW_MIPS_F31:
34400b57cec5SDimitry Andric return "$f31";
34415f757f3fSDimitry Andric #if __mips_isa_rev < 6
34420b57cec5SDimitry Andric case UNW_MIPS_HI:
34430b57cec5SDimitry Andric return "$hi";
34440b57cec5SDimitry Andric case UNW_MIPS_LO:
34450b57cec5SDimitry Andric return "$lo";
34465f757f3fSDimitry Andric #endif
34470b57cec5SDimitry Andric default:
34480b57cec5SDimitry Andric return "unknown register";
34490b57cec5SDimitry Andric }
34500b57cec5SDimitry Andric }
34510b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_MIPS_NEWABI
34520b57cec5SDimitry Andric
34530b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_SPARC)
34540b57cec5SDimitry Andric /// Registers_sparc holds the register state of a thread in a 32-bit Sparc
34550b57cec5SDimitry Andric /// process.
34560b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN Registers_sparc {
34570b57cec5SDimitry Andric public:
34580b57cec5SDimitry Andric Registers_sparc();
34590b57cec5SDimitry Andric Registers_sparc(const void *registers);
34600b57cec5SDimitry Andric
34610b57cec5SDimitry Andric bool validRegister(int num) const;
34620b57cec5SDimitry Andric uint32_t getRegister(int num) const;
34630b57cec5SDimitry Andric void setRegister(int num, uint32_t value);
34640b57cec5SDimitry Andric bool validFloatRegister(int num) const;
34650b57cec5SDimitry Andric double getFloatRegister(int num) const;
34660b57cec5SDimitry Andric void setFloatRegister(int num, double value);
34670b57cec5SDimitry Andric bool validVectorRegister(int num) const;
34680b57cec5SDimitry Andric v128 getVectorRegister(int num) const;
34690b57cec5SDimitry Andric void setVectorRegister(int num, v128 value);
34700b57cec5SDimitry Andric static const char *getRegisterName(int num);
34710b57cec5SDimitry Andric void jumpto();
lastDwarfRegNum()347281ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
347381ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC;
347481ad6265SDimitry Andric }
getArch()34750b57cec5SDimitry Andric static int getArch() { return REGISTERS_SPARC; }
34760b57cec5SDimitry Andric
getSP() const34770b57cec5SDimitry Andric uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
setSP(uint32_t value)34780b57cec5SDimitry Andric void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
getIP() const34790b57cec5SDimitry Andric uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
setIP(uint32_t value)34800b57cec5SDimitry Andric void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
34810b57cec5SDimitry Andric
34820b57cec5SDimitry Andric private:
34830b57cec5SDimitry Andric struct sparc_thread_state_t {
34840b57cec5SDimitry Andric unsigned int __regs[32];
34850b57cec5SDimitry Andric };
34860b57cec5SDimitry Andric
34870b57cec5SDimitry Andric sparc_thread_state_t _registers;
34880b57cec5SDimitry Andric };
34890b57cec5SDimitry Andric
Registers_sparc(const void * registers)34900b57cec5SDimitry Andric inline Registers_sparc::Registers_sparc(const void *registers) {
34910b57cec5SDimitry Andric static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
34920b57cec5SDimitry Andric "sparc registers do not fit into unw_context_t");
34930b57cec5SDimitry Andric memcpy(&_registers, static_cast<const uint8_t *>(registers),
34940b57cec5SDimitry Andric sizeof(_registers));
34950b57cec5SDimitry Andric }
34960b57cec5SDimitry Andric
Registers_sparc()34970b57cec5SDimitry Andric inline Registers_sparc::Registers_sparc() {
34980b57cec5SDimitry Andric memset(&_registers, 0, sizeof(_registers));
34990b57cec5SDimitry Andric }
35000b57cec5SDimitry Andric
validRegister(int regNum) const35010b57cec5SDimitry Andric inline bool Registers_sparc::validRegister(int regNum) const {
35020b57cec5SDimitry Andric if (regNum == UNW_REG_IP)
35030b57cec5SDimitry Andric return true;
35040b57cec5SDimitry Andric if (regNum == UNW_REG_SP)
35050b57cec5SDimitry Andric return true;
35060b57cec5SDimitry Andric if (regNum < 0)
35070b57cec5SDimitry Andric return false;
35080b57cec5SDimitry Andric if (regNum <= UNW_SPARC_I7)
35090b57cec5SDimitry Andric return true;
35100b57cec5SDimitry Andric return false;
35110b57cec5SDimitry Andric }
35120b57cec5SDimitry Andric
getRegister(int regNum) const35130b57cec5SDimitry Andric inline uint32_t Registers_sparc::getRegister(int regNum) const {
35140b57cec5SDimitry Andric if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
35150b57cec5SDimitry Andric return _registers.__regs[regNum];
35160b57cec5SDimitry Andric }
35170b57cec5SDimitry Andric
35180b57cec5SDimitry Andric switch (regNum) {
35190b57cec5SDimitry Andric case UNW_REG_IP:
35200b57cec5SDimitry Andric return _registers.__regs[UNW_SPARC_O7];
35210b57cec5SDimitry Andric case UNW_REG_SP:
35220b57cec5SDimitry Andric return _registers.__regs[UNW_SPARC_O6];
35230b57cec5SDimitry Andric }
35240b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported sparc register");
35250b57cec5SDimitry Andric }
35260b57cec5SDimitry Andric
setRegister(int regNum,uint32_t value)35270b57cec5SDimitry Andric inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
35280b57cec5SDimitry Andric if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
35290b57cec5SDimitry Andric _registers.__regs[regNum] = value;
35300b57cec5SDimitry Andric return;
35310b57cec5SDimitry Andric }
35320b57cec5SDimitry Andric
35330b57cec5SDimitry Andric switch (regNum) {
35340b57cec5SDimitry Andric case UNW_REG_IP:
35350b57cec5SDimitry Andric _registers.__regs[UNW_SPARC_O7] = value;
35360b57cec5SDimitry Andric return;
35370b57cec5SDimitry Andric case UNW_REG_SP:
35380b57cec5SDimitry Andric _registers.__regs[UNW_SPARC_O6] = value;
35390b57cec5SDimitry Andric return;
35400b57cec5SDimitry Andric }
35410b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported sparc register");
35420b57cec5SDimitry Andric }
35430b57cec5SDimitry Andric
validFloatRegister(int) const35440b57cec5SDimitry Andric inline bool Registers_sparc::validFloatRegister(int) const { return false; }
35450b57cec5SDimitry Andric
getFloatRegister(int) const35460b57cec5SDimitry Andric inline double Registers_sparc::getFloatRegister(int) const {
35470b57cec5SDimitry Andric _LIBUNWIND_ABORT("no Sparc float registers");
35480b57cec5SDimitry Andric }
35490b57cec5SDimitry Andric
setFloatRegister(int,double)35500b57cec5SDimitry Andric inline void Registers_sparc::setFloatRegister(int, double) {
35510b57cec5SDimitry Andric _LIBUNWIND_ABORT("no Sparc float registers");
35520b57cec5SDimitry Andric }
35530b57cec5SDimitry Andric
validVectorRegister(int) const35540b57cec5SDimitry Andric inline bool Registers_sparc::validVectorRegister(int) const { return false; }
35550b57cec5SDimitry Andric
getVectorRegister(int) const35560b57cec5SDimitry Andric inline v128 Registers_sparc::getVectorRegister(int) const {
35570b57cec5SDimitry Andric _LIBUNWIND_ABORT("no Sparc vector registers");
35580b57cec5SDimitry Andric }
35590b57cec5SDimitry Andric
setVectorRegister(int,v128)35600b57cec5SDimitry Andric inline void Registers_sparc::setVectorRegister(int, v128) {
35610b57cec5SDimitry Andric _LIBUNWIND_ABORT("no Sparc vector registers");
35620b57cec5SDimitry Andric }
35630b57cec5SDimitry Andric
getRegisterName(int regNum)35640b57cec5SDimitry Andric inline const char *Registers_sparc::getRegisterName(int regNum) {
35650b57cec5SDimitry Andric switch (regNum) {
35660b57cec5SDimitry Andric case UNW_REG_IP:
35670b57cec5SDimitry Andric return "pc";
35680b57cec5SDimitry Andric case UNW_SPARC_G0:
35690b57cec5SDimitry Andric return "g0";
35700b57cec5SDimitry Andric case UNW_SPARC_G1:
35710b57cec5SDimitry Andric return "g1";
35720b57cec5SDimitry Andric case UNW_SPARC_G2:
35730b57cec5SDimitry Andric return "g2";
35740b57cec5SDimitry Andric case UNW_SPARC_G3:
35750b57cec5SDimitry Andric return "g3";
35760b57cec5SDimitry Andric case UNW_SPARC_G4:
35770b57cec5SDimitry Andric return "g4";
35780b57cec5SDimitry Andric case UNW_SPARC_G5:
35790b57cec5SDimitry Andric return "g5";
35800b57cec5SDimitry Andric case UNW_SPARC_G6:
35810b57cec5SDimitry Andric return "g6";
35820b57cec5SDimitry Andric case UNW_SPARC_G7:
35830b57cec5SDimitry Andric return "g7";
35840b57cec5SDimitry Andric case UNW_SPARC_O0:
35850b57cec5SDimitry Andric return "o0";
35860b57cec5SDimitry Andric case UNW_SPARC_O1:
35870b57cec5SDimitry Andric return "o1";
35880b57cec5SDimitry Andric case UNW_SPARC_O2:
35890b57cec5SDimitry Andric return "o2";
35900b57cec5SDimitry Andric case UNW_SPARC_O3:
35910b57cec5SDimitry Andric return "o3";
35920b57cec5SDimitry Andric case UNW_SPARC_O4:
35930b57cec5SDimitry Andric return "o4";
35940b57cec5SDimitry Andric case UNW_SPARC_O5:
35950b57cec5SDimitry Andric return "o5";
35960b57cec5SDimitry Andric case UNW_REG_SP:
35970b57cec5SDimitry Andric case UNW_SPARC_O6:
35980b57cec5SDimitry Andric return "sp";
35990b57cec5SDimitry Andric case UNW_SPARC_O7:
36000b57cec5SDimitry Andric return "o7";
36010b57cec5SDimitry Andric case UNW_SPARC_L0:
36020b57cec5SDimitry Andric return "l0";
36030b57cec5SDimitry Andric case UNW_SPARC_L1:
36040b57cec5SDimitry Andric return "l1";
36050b57cec5SDimitry Andric case UNW_SPARC_L2:
36060b57cec5SDimitry Andric return "l2";
36070b57cec5SDimitry Andric case UNW_SPARC_L3:
36080b57cec5SDimitry Andric return "l3";
36090b57cec5SDimitry Andric case UNW_SPARC_L4:
36100b57cec5SDimitry Andric return "l4";
36110b57cec5SDimitry Andric case UNW_SPARC_L5:
36120b57cec5SDimitry Andric return "l5";
36130b57cec5SDimitry Andric case UNW_SPARC_L6:
36140b57cec5SDimitry Andric return "l6";
36150b57cec5SDimitry Andric case UNW_SPARC_L7:
36160b57cec5SDimitry Andric return "l7";
36170b57cec5SDimitry Andric case UNW_SPARC_I0:
36180b57cec5SDimitry Andric return "i0";
36190b57cec5SDimitry Andric case UNW_SPARC_I1:
36200b57cec5SDimitry Andric return "i1";
36210b57cec5SDimitry Andric case UNW_SPARC_I2:
36220b57cec5SDimitry Andric return "i2";
36230b57cec5SDimitry Andric case UNW_SPARC_I3:
36240b57cec5SDimitry Andric return "i3";
36250b57cec5SDimitry Andric case UNW_SPARC_I4:
36260b57cec5SDimitry Andric return "i4";
36270b57cec5SDimitry Andric case UNW_SPARC_I5:
36280b57cec5SDimitry Andric return "i5";
36290b57cec5SDimitry Andric case UNW_SPARC_I6:
36300b57cec5SDimitry Andric return "fp";
36310b57cec5SDimitry Andric case UNW_SPARC_I7:
36320b57cec5SDimitry Andric return "i7";
36330b57cec5SDimitry Andric default:
36340b57cec5SDimitry Andric return "unknown register";
36350b57cec5SDimitry Andric }
36360b57cec5SDimitry Andric }
36370b57cec5SDimitry Andric #endif // _LIBUNWIND_TARGET_SPARC
36380b57cec5SDimitry Andric
3639d56accc7SDimitry Andric #if defined(_LIBUNWIND_TARGET_SPARC64)
3640d56accc7SDimitry Andric /// Registers_sparc64 holds the register state of a thread in a 64-bit
3641d56accc7SDimitry Andric /// sparc process.
3642d56accc7SDimitry Andric class _LIBUNWIND_HIDDEN Registers_sparc64 {
3643d56accc7SDimitry Andric public:
3644d56accc7SDimitry Andric Registers_sparc64() = default;
3645d56accc7SDimitry Andric Registers_sparc64(const void *registers);
3646d56accc7SDimitry Andric
3647d56accc7SDimitry Andric bool validRegister(int num) const;
3648d56accc7SDimitry Andric uint64_t getRegister(int num) const;
3649d56accc7SDimitry Andric void setRegister(int num, uint64_t value);
3650d56accc7SDimitry Andric bool validFloatRegister(int num) const;
3651d56accc7SDimitry Andric double getFloatRegister(int num) const;
3652d56accc7SDimitry Andric void setFloatRegister(int num, double value);
3653d56accc7SDimitry Andric bool validVectorRegister(int num) const;
3654d56accc7SDimitry Andric v128 getVectorRegister(int num) const;
3655d56accc7SDimitry Andric void setVectorRegister(int num, v128 value);
3656d56accc7SDimitry Andric const char *getRegisterName(int num);
3657d56accc7SDimitry Andric void jumpto();
lastDwarfRegNum()365881ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
3659d56accc7SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;
3660d56accc7SDimitry Andric }
getArch()3661d56accc7SDimitry Andric static int getArch() { return REGISTERS_SPARC64; }
3662d56accc7SDimitry Andric
getSP() const3663d56accc7SDimitry Andric uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; }
setSP(uint64_t value)3664d56accc7SDimitry Andric void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; }
getIP() const3665d56accc7SDimitry Andric uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
setIP(uint64_t value)3666d56accc7SDimitry Andric void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
getWCookie() const3667d56accc7SDimitry Andric uint64_t getWCookie() const { return _wcookie; }
3668d56accc7SDimitry Andric
3669d56accc7SDimitry Andric private:
3670d56accc7SDimitry Andric struct sparc64_thread_state_t {
3671d56accc7SDimitry Andric uint64_t __regs[32];
3672d56accc7SDimitry Andric };
3673d56accc7SDimitry Andric
3674d56accc7SDimitry Andric sparc64_thread_state_t _registers{};
3675d56accc7SDimitry Andric uint64_t _wcookie = 0;
3676d56accc7SDimitry Andric };
3677d56accc7SDimitry Andric
Registers_sparc64(const void * registers)3678d56accc7SDimitry Andric inline Registers_sparc64::Registers_sparc64(const void *registers) {
3679d56accc7SDimitry Andric static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit),
3680d56accc7SDimitry Andric "sparc64 registers do not fit into unw_context_t");
3681d56accc7SDimitry Andric memcpy(&_registers, registers, sizeof(_registers));
3682d56accc7SDimitry Andric memcpy(&_wcookie,
3683d56accc7SDimitry Andric static_cast<const uint8_t *>(registers) + sizeof(_registers),
3684d56accc7SDimitry Andric sizeof(_wcookie));
3685d56accc7SDimitry Andric }
3686d56accc7SDimitry Andric
validRegister(int regNum) const3687d56accc7SDimitry Andric inline bool Registers_sparc64::validRegister(int regNum) const {
3688d56accc7SDimitry Andric if (regNum == UNW_REG_IP)
3689d56accc7SDimitry Andric return true;
3690d56accc7SDimitry Andric if (regNum == UNW_REG_SP)
3691d56accc7SDimitry Andric return true;
3692d56accc7SDimitry Andric if (regNum < 0)
3693d56accc7SDimitry Andric return false;
3694d56accc7SDimitry Andric if (regNum <= UNW_SPARC_I7)
3695d56accc7SDimitry Andric return true;
3696d56accc7SDimitry Andric return false;
3697d56accc7SDimitry Andric }
3698d56accc7SDimitry Andric
getRegister(int regNum) const3699d56accc7SDimitry Andric inline uint64_t Registers_sparc64::getRegister(int regNum) const {
3700d56accc7SDimitry Andric if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7)
3701d56accc7SDimitry Andric return _registers.__regs[regNum];
3702d56accc7SDimitry Andric
3703d56accc7SDimitry Andric switch (regNum) {
3704d56accc7SDimitry Andric case UNW_REG_IP:
3705d56accc7SDimitry Andric return _registers.__regs[UNW_SPARC_O7];
3706d56accc7SDimitry Andric case UNW_REG_SP:
3707d56accc7SDimitry Andric return _registers.__regs[UNW_SPARC_O6] + 2047;
3708d56accc7SDimitry Andric }
3709d56accc7SDimitry Andric _LIBUNWIND_ABORT("unsupported sparc64 register");
3710d56accc7SDimitry Andric }
3711d56accc7SDimitry Andric
setRegister(int regNum,uint64_t value)3712d56accc7SDimitry Andric inline void Registers_sparc64::setRegister(int regNum, uint64_t value) {
3713d56accc7SDimitry Andric if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) {
3714d56accc7SDimitry Andric _registers.__regs[regNum] = value;
3715d56accc7SDimitry Andric return;
3716d56accc7SDimitry Andric }
3717d56accc7SDimitry Andric
3718d56accc7SDimitry Andric switch (regNum) {
3719d56accc7SDimitry Andric case UNW_REG_IP:
3720d56accc7SDimitry Andric _registers.__regs[UNW_SPARC_O7] = value;
3721d56accc7SDimitry Andric return;
3722d56accc7SDimitry Andric case UNW_REG_SP:
3723d56accc7SDimitry Andric _registers.__regs[UNW_SPARC_O6] = value - 2047;
3724d56accc7SDimitry Andric return;
3725d56accc7SDimitry Andric }
3726d56accc7SDimitry Andric _LIBUNWIND_ABORT("unsupported sparc64 register");
3727d56accc7SDimitry Andric }
3728d56accc7SDimitry Andric
validFloatRegister(int) const3729d56accc7SDimitry Andric inline bool Registers_sparc64::validFloatRegister(int) const { return false; }
3730d56accc7SDimitry Andric
getFloatRegister(int) const3731d56accc7SDimitry Andric inline double Registers_sparc64::getFloatRegister(int) const {
3732d56accc7SDimitry Andric _LIBUNWIND_ABORT("no sparc64 float registers");
3733d56accc7SDimitry Andric }
3734d56accc7SDimitry Andric
setFloatRegister(int,double)3735d56accc7SDimitry Andric inline void Registers_sparc64::setFloatRegister(int, double) {
3736d56accc7SDimitry Andric _LIBUNWIND_ABORT("no sparc64 float registers");
3737d56accc7SDimitry Andric }
3738d56accc7SDimitry Andric
validVectorRegister(int) const3739d56accc7SDimitry Andric inline bool Registers_sparc64::validVectorRegister(int) const { return false; }
3740d56accc7SDimitry Andric
getVectorRegister(int) const3741d56accc7SDimitry Andric inline v128 Registers_sparc64::getVectorRegister(int) const {
3742d56accc7SDimitry Andric _LIBUNWIND_ABORT("no sparc64 vector registers");
3743d56accc7SDimitry Andric }
3744d56accc7SDimitry Andric
setVectorRegister(int,v128)3745d56accc7SDimitry Andric inline void Registers_sparc64::setVectorRegister(int, v128) {
3746d56accc7SDimitry Andric _LIBUNWIND_ABORT("no sparc64 vector registers");
3747d56accc7SDimitry Andric }
3748d56accc7SDimitry Andric
getRegisterName(int regNum)3749d56accc7SDimitry Andric inline const char *Registers_sparc64::getRegisterName(int regNum) {
3750d56accc7SDimitry Andric switch (regNum) {
3751d56accc7SDimitry Andric case UNW_REG_IP:
3752d56accc7SDimitry Andric return "pc";
3753d56accc7SDimitry Andric case UNW_SPARC_G0:
3754d56accc7SDimitry Andric return "g0";
3755d56accc7SDimitry Andric case UNW_SPARC_G1:
3756d56accc7SDimitry Andric return "g1";
3757d56accc7SDimitry Andric case UNW_SPARC_G2:
3758d56accc7SDimitry Andric return "g2";
3759d56accc7SDimitry Andric case UNW_SPARC_G3:
3760d56accc7SDimitry Andric return "g3";
3761d56accc7SDimitry Andric case UNW_SPARC_G4:
3762d56accc7SDimitry Andric return "g4";
3763d56accc7SDimitry Andric case UNW_SPARC_G5:
3764d56accc7SDimitry Andric return "g5";
3765d56accc7SDimitry Andric case UNW_SPARC_G6:
3766d56accc7SDimitry Andric return "g6";
3767d56accc7SDimitry Andric case UNW_SPARC_G7:
3768d56accc7SDimitry Andric return "g7";
3769d56accc7SDimitry Andric case UNW_SPARC_O0:
3770d56accc7SDimitry Andric return "o0";
3771d56accc7SDimitry Andric case UNW_SPARC_O1:
3772d56accc7SDimitry Andric return "o1";
3773d56accc7SDimitry Andric case UNW_SPARC_O2:
3774d56accc7SDimitry Andric return "o2";
3775d56accc7SDimitry Andric case UNW_SPARC_O3:
3776d56accc7SDimitry Andric return "o3";
3777d56accc7SDimitry Andric case UNW_SPARC_O4:
3778d56accc7SDimitry Andric return "o4";
3779d56accc7SDimitry Andric case UNW_SPARC_O5:
3780d56accc7SDimitry Andric return "o5";
3781d56accc7SDimitry Andric case UNW_REG_SP:
3782d56accc7SDimitry Andric case UNW_SPARC_O6:
3783d56accc7SDimitry Andric return "o6";
3784d56accc7SDimitry Andric case UNW_SPARC_O7:
3785d56accc7SDimitry Andric return "o7";
3786d56accc7SDimitry Andric case UNW_SPARC_L0:
3787d56accc7SDimitry Andric return "l0";
3788d56accc7SDimitry Andric case UNW_SPARC_L1:
3789d56accc7SDimitry Andric return "l1";
3790d56accc7SDimitry Andric case UNW_SPARC_L2:
3791d56accc7SDimitry Andric return "l2";
3792d56accc7SDimitry Andric case UNW_SPARC_L3:
3793d56accc7SDimitry Andric return "l3";
3794d56accc7SDimitry Andric case UNW_SPARC_L4:
3795d56accc7SDimitry Andric return "l4";
3796d56accc7SDimitry Andric case UNW_SPARC_L5:
3797d56accc7SDimitry Andric return "l5";
3798d56accc7SDimitry Andric case UNW_SPARC_L6:
3799d56accc7SDimitry Andric return "l6";
3800d56accc7SDimitry Andric case UNW_SPARC_L7:
3801d56accc7SDimitry Andric return "l7";
3802d56accc7SDimitry Andric case UNW_SPARC_I0:
3803d56accc7SDimitry Andric return "i0";
3804d56accc7SDimitry Andric case UNW_SPARC_I1:
3805d56accc7SDimitry Andric return "i1";
3806d56accc7SDimitry Andric case UNW_SPARC_I2:
3807d56accc7SDimitry Andric return "i2";
3808d56accc7SDimitry Andric case UNW_SPARC_I3:
3809d56accc7SDimitry Andric return "i3";
3810d56accc7SDimitry Andric case UNW_SPARC_I4:
3811d56accc7SDimitry Andric return "i4";
3812d56accc7SDimitry Andric case UNW_SPARC_I5:
3813d56accc7SDimitry Andric return "i5";
3814d56accc7SDimitry Andric case UNW_SPARC_I6:
3815d56accc7SDimitry Andric return "i6";
3816d56accc7SDimitry Andric case UNW_SPARC_I7:
3817d56accc7SDimitry Andric return "i7";
3818d56accc7SDimitry Andric default:
3819d56accc7SDimitry Andric return "unknown register";
3820d56accc7SDimitry Andric }
3821d56accc7SDimitry Andric }
3822d56accc7SDimitry Andric #endif // _LIBUNWIND_TARGET_SPARC64
3823d56accc7SDimitry Andric
38245ffd83dbSDimitry Andric #if defined(_LIBUNWIND_TARGET_HEXAGON)
38255ffd83dbSDimitry Andric /// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
38265ffd83dbSDimitry Andric /// process.
38275ffd83dbSDimitry Andric class _LIBUNWIND_HIDDEN Registers_hexagon {
38285ffd83dbSDimitry Andric public:
38295ffd83dbSDimitry Andric Registers_hexagon();
38305ffd83dbSDimitry Andric Registers_hexagon(const void *registers);
38315ffd83dbSDimitry Andric
38325ffd83dbSDimitry Andric bool validRegister(int num) const;
38335ffd83dbSDimitry Andric uint32_t getRegister(int num) const;
38345ffd83dbSDimitry Andric void setRegister(int num, uint32_t value);
38355ffd83dbSDimitry Andric bool validFloatRegister(int num) const;
38365ffd83dbSDimitry Andric double getFloatRegister(int num) const;
38375ffd83dbSDimitry Andric void setFloatRegister(int num, double value);
38385ffd83dbSDimitry Andric bool validVectorRegister(int num) const;
38395ffd83dbSDimitry Andric v128 getVectorRegister(int num) const;
38405ffd83dbSDimitry Andric void setVectorRegister(int num, v128 value);
38415ffd83dbSDimitry Andric const char *getRegisterName(int num);
38425ffd83dbSDimitry Andric void jumpto();
lastDwarfRegNum()384381ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
384481ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON;
384581ad6265SDimitry Andric }
getArch()38465ffd83dbSDimitry Andric static int getArch() { return REGISTERS_HEXAGON; }
38475ffd83dbSDimitry Andric
getSP() const38485ffd83dbSDimitry Andric uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }
setSP(uint32_t value)38495ffd83dbSDimitry Andric void setSP(uint32_t value) { _registers.__r[UNW_HEXAGON_R29] = value; }
getIP() const38505ffd83dbSDimitry Andric uint32_t getIP() const { return _registers.__r[UNW_HEXAGON_PC]; }
setIP(uint32_t value)38515ffd83dbSDimitry Andric void setIP(uint32_t value) { _registers.__r[UNW_HEXAGON_PC] = value; }
38525ffd83dbSDimitry Andric
38535ffd83dbSDimitry Andric private:
38545ffd83dbSDimitry Andric struct hexagon_thread_state_t {
38555ffd83dbSDimitry Andric unsigned int __r[35];
38565ffd83dbSDimitry Andric };
38575ffd83dbSDimitry Andric
38585ffd83dbSDimitry Andric hexagon_thread_state_t _registers;
38595ffd83dbSDimitry Andric };
38605ffd83dbSDimitry Andric
Registers_hexagon(const void * registers)38615ffd83dbSDimitry Andric inline Registers_hexagon::Registers_hexagon(const void *registers) {
38625ffd83dbSDimitry Andric static_assert((check_fit<Registers_hexagon, unw_context_t>::does_fit),
38635ffd83dbSDimitry Andric "hexagon registers do not fit into unw_context_t");
38645ffd83dbSDimitry Andric memcpy(&_registers, static_cast<const uint8_t *>(registers),
38655ffd83dbSDimitry Andric sizeof(_registers));
38665ffd83dbSDimitry Andric }
38675ffd83dbSDimitry Andric
Registers_hexagon()38685ffd83dbSDimitry Andric inline Registers_hexagon::Registers_hexagon() {
38695ffd83dbSDimitry Andric memset(&_registers, 0, sizeof(_registers));
38705ffd83dbSDimitry Andric }
38715ffd83dbSDimitry Andric
validRegister(int regNum) const38725ffd83dbSDimitry Andric inline bool Registers_hexagon::validRegister(int regNum) const {
38735ffd83dbSDimitry Andric if (regNum <= UNW_HEXAGON_R31)
38745ffd83dbSDimitry Andric return true;
38755ffd83dbSDimitry Andric return false;
38765ffd83dbSDimitry Andric }
38775ffd83dbSDimitry Andric
getRegister(int regNum) const38785ffd83dbSDimitry Andric inline uint32_t Registers_hexagon::getRegister(int regNum) const {
38795ffd83dbSDimitry Andric if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31)
38805ffd83dbSDimitry Andric return _registers.__r[regNum - UNW_HEXAGON_R0];
38815ffd83dbSDimitry Andric
38825ffd83dbSDimitry Andric switch (regNum) {
38835ffd83dbSDimitry Andric case UNW_REG_IP:
38845ffd83dbSDimitry Andric return _registers.__r[UNW_HEXAGON_PC];
38855ffd83dbSDimitry Andric case UNW_REG_SP:
38865ffd83dbSDimitry Andric return _registers.__r[UNW_HEXAGON_R29];
38875ffd83dbSDimitry Andric }
38885ffd83dbSDimitry Andric _LIBUNWIND_ABORT("unsupported hexagon register");
38895ffd83dbSDimitry Andric }
38905ffd83dbSDimitry Andric
setRegister(int regNum,uint32_t value)38915ffd83dbSDimitry Andric inline void Registers_hexagon::setRegister(int regNum, uint32_t value) {
38925ffd83dbSDimitry Andric if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) {
38935ffd83dbSDimitry Andric _registers.__r[regNum - UNW_HEXAGON_R0] = value;
38945ffd83dbSDimitry Andric return;
38955ffd83dbSDimitry Andric }
38965ffd83dbSDimitry Andric
38975ffd83dbSDimitry Andric switch (regNum) {
38985ffd83dbSDimitry Andric case UNW_REG_IP:
38995ffd83dbSDimitry Andric _registers.__r[UNW_HEXAGON_PC] = value;
39005ffd83dbSDimitry Andric return;
39015ffd83dbSDimitry Andric case UNW_REG_SP:
39025ffd83dbSDimitry Andric _registers.__r[UNW_HEXAGON_R29] = value;
39035ffd83dbSDimitry Andric return;
39045ffd83dbSDimitry Andric }
39055ffd83dbSDimitry Andric _LIBUNWIND_ABORT("unsupported hexagon register");
39065ffd83dbSDimitry Andric }
39075ffd83dbSDimitry Andric
validFloatRegister(int) const39085ffd83dbSDimitry Andric inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {
39095ffd83dbSDimitry Andric return false;
39105ffd83dbSDimitry Andric }
39115ffd83dbSDimitry Andric
getFloatRegister(int) const39125ffd83dbSDimitry Andric inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {
39135ffd83dbSDimitry Andric _LIBUNWIND_ABORT("hexagon float support not implemented");
39145ffd83dbSDimitry Andric }
39155ffd83dbSDimitry Andric
setFloatRegister(int,double)39165ffd83dbSDimitry Andric inline void Registers_hexagon::setFloatRegister(int /* regNum */,
39175ffd83dbSDimitry Andric double /* value */) {
39185ffd83dbSDimitry Andric _LIBUNWIND_ABORT("hexagon float support not implemented");
39195ffd83dbSDimitry Andric }
39205ffd83dbSDimitry Andric
validVectorRegister(int) const39215ffd83dbSDimitry Andric inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {
39225ffd83dbSDimitry Andric return false;
39235ffd83dbSDimitry Andric }
39245ffd83dbSDimitry Andric
getVectorRegister(int) const39255ffd83dbSDimitry Andric inline v128 Registers_hexagon::getVectorRegister(int /* regNum */) const {
39265ffd83dbSDimitry Andric _LIBUNWIND_ABORT("hexagon vector support not implemented");
39275ffd83dbSDimitry Andric }
39285ffd83dbSDimitry Andric
setVectorRegister(int,v128)39295ffd83dbSDimitry Andric inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128 /* value */) {
39305ffd83dbSDimitry Andric _LIBUNWIND_ABORT("hexagon vector support not implemented");
39315ffd83dbSDimitry Andric }
39325ffd83dbSDimitry Andric
getRegisterName(int regNum)39335ffd83dbSDimitry Andric inline const char *Registers_hexagon::getRegisterName(int regNum) {
39345ffd83dbSDimitry Andric switch (regNum) {
39355ffd83dbSDimitry Andric case UNW_HEXAGON_R0:
39365ffd83dbSDimitry Andric return "r0";
39375ffd83dbSDimitry Andric case UNW_HEXAGON_R1:
39385ffd83dbSDimitry Andric return "r1";
39395ffd83dbSDimitry Andric case UNW_HEXAGON_R2:
39405ffd83dbSDimitry Andric return "r2";
39415ffd83dbSDimitry Andric case UNW_HEXAGON_R3:
39425ffd83dbSDimitry Andric return "r3";
39435ffd83dbSDimitry Andric case UNW_HEXAGON_R4:
39445ffd83dbSDimitry Andric return "r4";
39455ffd83dbSDimitry Andric case UNW_HEXAGON_R5:
39465ffd83dbSDimitry Andric return "r5";
39475ffd83dbSDimitry Andric case UNW_HEXAGON_R6:
39485ffd83dbSDimitry Andric return "r6";
39495ffd83dbSDimitry Andric case UNW_HEXAGON_R7:
39505ffd83dbSDimitry Andric return "r7";
39515ffd83dbSDimitry Andric case UNW_HEXAGON_R8:
39525ffd83dbSDimitry Andric return "r8";
39535ffd83dbSDimitry Andric case UNW_HEXAGON_R9:
39545ffd83dbSDimitry Andric return "r9";
39555ffd83dbSDimitry Andric case UNW_HEXAGON_R10:
39565ffd83dbSDimitry Andric return "r10";
39575ffd83dbSDimitry Andric case UNW_HEXAGON_R11:
39585ffd83dbSDimitry Andric return "r11";
39595ffd83dbSDimitry Andric case UNW_HEXAGON_R12:
39605ffd83dbSDimitry Andric return "r12";
39615ffd83dbSDimitry Andric case UNW_HEXAGON_R13:
39625ffd83dbSDimitry Andric return "r13";
39635ffd83dbSDimitry Andric case UNW_HEXAGON_R14:
39645ffd83dbSDimitry Andric return "r14";
39655ffd83dbSDimitry Andric case UNW_HEXAGON_R15:
39665ffd83dbSDimitry Andric return "r15";
39675ffd83dbSDimitry Andric case UNW_HEXAGON_R16:
39685ffd83dbSDimitry Andric return "r16";
39695ffd83dbSDimitry Andric case UNW_HEXAGON_R17:
39705ffd83dbSDimitry Andric return "r17";
39715ffd83dbSDimitry Andric case UNW_HEXAGON_R18:
39725ffd83dbSDimitry Andric return "r18";
39735ffd83dbSDimitry Andric case UNW_HEXAGON_R19:
39745ffd83dbSDimitry Andric return "r19";
39755ffd83dbSDimitry Andric case UNW_HEXAGON_R20:
39765ffd83dbSDimitry Andric return "r20";
39775ffd83dbSDimitry Andric case UNW_HEXAGON_R21:
39785ffd83dbSDimitry Andric return "r21";
39795ffd83dbSDimitry Andric case UNW_HEXAGON_R22:
39805ffd83dbSDimitry Andric return "r22";
39815ffd83dbSDimitry Andric case UNW_HEXAGON_R23:
39825ffd83dbSDimitry Andric return "r23";
39835ffd83dbSDimitry Andric case UNW_HEXAGON_R24:
39845ffd83dbSDimitry Andric return "r24";
39855ffd83dbSDimitry Andric case UNW_HEXAGON_R25:
39865ffd83dbSDimitry Andric return "r25";
39875ffd83dbSDimitry Andric case UNW_HEXAGON_R26:
39885ffd83dbSDimitry Andric return "r26";
39895ffd83dbSDimitry Andric case UNW_HEXAGON_R27:
39905ffd83dbSDimitry Andric return "r27";
39915ffd83dbSDimitry Andric case UNW_HEXAGON_R28:
39925ffd83dbSDimitry Andric return "r28";
39935ffd83dbSDimitry Andric case UNW_HEXAGON_R29:
39945ffd83dbSDimitry Andric return "r29";
39955ffd83dbSDimitry Andric case UNW_HEXAGON_R30:
39965ffd83dbSDimitry Andric return "r30";
39975ffd83dbSDimitry Andric case UNW_HEXAGON_R31:
39985ffd83dbSDimitry Andric return "r31";
39995ffd83dbSDimitry Andric default:
40005ffd83dbSDimitry Andric return "unknown register";
40015ffd83dbSDimitry Andric }
40025ffd83dbSDimitry Andric
40035ffd83dbSDimitry Andric }
40045ffd83dbSDimitry Andric #endif // _LIBUNWIND_TARGET_HEXAGON
40055ffd83dbSDimitry Andric
40065ffd83dbSDimitry Andric
4007480093f4SDimitry Andric #if defined(_LIBUNWIND_TARGET_RISCV)
4008fe6060f1SDimitry Andric /// Registers_riscv holds the register state of a thread in a RISC-V
4009480093f4SDimitry Andric /// process.
4010fe6060f1SDimitry Andric
4011fe6060f1SDimitry Andric // This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.
4012fe6060f1SDimitry Andric # ifdef __riscv
4013fe6060f1SDimitry Andric # if __riscv_xlen == 32
4014fe6060f1SDimitry Andric typedef uint32_t reg_t;
4015fe6060f1SDimitry Andric # elif __riscv_xlen == 64
4016fe6060f1SDimitry Andric typedef uint64_t reg_t;
4017fe6060f1SDimitry Andric # else
4018fe6060f1SDimitry Andric # error "Unsupported __riscv_xlen"
4019fe6060f1SDimitry Andric # endif
4020fe6060f1SDimitry Andric
4021fe6060f1SDimitry Andric # if defined(__riscv_flen)
4022fe6060f1SDimitry Andric # if __riscv_flen == 64
4023fe6060f1SDimitry Andric typedef double fp_t;
4024fe6060f1SDimitry Andric # elif __riscv_flen == 32
4025fe6060f1SDimitry Andric typedef float fp_t;
4026fe6060f1SDimitry Andric # else
4027fe6060f1SDimitry Andric # error "Unsupported __riscv_flen"
4028fe6060f1SDimitry Andric # endif
4029fe6060f1SDimitry Andric # else
4030bdd1243dSDimitry Andric // This is just for suppressing undeclared error of fp_t.
4031fe6060f1SDimitry Andric typedef double fp_t;
4032fe6060f1SDimitry Andric # endif
4033fe6060f1SDimitry Andric # else
4034fe6060f1SDimitry Andric // Use Max possible width when cross unwinding
4035fe6060f1SDimitry Andric typedef uint64_t reg_t;
4036fe6060f1SDimitry Andric typedef double fp_t;
4037fe6060f1SDimitry Andric # define __riscv_xlen 64
4038fe6060f1SDimitry Andric # define __riscv_flen 64
4039fe6060f1SDimitry Andric #endif
4040fe6060f1SDimitry Andric
4041fe6060f1SDimitry Andric /// Registers_riscv holds the register state of a thread.
4042480093f4SDimitry Andric class _LIBUNWIND_HIDDEN Registers_riscv {
4043480093f4SDimitry Andric public:
4044480093f4SDimitry Andric Registers_riscv();
4045480093f4SDimitry Andric Registers_riscv(const void *registers);
4046480093f4SDimitry Andric
4047480093f4SDimitry Andric bool validRegister(int num) const;
4048fe6060f1SDimitry Andric reg_t getRegister(int num) const;
4049fe6060f1SDimitry Andric void setRegister(int num, reg_t value);
4050480093f4SDimitry Andric bool validFloatRegister(int num) const;
4051fe6060f1SDimitry Andric fp_t getFloatRegister(int num) const;
4052fe6060f1SDimitry Andric void setFloatRegister(int num, fp_t value);
4053480093f4SDimitry Andric bool validVectorRegister(int num) const;
4054480093f4SDimitry Andric v128 getVectorRegister(int num) const;
4055480093f4SDimitry Andric void setVectorRegister(int num, v128 value);
4056480093f4SDimitry Andric static const char *getRegisterName(int num);
4057480093f4SDimitry Andric void jumpto();
lastDwarfRegNum()405881ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
405981ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV;
406081ad6265SDimitry Andric }
getArch()4061480093f4SDimitry Andric static int getArch() { return REGISTERS_RISCV; }
4062480093f4SDimitry Andric
getSP() const4063fe6060f1SDimitry Andric reg_t getSP() const { return _registers[2]; }
setSP(reg_t value)4064fe6060f1SDimitry Andric void setSP(reg_t value) { _registers[2] = value; }
getIP() const4065fe6060f1SDimitry Andric reg_t getIP() const { return _registers[0]; }
setIP(reg_t value)4066fe6060f1SDimitry Andric void setIP(reg_t value) { _registers[0] = value; }
4067480093f4SDimitry Andric
4068480093f4SDimitry Andric private:
40695ffd83dbSDimitry Andric // _registers[0] holds the pc
4070fe6060f1SDimitry Andric reg_t _registers[32];
4071fe6060f1SDimitry Andric # if defined(__riscv_flen)
4072fe6060f1SDimitry Andric fp_t _floats[32];
4073fe6060f1SDimitry Andric # endif
4074480093f4SDimitry Andric };
4075480093f4SDimitry Andric
Registers_riscv(const void * registers)4076480093f4SDimitry Andric inline Registers_riscv::Registers_riscv(const void *registers) {
4077480093f4SDimitry Andric static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit),
4078480093f4SDimitry Andric "riscv registers do not fit into unw_context_t");
4079480093f4SDimitry Andric memcpy(&_registers, registers, sizeof(_registers));
4080fe6060f1SDimitry Andric # if __riscv_xlen == 32
4081fe6060f1SDimitry Andric static_assert(sizeof(_registers) == 0x80,
4082fe6060f1SDimitry Andric "expected float registers to be at offset 128");
4083fe6060f1SDimitry Andric # elif __riscv_xlen == 64
4084480093f4SDimitry Andric static_assert(sizeof(_registers) == 0x100,
4085480093f4SDimitry Andric "expected float registers to be at offset 256");
4086fe6060f1SDimitry Andric # else
4087fe6060f1SDimitry Andric # error "Unexpected float registers."
4088fe6060f1SDimitry Andric # endif
4089fe6060f1SDimitry Andric
4090fe6060f1SDimitry Andric # if defined(__riscv_flen)
4091480093f4SDimitry Andric memcpy(_floats,
4092480093f4SDimitry Andric static_cast<const uint8_t *>(registers) + sizeof(_registers),
4093480093f4SDimitry Andric sizeof(_floats));
4094fe6060f1SDimitry Andric # endif
4095480093f4SDimitry Andric }
4096480093f4SDimitry Andric
Registers_riscv()4097480093f4SDimitry Andric inline Registers_riscv::Registers_riscv() {
4098480093f4SDimitry Andric memset(&_registers, 0, sizeof(_registers));
4099fe6060f1SDimitry Andric # if defined(__riscv_flen)
4100480093f4SDimitry Andric memset(&_floats, 0, sizeof(_floats));
4101fe6060f1SDimitry Andric # endif
4102480093f4SDimitry Andric }
4103480093f4SDimitry Andric
validRegister(int regNum) const4104480093f4SDimitry Andric inline bool Registers_riscv::validRegister(int regNum) const {
4105480093f4SDimitry Andric if (regNum == UNW_REG_IP)
4106480093f4SDimitry Andric return true;
4107480093f4SDimitry Andric if (regNum == UNW_REG_SP)
4108480093f4SDimitry Andric return true;
4109480093f4SDimitry Andric if (regNum < 0)
4110480093f4SDimitry Andric return false;
4111bdd1243dSDimitry Andric if (regNum == UNW_RISCV_VLENB)
4112bdd1243dSDimitry Andric return true;
4113480093f4SDimitry Andric if (regNum > UNW_RISCV_F31)
4114480093f4SDimitry Andric return false;
4115480093f4SDimitry Andric return true;
4116480093f4SDimitry Andric }
4117480093f4SDimitry Andric
getRegister(int regNum) const4118fe6060f1SDimitry Andric inline reg_t Registers_riscv::getRegister(int regNum) const {
4119480093f4SDimitry Andric if (regNum == UNW_REG_IP)
41205ffd83dbSDimitry Andric return _registers[0];
4121480093f4SDimitry Andric if (regNum == UNW_REG_SP)
4122480093f4SDimitry Andric return _registers[2];
4123480093f4SDimitry Andric if (regNum == UNW_RISCV_X0)
4124480093f4SDimitry Andric return 0;
4125480093f4SDimitry Andric if ((regNum > 0) && (regNum < 32))
4126480093f4SDimitry Andric return _registers[regNum];
4127bdd1243dSDimitry Andric if (regNum == UNW_RISCV_VLENB) {
4128bdd1243dSDimitry Andric reg_t vlenb;
4129bdd1243dSDimitry Andric __asm__("csrr %0, 0xC22" : "=r"(vlenb));
4130bdd1243dSDimitry Andric return vlenb;
4131bdd1243dSDimitry Andric }
4132480093f4SDimitry Andric _LIBUNWIND_ABORT("unsupported riscv register");
4133480093f4SDimitry Andric }
4134480093f4SDimitry Andric
setRegister(int regNum,reg_t value)4135fe6060f1SDimitry Andric inline void Registers_riscv::setRegister(int regNum, reg_t value) {
4136480093f4SDimitry Andric if (regNum == UNW_REG_IP)
41375ffd83dbSDimitry Andric _registers[0] = value;
4138480093f4SDimitry Andric else if (regNum == UNW_REG_SP)
4139480093f4SDimitry Andric _registers[2] = value;
4140480093f4SDimitry Andric else if (regNum == UNW_RISCV_X0)
4141480093f4SDimitry Andric /* x0 is hardwired to zero */
4142480093f4SDimitry Andric return;
4143480093f4SDimitry Andric else if ((regNum > 0) && (regNum < 32))
4144480093f4SDimitry Andric _registers[regNum] = value;
4145480093f4SDimitry Andric else
4146480093f4SDimitry Andric _LIBUNWIND_ABORT("unsupported riscv register");
4147480093f4SDimitry Andric }
4148480093f4SDimitry Andric
getRegisterName(int regNum)4149480093f4SDimitry Andric inline const char *Registers_riscv::getRegisterName(int regNum) {
4150480093f4SDimitry Andric switch (regNum) {
4151480093f4SDimitry Andric case UNW_REG_IP:
4152480093f4SDimitry Andric return "pc";
4153480093f4SDimitry Andric case UNW_REG_SP:
4154480093f4SDimitry Andric return "sp";
4155480093f4SDimitry Andric case UNW_RISCV_X0:
4156480093f4SDimitry Andric return "zero";
4157480093f4SDimitry Andric case UNW_RISCV_X1:
4158480093f4SDimitry Andric return "ra";
4159480093f4SDimitry Andric case UNW_RISCV_X2:
4160480093f4SDimitry Andric return "sp";
4161480093f4SDimitry Andric case UNW_RISCV_X3:
4162480093f4SDimitry Andric return "gp";
4163480093f4SDimitry Andric case UNW_RISCV_X4:
4164480093f4SDimitry Andric return "tp";
4165480093f4SDimitry Andric case UNW_RISCV_X5:
4166480093f4SDimitry Andric return "t0";
4167480093f4SDimitry Andric case UNW_RISCV_X6:
4168480093f4SDimitry Andric return "t1";
4169480093f4SDimitry Andric case UNW_RISCV_X7:
4170480093f4SDimitry Andric return "t2";
4171480093f4SDimitry Andric case UNW_RISCV_X8:
4172480093f4SDimitry Andric return "s0";
4173480093f4SDimitry Andric case UNW_RISCV_X9:
4174480093f4SDimitry Andric return "s1";
4175480093f4SDimitry Andric case UNW_RISCV_X10:
4176480093f4SDimitry Andric return "a0";
4177480093f4SDimitry Andric case UNW_RISCV_X11:
4178480093f4SDimitry Andric return "a1";
4179480093f4SDimitry Andric case UNW_RISCV_X12:
4180480093f4SDimitry Andric return "a2";
4181480093f4SDimitry Andric case UNW_RISCV_X13:
4182480093f4SDimitry Andric return "a3";
4183480093f4SDimitry Andric case UNW_RISCV_X14:
4184480093f4SDimitry Andric return "a4";
4185480093f4SDimitry Andric case UNW_RISCV_X15:
4186480093f4SDimitry Andric return "a5";
4187480093f4SDimitry Andric case UNW_RISCV_X16:
4188480093f4SDimitry Andric return "a6";
4189480093f4SDimitry Andric case UNW_RISCV_X17:
4190480093f4SDimitry Andric return "a7";
4191480093f4SDimitry Andric case UNW_RISCV_X18:
4192480093f4SDimitry Andric return "s2";
4193480093f4SDimitry Andric case UNW_RISCV_X19:
4194480093f4SDimitry Andric return "s3";
4195480093f4SDimitry Andric case UNW_RISCV_X20:
4196480093f4SDimitry Andric return "s4";
4197480093f4SDimitry Andric case UNW_RISCV_X21:
4198480093f4SDimitry Andric return "s5";
4199480093f4SDimitry Andric case UNW_RISCV_X22:
4200480093f4SDimitry Andric return "s6";
4201480093f4SDimitry Andric case UNW_RISCV_X23:
4202480093f4SDimitry Andric return "s7";
4203480093f4SDimitry Andric case UNW_RISCV_X24:
4204480093f4SDimitry Andric return "s8";
4205480093f4SDimitry Andric case UNW_RISCV_X25:
4206480093f4SDimitry Andric return "s9";
4207480093f4SDimitry Andric case UNW_RISCV_X26:
4208480093f4SDimitry Andric return "s10";
4209480093f4SDimitry Andric case UNW_RISCV_X27:
4210480093f4SDimitry Andric return "s11";
4211480093f4SDimitry Andric case UNW_RISCV_X28:
4212480093f4SDimitry Andric return "t3";
4213480093f4SDimitry Andric case UNW_RISCV_X29:
4214480093f4SDimitry Andric return "t4";
4215480093f4SDimitry Andric case UNW_RISCV_X30:
4216480093f4SDimitry Andric return "t5";
4217480093f4SDimitry Andric case UNW_RISCV_X31:
4218480093f4SDimitry Andric return "t6";
4219480093f4SDimitry Andric case UNW_RISCV_F0:
4220480093f4SDimitry Andric return "ft0";
4221480093f4SDimitry Andric case UNW_RISCV_F1:
4222480093f4SDimitry Andric return "ft1";
4223480093f4SDimitry Andric case UNW_RISCV_F2:
4224480093f4SDimitry Andric return "ft2";
4225480093f4SDimitry Andric case UNW_RISCV_F3:
4226480093f4SDimitry Andric return "ft3";
4227480093f4SDimitry Andric case UNW_RISCV_F4:
4228480093f4SDimitry Andric return "ft4";
4229480093f4SDimitry Andric case UNW_RISCV_F5:
4230480093f4SDimitry Andric return "ft5";
4231480093f4SDimitry Andric case UNW_RISCV_F6:
4232480093f4SDimitry Andric return "ft6";
4233480093f4SDimitry Andric case UNW_RISCV_F7:
4234480093f4SDimitry Andric return "ft7";
4235480093f4SDimitry Andric case UNW_RISCV_F8:
4236480093f4SDimitry Andric return "fs0";
4237480093f4SDimitry Andric case UNW_RISCV_F9:
4238480093f4SDimitry Andric return "fs1";
4239480093f4SDimitry Andric case UNW_RISCV_F10:
4240480093f4SDimitry Andric return "fa0";
4241480093f4SDimitry Andric case UNW_RISCV_F11:
4242480093f4SDimitry Andric return "fa1";
4243480093f4SDimitry Andric case UNW_RISCV_F12:
4244480093f4SDimitry Andric return "fa2";
4245480093f4SDimitry Andric case UNW_RISCV_F13:
4246480093f4SDimitry Andric return "fa3";
4247480093f4SDimitry Andric case UNW_RISCV_F14:
4248480093f4SDimitry Andric return "fa4";
4249480093f4SDimitry Andric case UNW_RISCV_F15:
4250480093f4SDimitry Andric return "fa5";
4251480093f4SDimitry Andric case UNW_RISCV_F16:
4252480093f4SDimitry Andric return "fa6";
4253480093f4SDimitry Andric case UNW_RISCV_F17:
4254480093f4SDimitry Andric return "fa7";
4255480093f4SDimitry Andric case UNW_RISCV_F18:
4256480093f4SDimitry Andric return "fs2";
4257480093f4SDimitry Andric case UNW_RISCV_F19:
4258480093f4SDimitry Andric return "fs3";
4259480093f4SDimitry Andric case UNW_RISCV_F20:
4260480093f4SDimitry Andric return "fs4";
4261480093f4SDimitry Andric case UNW_RISCV_F21:
4262480093f4SDimitry Andric return "fs5";
4263480093f4SDimitry Andric case UNW_RISCV_F22:
4264480093f4SDimitry Andric return "fs6";
4265480093f4SDimitry Andric case UNW_RISCV_F23:
4266480093f4SDimitry Andric return "fs7";
4267480093f4SDimitry Andric case UNW_RISCV_F24:
4268480093f4SDimitry Andric return "fs8";
4269480093f4SDimitry Andric case UNW_RISCV_F25:
4270480093f4SDimitry Andric return "fs9";
4271480093f4SDimitry Andric case UNW_RISCV_F26:
4272480093f4SDimitry Andric return "fs10";
4273480093f4SDimitry Andric case UNW_RISCV_F27:
4274480093f4SDimitry Andric return "fs11";
4275480093f4SDimitry Andric case UNW_RISCV_F28:
4276480093f4SDimitry Andric return "ft8";
4277480093f4SDimitry Andric case UNW_RISCV_F29:
4278480093f4SDimitry Andric return "ft9";
4279480093f4SDimitry Andric case UNW_RISCV_F30:
4280480093f4SDimitry Andric return "ft10";
4281480093f4SDimitry Andric case UNW_RISCV_F31:
4282480093f4SDimitry Andric return "ft11";
4283bdd1243dSDimitry Andric case UNW_RISCV_VLENB:
4284bdd1243dSDimitry Andric return "vlenb";
4285480093f4SDimitry Andric default:
4286480093f4SDimitry Andric return "unknown register";
4287480093f4SDimitry Andric }
4288480093f4SDimitry Andric }
4289480093f4SDimitry Andric
validFloatRegister(int regNum) const4290480093f4SDimitry Andric inline bool Registers_riscv::validFloatRegister(int regNum) const {
4291fe6060f1SDimitry Andric # if defined(__riscv_flen)
4292480093f4SDimitry Andric if (regNum < UNW_RISCV_F0)
4293480093f4SDimitry Andric return false;
4294480093f4SDimitry Andric if (regNum > UNW_RISCV_F31)
4295480093f4SDimitry Andric return false;
4296480093f4SDimitry Andric return true;
4297fe6060f1SDimitry Andric # else
4298fe6060f1SDimitry Andric (void)regNum;
4299fe6060f1SDimitry Andric return false;
4300fe6060f1SDimitry Andric # endif
4301480093f4SDimitry Andric }
4302480093f4SDimitry Andric
getFloatRegister(int regNum) const4303fe6060f1SDimitry Andric inline fp_t Registers_riscv::getFloatRegister(int regNum) const {
4304fe6060f1SDimitry Andric # if defined(__riscv_flen)
4305480093f4SDimitry Andric assert(validFloatRegister(regNum));
4306480093f4SDimitry Andric return _floats[regNum - UNW_RISCV_F0];
4307480093f4SDimitry Andric # else
43085ffd83dbSDimitry Andric (void)regNum;
4309480093f4SDimitry Andric _LIBUNWIND_ABORT("libunwind not built with float support");
4310480093f4SDimitry Andric # endif
4311480093f4SDimitry Andric }
4312480093f4SDimitry Andric
setFloatRegister(int regNum,fp_t value)4313fe6060f1SDimitry Andric inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) {
4314fe6060f1SDimitry Andric # if defined(__riscv_flen)
4315480093f4SDimitry Andric assert(validFloatRegister(regNum));
4316480093f4SDimitry Andric _floats[regNum - UNW_RISCV_F0] = value;
4317480093f4SDimitry Andric # else
43185ffd83dbSDimitry Andric (void)regNum;
43195ffd83dbSDimitry Andric (void)value;
4320480093f4SDimitry Andric _LIBUNWIND_ABORT("libunwind not built with float support");
4321480093f4SDimitry Andric # endif
4322480093f4SDimitry Andric }
4323480093f4SDimitry Andric
validVectorRegister(int) const4324480093f4SDimitry Andric inline bool Registers_riscv::validVectorRegister(int) const {
4325480093f4SDimitry Andric return false;
4326480093f4SDimitry Andric }
4327480093f4SDimitry Andric
getVectorRegister(int) const4328480093f4SDimitry Andric inline v128 Registers_riscv::getVectorRegister(int) const {
4329480093f4SDimitry Andric _LIBUNWIND_ABORT("no riscv vector register support yet");
4330480093f4SDimitry Andric }
4331480093f4SDimitry Andric
setVectorRegister(int,v128)4332480093f4SDimitry Andric inline void Registers_riscv::setVectorRegister(int, v128) {
4333480093f4SDimitry Andric _LIBUNWIND_ABORT("no riscv vector register support yet");
4334480093f4SDimitry Andric }
4335480093f4SDimitry Andric #endif // _LIBUNWIND_TARGET_RISCV
4336e8d8bef9SDimitry Andric
4337e8d8bef9SDimitry Andric #if defined(_LIBUNWIND_TARGET_VE)
4338e8d8bef9SDimitry Andric /// Registers_ve holds the register state of a thread in a VE process.
4339e8d8bef9SDimitry Andric class _LIBUNWIND_HIDDEN Registers_ve {
4340e8d8bef9SDimitry Andric public:
4341e8d8bef9SDimitry Andric Registers_ve();
4342e8d8bef9SDimitry Andric Registers_ve(const void *registers);
4343e8d8bef9SDimitry Andric
4344e8d8bef9SDimitry Andric bool validRegister(int num) const;
4345e8d8bef9SDimitry Andric uint64_t getRegister(int num) const;
4346e8d8bef9SDimitry Andric void setRegister(int num, uint64_t value);
4347e8d8bef9SDimitry Andric bool validFloatRegister(int num) const;
4348e8d8bef9SDimitry Andric double getFloatRegister(int num) const;
4349e8d8bef9SDimitry Andric void setFloatRegister(int num, double value);
4350e8d8bef9SDimitry Andric bool validVectorRegister(int num) const;
4351e8d8bef9SDimitry Andric v128 getVectorRegister(int num) const;
4352e8d8bef9SDimitry Andric void setVectorRegister(int num, v128 value);
4353e8d8bef9SDimitry Andric static const char *getRegisterName(int num);
4354e8d8bef9SDimitry Andric void jumpto();
lastDwarfRegNum()435581ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
435681ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE;
435781ad6265SDimitry Andric }
getArch()4358e8d8bef9SDimitry Andric static int getArch() { return REGISTERS_VE; }
4359e8d8bef9SDimitry Andric
getSP() const4360e8d8bef9SDimitry Andric uint64_t getSP() const { return _registers.__s[11]; }
setSP(uint64_t value)4361e8d8bef9SDimitry Andric void setSP(uint64_t value) { _registers.__s[11] = value; }
getIP() const4362e8d8bef9SDimitry Andric uint64_t getIP() const { return _registers.__ic; }
setIP(uint64_t value)4363e8d8bef9SDimitry Andric void setIP(uint64_t value) { _registers.__ic = value; }
4364e8d8bef9SDimitry Andric
4365e8d8bef9SDimitry Andric private:
4366e8d8bef9SDimitry Andric // FIXME: Need to store not only scalar registers but also vector and vector
4367e8d8bef9SDimitry Andric // mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes
4368e8d8bef9SDimitry Andric // 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for
4369e8d8bef9SDimitry Andric // SjLj exception support only, so Registers_ve is not implemented completely.
4370e8d8bef9SDimitry Andric struct ve_thread_state_t {
4371e8d8bef9SDimitry Andric uint64_t __s[64]; // s0-s64
4372e8d8bef9SDimitry Andric uint64_t __ic; // Instruction counter (IC)
4373e8d8bef9SDimitry Andric uint64_t __vixr; // Vector Index Register
4374e8d8bef9SDimitry Andric uint64_t __vl; // Vector Length Register
4375e8d8bef9SDimitry Andric };
4376e8d8bef9SDimitry Andric
4377e8d8bef9SDimitry Andric ve_thread_state_t _registers; // total 67 registers
4378e8d8bef9SDimitry Andric
4379e8d8bef9SDimitry Andric // Currently no vector register is preserved.
4380e8d8bef9SDimitry Andric };
4381e8d8bef9SDimitry Andric
Registers_ve(const void * registers)4382e8d8bef9SDimitry Andric inline Registers_ve::Registers_ve(const void *registers) {
4383e8d8bef9SDimitry Andric static_assert((check_fit<Registers_ve, unw_context_t>::does_fit),
4384e8d8bef9SDimitry Andric "ve registers do not fit into unw_context_t");
4385e8d8bef9SDimitry Andric memcpy(&_registers, static_cast<const uint8_t *>(registers),
4386e8d8bef9SDimitry Andric sizeof(_registers));
4387e8d8bef9SDimitry Andric static_assert(sizeof(_registers) == 536,
4388e8d8bef9SDimitry Andric "expected vector register offset to be 536");
4389e8d8bef9SDimitry Andric }
4390e8d8bef9SDimitry Andric
Registers_ve()4391e8d8bef9SDimitry Andric inline Registers_ve::Registers_ve() {
4392e8d8bef9SDimitry Andric memset(&_registers, 0, sizeof(_registers));
4393e8d8bef9SDimitry Andric }
4394e8d8bef9SDimitry Andric
validRegister(int regNum) const4395e8d8bef9SDimitry Andric inline bool Registers_ve::validRegister(int regNum) const {
4396e8d8bef9SDimitry Andric if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
4397e8d8bef9SDimitry Andric return true;
4398e8d8bef9SDimitry Andric
4399e8d8bef9SDimitry Andric switch (regNum) {
4400e8d8bef9SDimitry Andric case UNW_REG_IP:
4401e8d8bef9SDimitry Andric case UNW_REG_SP:
4402e8d8bef9SDimitry Andric case UNW_VE_VIXR:
4403e8d8bef9SDimitry Andric case UNW_VE_VL:
4404e8d8bef9SDimitry Andric return true;
4405e8d8bef9SDimitry Andric default:
4406e8d8bef9SDimitry Andric return false;
4407e8d8bef9SDimitry Andric }
4408e8d8bef9SDimitry Andric }
4409e8d8bef9SDimitry Andric
getRegister(int regNum) const4410e8d8bef9SDimitry Andric inline uint64_t Registers_ve::getRegister(int regNum) const {
4411e8d8bef9SDimitry Andric if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
4412e8d8bef9SDimitry Andric return _registers.__s[regNum - UNW_VE_S0];
4413e8d8bef9SDimitry Andric
4414e8d8bef9SDimitry Andric switch (regNum) {
4415e8d8bef9SDimitry Andric case UNW_REG_IP:
4416e8d8bef9SDimitry Andric return _registers.__ic;
4417e8d8bef9SDimitry Andric case UNW_REG_SP:
4418e8d8bef9SDimitry Andric return _registers.__s[11];
4419e8d8bef9SDimitry Andric case UNW_VE_VIXR:
4420e8d8bef9SDimitry Andric return _registers.__vixr;
4421e8d8bef9SDimitry Andric case UNW_VE_VL:
4422e8d8bef9SDimitry Andric return _registers.__vl;
4423e8d8bef9SDimitry Andric }
4424e8d8bef9SDimitry Andric _LIBUNWIND_ABORT("unsupported ve register");
4425e8d8bef9SDimitry Andric }
4426e8d8bef9SDimitry Andric
setRegister(int regNum,uint64_t value)4427e8d8bef9SDimitry Andric inline void Registers_ve::setRegister(int regNum, uint64_t value) {
4428e8d8bef9SDimitry Andric if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) {
4429e8d8bef9SDimitry Andric _registers.__s[regNum - UNW_VE_S0] = value;
4430e8d8bef9SDimitry Andric return;
4431e8d8bef9SDimitry Andric }
4432e8d8bef9SDimitry Andric
4433e8d8bef9SDimitry Andric switch (regNum) {
4434e8d8bef9SDimitry Andric case UNW_REG_IP:
4435e8d8bef9SDimitry Andric _registers.__ic = value;
4436e8d8bef9SDimitry Andric return;
4437e8d8bef9SDimitry Andric case UNW_REG_SP:
4438e8d8bef9SDimitry Andric _registers.__s[11] = value;
4439e8d8bef9SDimitry Andric return;
4440e8d8bef9SDimitry Andric case UNW_VE_VIXR:
4441e8d8bef9SDimitry Andric _registers.__vixr = value;
4442e8d8bef9SDimitry Andric return;
4443e8d8bef9SDimitry Andric case UNW_VE_VL:
4444e8d8bef9SDimitry Andric _registers.__vl = value;
4445e8d8bef9SDimitry Andric return;
4446e8d8bef9SDimitry Andric }
4447e8d8bef9SDimitry Andric _LIBUNWIND_ABORT("unsupported ve register");
4448e8d8bef9SDimitry Andric }
4449e8d8bef9SDimitry Andric
validFloatRegister(int) const4450e8d8bef9SDimitry Andric inline bool Registers_ve::validFloatRegister(int /* regNum */) const {
4451e8d8bef9SDimitry Andric return false;
4452e8d8bef9SDimitry Andric }
4453e8d8bef9SDimitry Andric
getFloatRegister(int) const4454e8d8bef9SDimitry Andric inline double Registers_ve::getFloatRegister(int /* regNum */) const {
4455e8d8bef9SDimitry Andric _LIBUNWIND_ABORT("VE doesn't have float registers");
4456e8d8bef9SDimitry Andric }
4457e8d8bef9SDimitry Andric
setFloatRegister(int,double)4458e8d8bef9SDimitry Andric inline void Registers_ve::setFloatRegister(int /* regNum */,
4459e8d8bef9SDimitry Andric double /* value */) {
4460e8d8bef9SDimitry Andric _LIBUNWIND_ABORT("VE doesn't have float registers");
4461e8d8bef9SDimitry Andric }
4462e8d8bef9SDimitry Andric
validVectorRegister(int) const4463e8d8bef9SDimitry Andric inline bool Registers_ve::validVectorRegister(int /* regNum */) const {
4464e8d8bef9SDimitry Andric return false;
4465e8d8bef9SDimitry Andric }
4466e8d8bef9SDimitry Andric
getVectorRegister(int) const4467e8d8bef9SDimitry Andric inline v128 Registers_ve::getVectorRegister(int /* regNum */) const {
4468e8d8bef9SDimitry Andric _LIBUNWIND_ABORT("VE vector support not implemented");
4469e8d8bef9SDimitry Andric }
4470e8d8bef9SDimitry Andric
setVectorRegister(int,v128)4471e8d8bef9SDimitry Andric inline void Registers_ve::setVectorRegister(int /* regNum */,
4472e8d8bef9SDimitry Andric v128 /* value */) {
4473e8d8bef9SDimitry Andric _LIBUNWIND_ABORT("VE vector support not implemented");
4474e8d8bef9SDimitry Andric }
4475e8d8bef9SDimitry Andric
getRegisterName(int regNum)4476e8d8bef9SDimitry Andric inline const char *Registers_ve::getRegisterName(int regNum) {
4477e8d8bef9SDimitry Andric switch (regNum) {
4478e8d8bef9SDimitry Andric case UNW_REG_IP:
4479e8d8bef9SDimitry Andric return "ip";
4480e8d8bef9SDimitry Andric case UNW_REG_SP:
4481e8d8bef9SDimitry Andric return "sp";
4482e8d8bef9SDimitry Andric case UNW_VE_VIXR:
4483e8d8bef9SDimitry Andric return "vixr";
4484e8d8bef9SDimitry Andric case UNW_VE_VL:
4485e8d8bef9SDimitry Andric return "vl";
4486e8d8bef9SDimitry Andric case UNW_VE_S0:
4487e8d8bef9SDimitry Andric return "s0";
4488e8d8bef9SDimitry Andric case UNW_VE_S1:
4489e8d8bef9SDimitry Andric return "s1";
4490e8d8bef9SDimitry Andric case UNW_VE_S2:
4491e8d8bef9SDimitry Andric return "s2";
4492e8d8bef9SDimitry Andric case UNW_VE_S3:
4493e8d8bef9SDimitry Andric return "s3";
4494e8d8bef9SDimitry Andric case UNW_VE_S4:
4495e8d8bef9SDimitry Andric return "s4";
4496e8d8bef9SDimitry Andric case UNW_VE_S5:
4497e8d8bef9SDimitry Andric return "s5";
4498e8d8bef9SDimitry Andric case UNW_VE_S6:
4499e8d8bef9SDimitry Andric return "s6";
4500e8d8bef9SDimitry Andric case UNW_VE_S7:
4501e8d8bef9SDimitry Andric return "s7";
4502e8d8bef9SDimitry Andric case UNW_VE_S8:
4503e8d8bef9SDimitry Andric return "s8";
4504e8d8bef9SDimitry Andric case UNW_VE_S9:
4505e8d8bef9SDimitry Andric return "s9";
4506e8d8bef9SDimitry Andric case UNW_VE_S10:
4507e8d8bef9SDimitry Andric return "s10";
4508e8d8bef9SDimitry Andric case UNW_VE_S11:
4509e8d8bef9SDimitry Andric return "s11";
4510e8d8bef9SDimitry Andric case UNW_VE_S12:
4511e8d8bef9SDimitry Andric return "s12";
4512e8d8bef9SDimitry Andric case UNW_VE_S13:
4513e8d8bef9SDimitry Andric return "s13";
4514e8d8bef9SDimitry Andric case UNW_VE_S14:
4515e8d8bef9SDimitry Andric return "s14";
4516e8d8bef9SDimitry Andric case UNW_VE_S15:
4517e8d8bef9SDimitry Andric return "s15";
4518e8d8bef9SDimitry Andric case UNW_VE_S16:
4519e8d8bef9SDimitry Andric return "s16";
4520e8d8bef9SDimitry Andric case UNW_VE_S17:
4521e8d8bef9SDimitry Andric return "s17";
4522e8d8bef9SDimitry Andric case UNW_VE_S18:
4523e8d8bef9SDimitry Andric return "s18";
4524e8d8bef9SDimitry Andric case UNW_VE_S19:
4525e8d8bef9SDimitry Andric return "s19";
4526e8d8bef9SDimitry Andric case UNW_VE_S20:
4527e8d8bef9SDimitry Andric return "s20";
4528e8d8bef9SDimitry Andric case UNW_VE_S21:
4529e8d8bef9SDimitry Andric return "s21";
4530e8d8bef9SDimitry Andric case UNW_VE_S22:
4531e8d8bef9SDimitry Andric return "s22";
4532e8d8bef9SDimitry Andric case UNW_VE_S23:
4533e8d8bef9SDimitry Andric return "s23";
4534e8d8bef9SDimitry Andric case UNW_VE_S24:
4535e8d8bef9SDimitry Andric return "s24";
4536e8d8bef9SDimitry Andric case UNW_VE_S25:
4537e8d8bef9SDimitry Andric return "s25";
4538e8d8bef9SDimitry Andric case UNW_VE_S26:
4539e8d8bef9SDimitry Andric return "s26";
4540e8d8bef9SDimitry Andric case UNW_VE_S27:
4541e8d8bef9SDimitry Andric return "s27";
4542e8d8bef9SDimitry Andric case UNW_VE_S28:
4543e8d8bef9SDimitry Andric return "s28";
4544e8d8bef9SDimitry Andric case UNW_VE_S29:
4545e8d8bef9SDimitry Andric return "s29";
4546e8d8bef9SDimitry Andric case UNW_VE_S30:
4547e8d8bef9SDimitry Andric return "s30";
4548e8d8bef9SDimitry Andric case UNW_VE_S31:
4549e8d8bef9SDimitry Andric return "s31";
4550e8d8bef9SDimitry Andric case UNW_VE_S32:
4551e8d8bef9SDimitry Andric return "s32";
4552e8d8bef9SDimitry Andric case UNW_VE_S33:
4553e8d8bef9SDimitry Andric return "s33";
4554e8d8bef9SDimitry Andric case UNW_VE_S34:
4555e8d8bef9SDimitry Andric return "s34";
4556e8d8bef9SDimitry Andric case UNW_VE_S35:
4557e8d8bef9SDimitry Andric return "s35";
4558e8d8bef9SDimitry Andric case UNW_VE_S36:
4559e8d8bef9SDimitry Andric return "s36";
4560e8d8bef9SDimitry Andric case UNW_VE_S37:
4561e8d8bef9SDimitry Andric return "s37";
4562e8d8bef9SDimitry Andric case UNW_VE_S38:
4563e8d8bef9SDimitry Andric return "s38";
4564e8d8bef9SDimitry Andric case UNW_VE_S39:
4565e8d8bef9SDimitry Andric return "s39";
4566e8d8bef9SDimitry Andric case UNW_VE_S40:
4567e8d8bef9SDimitry Andric return "s40";
4568e8d8bef9SDimitry Andric case UNW_VE_S41:
4569e8d8bef9SDimitry Andric return "s41";
4570e8d8bef9SDimitry Andric case UNW_VE_S42:
4571e8d8bef9SDimitry Andric return "s42";
4572e8d8bef9SDimitry Andric case UNW_VE_S43:
4573e8d8bef9SDimitry Andric return "s43";
4574e8d8bef9SDimitry Andric case UNW_VE_S44:
4575e8d8bef9SDimitry Andric return "s44";
4576e8d8bef9SDimitry Andric case UNW_VE_S45:
4577e8d8bef9SDimitry Andric return "s45";
4578e8d8bef9SDimitry Andric case UNW_VE_S46:
4579e8d8bef9SDimitry Andric return "s46";
4580e8d8bef9SDimitry Andric case UNW_VE_S47:
4581e8d8bef9SDimitry Andric return "s47";
4582e8d8bef9SDimitry Andric case UNW_VE_S48:
4583e8d8bef9SDimitry Andric return "s48";
4584e8d8bef9SDimitry Andric case UNW_VE_S49:
4585e8d8bef9SDimitry Andric return "s49";
4586e8d8bef9SDimitry Andric case UNW_VE_S50:
4587e8d8bef9SDimitry Andric return "s50";
4588e8d8bef9SDimitry Andric case UNW_VE_S51:
4589e8d8bef9SDimitry Andric return "s51";
4590e8d8bef9SDimitry Andric case UNW_VE_S52:
4591e8d8bef9SDimitry Andric return "s52";
4592e8d8bef9SDimitry Andric case UNW_VE_S53:
4593e8d8bef9SDimitry Andric return "s53";
4594e8d8bef9SDimitry Andric case UNW_VE_S54:
4595e8d8bef9SDimitry Andric return "s54";
4596e8d8bef9SDimitry Andric case UNW_VE_S55:
4597e8d8bef9SDimitry Andric return "s55";
4598e8d8bef9SDimitry Andric case UNW_VE_S56:
4599e8d8bef9SDimitry Andric return "s56";
4600e8d8bef9SDimitry Andric case UNW_VE_S57:
4601e8d8bef9SDimitry Andric return "s57";
4602e8d8bef9SDimitry Andric case UNW_VE_S58:
4603e8d8bef9SDimitry Andric return "s58";
4604e8d8bef9SDimitry Andric case UNW_VE_S59:
4605e8d8bef9SDimitry Andric return "s59";
4606e8d8bef9SDimitry Andric case UNW_VE_S60:
4607e8d8bef9SDimitry Andric return "s60";
4608e8d8bef9SDimitry Andric case UNW_VE_S61:
4609e8d8bef9SDimitry Andric return "s61";
4610e8d8bef9SDimitry Andric case UNW_VE_S62:
4611e8d8bef9SDimitry Andric return "s62";
4612e8d8bef9SDimitry Andric case UNW_VE_S63:
4613e8d8bef9SDimitry Andric return "s63";
4614e8d8bef9SDimitry Andric case UNW_VE_V0:
4615e8d8bef9SDimitry Andric return "v0";
4616e8d8bef9SDimitry Andric case UNW_VE_V1:
4617e8d8bef9SDimitry Andric return "v1";
4618e8d8bef9SDimitry Andric case UNW_VE_V2:
4619e8d8bef9SDimitry Andric return "v2";
4620e8d8bef9SDimitry Andric case UNW_VE_V3:
4621e8d8bef9SDimitry Andric return "v3";
4622e8d8bef9SDimitry Andric case UNW_VE_V4:
4623e8d8bef9SDimitry Andric return "v4";
4624e8d8bef9SDimitry Andric case UNW_VE_V5:
4625e8d8bef9SDimitry Andric return "v5";
4626e8d8bef9SDimitry Andric case UNW_VE_V6:
4627e8d8bef9SDimitry Andric return "v6";
4628e8d8bef9SDimitry Andric case UNW_VE_V7:
4629e8d8bef9SDimitry Andric return "v7";
4630e8d8bef9SDimitry Andric case UNW_VE_V8:
4631e8d8bef9SDimitry Andric return "v8";
4632e8d8bef9SDimitry Andric case UNW_VE_V9:
4633e8d8bef9SDimitry Andric return "v9";
4634e8d8bef9SDimitry Andric case UNW_VE_V10:
4635e8d8bef9SDimitry Andric return "v10";
4636e8d8bef9SDimitry Andric case UNW_VE_V11:
4637e8d8bef9SDimitry Andric return "v11";
4638e8d8bef9SDimitry Andric case UNW_VE_V12:
4639e8d8bef9SDimitry Andric return "v12";
4640e8d8bef9SDimitry Andric case UNW_VE_V13:
4641e8d8bef9SDimitry Andric return "v13";
4642e8d8bef9SDimitry Andric case UNW_VE_V14:
4643e8d8bef9SDimitry Andric return "v14";
4644e8d8bef9SDimitry Andric case UNW_VE_V15:
4645e8d8bef9SDimitry Andric return "v15";
4646e8d8bef9SDimitry Andric case UNW_VE_V16:
4647e8d8bef9SDimitry Andric return "v16";
4648e8d8bef9SDimitry Andric case UNW_VE_V17:
4649e8d8bef9SDimitry Andric return "v17";
4650e8d8bef9SDimitry Andric case UNW_VE_V18:
4651e8d8bef9SDimitry Andric return "v18";
4652e8d8bef9SDimitry Andric case UNW_VE_V19:
4653e8d8bef9SDimitry Andric return "v19";
4654e8d8bef9SDimitry Andric case UNW_VE_V20:
4655e8d8bef9SDimitry Andric return "v20";
4656e8d8bef9SDimitry Andric case UNW_VE_V21:
4657e8d8bef9SDimitry Andric return "v21";
4658e8d8bef9SDimitry Andric case UNW_VE_V22:
4659e8d8bef9SDimitry Andric return "v22";
4660e8d8bef9SDimitry Andric case UNW_VE_V23:
4661e8d8bef9SDimitry Andric return "v23";
4662e8d8bef9SDimitry Andric case UNW_VE_V24:
4663e8d8bef9SDimitry Andric return "v24";
4664e8d8bef9SDimitry Andric case UNW_VE_V25:
4665e8d8bef9SDimitry Andric return "v25";
4666e8d8bef9SDimitry Andric case UNW_VE_V26:
4667e8d8bef9SDimitry Andric return "v26";
4668e8d8bef9SDimitry Andric case UNW_VE_V27:
4669e8d8bef9SDimitry Andric return "v27";
4670e8d8bef9SDimitry Andric case UNW_VE_V28:
4671e8d8bef9SDimitry Andric return "v28";
4672e8d8bef9SDimitry Andric case UNW_VE_V29:
4673e8d8bef9SDimitry Andric return "v29";
4674e8d8bef9SDimitry Andric case UNW_VE_V30:
4675e8d8bef9SDimitry Andric return "v30";
4676e8d8bef9SDimitry Andric case UNW_VE_V31:
4677e8d8bef9SDimitry Andric return "v31";
4678e8d8bef9SDimitry Andric case UNW_VE_V32:
4679e8d8bef9SDimitry Andric return "v32";
4680e8d8bef9SDimitry Andric case UNW_VE_V33:
4681e8d8bef9SDimitry Andric return "v33";
4682e8d8bef9SDimitry Andric case UNW_VE_V34:
4683e8d8bef9SDimitry Andric return "v34";
4684e8d8bef9SDimitry Andric case UNW_VE_V35:
4685e8d8bef9SDimitry Andric return "v35";
4686e8d8bef9SDimitry Andric case UNW_VE_V36:
4687e8d8bef9SDimitry Andric return "v36";
4688e8d8bef9SDimitry Andric case UNW_VE_V37:
4689e8d8bef9SDimitry Andric return "v37";
4690e8d8bef9SDimitry Andric case UNW_VE_V38:
4691e8d8bef9SDimitry Andric return "v38";
4692e8d8bef9SDimitry Andric case UNW_VE_V39:
4693e8d8bef9SDimitry Andric return "v39";
4694e8d8bef9SDimitry Andric case UNW_VE_V40:
4695e8d8bef9SDimitry Andric return "v40";
4696e8d8bef9SDimitry Andric case UNW_VE_V41:
4697e8d8bef9SDimitry Andric return "v41";
4698e8d8bef9SDimitry Andric case UNW_VE_V42:
4699e8d8bef9SDimitry Andric return "v42";
4700e8d8bef9SDimitry Andric case UNW_VE_V43:
4701e8d8bef9SDimitry Andric return "v43";
4702e8d8bef9SDimitry Andric case UNW_VE_V44:
4703e8d8bef9SDimitry Andric return "v44";
4704e8d8bef9SDimitry Andric case UNW_VE_V45:
4705e8d8bef9SDimitry Andric return "v45";
4706e8d8bef9SDimitry Andric case UNW_VE_V46:
4707e8d8bef9SDimitry Andric return "v46";
4708e8d8bef9SDimitry Andric case UNW_VE_V47:
4709e8d8bef9SDimitry Andric return "v47";
4710e8d8bef9SDimitry Andric case UNW_VE_V48:
4711e8d8bef9SDimitry Andric return "v48";
4712e8d8bef9SDimitry Andric case UNW_VE_V49:
4713e8d8bef9SDimitry Andric return "v49";
4714e8d8bef9SDimitry Andric case UNW_VE_V50:
4715e8d8bef9SDimitry Andric return "v50";
4716e8d8bef9SDimitry Andric case UNW_VE_V51:
4717e8d8bef9SDimitry Andric return "v51";
4718e8d8bef9SDimitry Andric case UNW_VE_V52:
4719e8d8bef9SDimitry Andric return "v52";
4720e8d8bef9SDimitry Andric case UNW_VE_V53:
4721e8d8bef9SDimitry Andric return "v53";
4722e8d8bef9SDimitry Andric case UNW_VE_V54:
4723e8d8bef9SDimitry Andric return "v54";
4724e8d8bef9SDimitry Andric case UNW_VE_V55:
4725e8d8bef9SDimitry Andric return "v55";
4726e8d8bef9SDimitry Andric case UNW_VE_V56:
4727e8d8bef9SDimitry Andric return "v56";
4728e8d8bef9SDimitry Andric case UNW_VE_V57:
4729e8d8bef9SDimitry Andric return "v57";
4730e8d8bef9SDimitry Andric case UNW_VE_V58:
4731e8d8bef9SDimitry Andric return "v58";
4732e8d8bef9SDimitry Andric case UNW_VE_V59:
4733e8d8bef9SDimitry Andric return "v59";
4734e8d8bef9SDimitry Andric case UNW_VE_V60:
4735e8d8bef9SDimitry Andric return "v60";
4736e8d8bef9SDimitry Andric case UNW_VE_V61:
4737e8d8bef9SDimitry Andric return "v61";
4738e8d8bef9SDimitry Andric case UNW_VE_V62:
4739e8d8bef9SDimitry Andric return "v62";
4740e8d8bef9SDimitry Andric case UNW_VE_V63:
4741e8d8bef9SDimitry Andric return "v63";
4742e8d8bef9SDimitry Andric case UNW_VE_VM0:
4743e8d8bef9SDimitry Andric return "vm0";
4744e8d8bef9SDimitry Andric case UNW_VE_VM1:
4745e8d8bef9SDimitry Andric return "vm1";
4746e8d8bef9SDimitry Andric case UNW_VE_VM2:
4747e8d8bef9SDimitry Andric return "vm2";
4748e8d8bef9SDimitry Andric case UNW_VE_VM3:
4749e8d8bef9SDimitry Andric return "vm3";
4750e8d8bef9SDimitry Andric case UNW_VE_VM4:
4751e8d8bef9SDimitry Andric return "vm4";
4752e8d8bef9SDimitry Andric case UNW_VE_VM5:
4753e8d8bef9SDimitry Andric return "vm5";
4754e8d8bef9SDimitry Andric case UNW_VE_VM6:
4755e8d8bef9SDimitry Andric return "vm6";
4756e8d8bef9SDimitry Andric case UNW_VE_VM7:
4757e8d8bef9SDimitry Andric return "vm7";
4758e8d8bef9SDimitry Andric case UNW_VE_VM8:
4759e8d8bef9SDimitry Andric return "vm8";
4760e8d8bef9SDimitry Andric case UNW_VE_VM9:
4761e8d8bef9SDimitry Andric return "vm9";
4762e8d8bef9SDimitry Andric case UNW_VE_VM10:
4763e8d8bef9SDimitry Andric return "vm10";
4764e8d8bef9SDimitry Andric case UNW_VE_VM11:
4765e8d8bef9SDimitry Andric return "vm11";
4766e8d8bef9SDimitry Andric case UNW_VE_VM12:
4767e8d8bef9SDimitry Andric return "vm12";
4768e8d8bef9SDimitry Andric case UNW_VE_VM13:
4769e8d8bef9SDimitry Andric return "vm13";
4770e8d8bef9SDimitry Andric case UNW_VE_VM14:
4771e8d8bef9SDimitry Andric return "vm14";
4772e8d8bef9SDimitry Andric case UNW_VE_VM15:
4773e8d8bef9SDimitry Andric return "vm15";
4774e8d8bef9SDimitry Andric }
4775e8d8bef9SDimitry Andric return "unknown register";
4776e8d8bef9SDimitry Andric }
4777e8d8bef9SDimitry Andric #endif // _LIBUNWIND_TARGET_VE
4778e8d8bef9SDimitry Andric
477981ad6265SDimitry Andric #if defined(_LIBUNWIND_TARGET_S390X)
478081ad6265SDimitry Andric /// Registers_s390x holds the register state of a thread in a
478181ad6265SDimitry Andric /// 64-bit Linux on IBM zSystems process.
478281ad6265SDimitry Andric class _LIBUNWIND_HIDDEN Registers_s390x {
478381ad6265SDimitry Andric public:
478481ad6265SDimitry Andric Registers_s390x();
478581ad6265SDimitry Andric Registers_s390x(const void *registers);
478681ad6265SDimitry Andric
478781ad6265SDimitry Andric bool validRegister(int num) const;
478881ad6265SDimitry Andric uint64_t getRegister(int num) const;
478981ad6265SDimitry Andric void setRegister(int num, uint64_t value);
479081ad6265SDimitry Andric bool validFloatRegister(int num) const;
479181ad6265SDimitry Andric double getFloatRegister(int num) const;
479281ad6265SDimitry Andric void setFloatRegister(int num, double value);
479381ad6265SDimitry Andric bool validVectorRegister(int num) const;
479481ad6265SDimitry Andric v128 getVectorRegister(int num) const;
479581ad6265SDimitry Andric void setVectorRegister(int num, v128 value);
479681ad6265SDimitry Andric static const char *getRegisterName(int num);
479781ad6265SDimitry Andric void jumpto();
lastDwarfRegNum()479881ad6265SDimitry Andric static constexpr int lastDwarfRegNum() {
479981ad6265SDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X;
480081ad6265SDimitry Andric }
getArch()480181ad6265SDimitry Andric static int getArch() { return REGISTERS_S390X; }
480281ad6265SDimitry Andric
getSP() const480381ad6265SDimitry Andric uint64_t getSP() const { return _registers.__gpr[15]; }
setSP(uint64_t value)480481ad6265SDimitry Andric void setSP(uint64_t value) { _registers.__gpr[15] = value; }
getIP() const480581ad6265SDimitry Andric uint64_t getIP() const { return _registers.__pswa; }
setIP(uint64_t value)480681ad6265SDimitry Andric void setIP(uint64_t value) { _registers.__pswa = value; }
480781ad6265SDimitry Andric
480881ad6265SDimitry Andric private:
480981ad6265SDimitry Andric struct s390x_thread_state_t {
481081ad6265SDimitry Andric uint64_t __pswm; // Problem Status Word: Mask
481181ad6265SDimitry Andric uint64_t __pswa; // Problem Status Word: Address (PC)
481281ad6265SDimitry Andric uint64_t __gpr[16]; // General Purpose Registers
481381ad6265SDimitry Andric double __fpr[16]; // Floating-Point Registers
481481ad6265SDimitry Andric };
481581ad6265SDimitry Andric
481681ad6265SDimitry Andric s390x_thread_state_t _registers;
481781ad6265SDimitry Andric };
481881ad6265SDimitry Andric
Registers_s390x(const void * registers)481981ad6265SDimitry Andric inline Registers_s390x::Registers_s390x(const void *registers) {
482081ad6265SDimitry Andric static_assert((check_fit<Registers_s390x, unw_context_t>::does_fit),
482181ad6265SDimitry Andric "s390x registers do not fit into unw_context_t");
482281ad6265SDimitry Andric memcpy(&_registers, static_cast<const uint8_t *>(registers),
482381ad6265SDimitry Andric sizeof(_registers));
482481ad6265SDimitry Andric }
482581ad6265SDimitry Andric
Registers_s390x()482681ad6265SDimitry Andric inline Registers_s390x::Registers_s390x() {
482781ad6265SDimitry Andric memset(&_registers, 0, sizeof(_registers));
482881ad6265SDimitry Andric }
482981ad6265SDimitry Andric
validRegister(int regNum) const483081ad6265SDimitry Andric inline bool Registers_s390x::validRegister(int regNum) const {
483181ad6265SDimitry Andric switch (regNum) {
483281ad6265SDimitry Andric case UNW_S390X_PSWM:
483381ad6265SDimitry Andric case UNW_S390X_PSWA:
483481ad6265SDimitry Andric case UNW_REG_IP:
483581ad6265SDimitry Andric case UNW_REG_SP:
483681ad6265SDimitry Andric return true;
483781ad6265SDimitry Andric }
483881ad6265SDimitry Andric
483981ad6265SDimitry Andric if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
484081ad6265SDimitry Andric return true;
484181ad6265SDimitry Andric
484281ad6265SDimitry Andric return false;
484381ad6265SDimitry Andric }
484481ad6265SDimitry Andric
getRegister(int regNum) const484581ad6265SDimitry Andric inline uint64_t Registers_s390x::getRegister(int regNum) const {
484681ad6265SDimitry Andric if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
484781ad6265SDimitry Andric return _registers.__gpr[regNum - UNW_S390X_R0];
484881ad6265SDimitry Andric
484981ad6265SDimitry Andric switch (regNum) {
485081ad6265SDimitry Andric case UNW_S390X_PSWM:
485181ad6265SDimitry Andric return _registers.__pswm;
485281ad6265SDimitry Andric case UNW_S390X_PSWA:
485381ad6265SDimitry Andric case UNW_REG_IP:
485481ad6265SDimitry Andric return _registers.__pswa;
485581ad6265SDimitry Andric case UNW_REG_SP:
485681ad6265SDimitry Andric return _registers.__gpr[15];
485781ad6265SDimitry Andric }
485881ad6265SDimitry Andric _LIBUNWIND_ABORT("unsupported s390x register");
485981ad6265SDimitry Andric }
486081ad6265SDimitry Andric
setRegister(int regNum,uint64_t value)486181ad6265SDimitry Andric inline void Registers_s390x::setRegister(int regNum, uint64_t value) {
486281ad6265SDimitry Andric if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) {
486381ad6265SDimitry Andric _registers.__gpr[regNum - UNW_S390X_R0] = value;
486481ad6265SDimitry Andric return;
486581ad6265SDimitry Andric }
486681ad6265SDimitry Andric
486781ad6265SDimitry Andric switch (regNum) {
486881ad6265SDimitry Andric case UNW_S390X_PSWM:
486981ad6265SDimitry Andric _registers.__pswm = value;
487081ad6265SDimitry Andric return;
487181ad6265SDimitry Andric case UNW_S390X_PSWA:
487281ad6265SDimitry Andric case UNW_REG_IP:
487381ad6265SDimitry Andric _registers.__pswa = value;
487481ad6265SDimitry Andric return;
487581ad6265SDimitry Andric case UNW_REG_SP:
487681ad6265SDimitry Andric _registers.__gpr[15] = value;
487781ad6265SDimitry Andric return;
487881ad6265SDimitry Andric }
487981ad6265SDimitry Andric _LIBUNWIND_ABORT("unsupported s390x register");
488081ad6265SDimitry Andric }
488181ad6265SDimitry Andric
validFloatRegister(int regNum) const488281ad6265SDimitry Andric inline bool Registers_s390x::validFloatRegister(int regNum) const {
488381ad6265SDimitry Andric return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15;
488481ad6265SDimitry Andric }
488581ad6265SDimitry Andric
getFloatRegister(int regNum) const488681ad6265SDimitry Andric inline double Registers_s390x::getFloatRegister(int regNum) const {
488781ad6265SDimitry Andric // NOTE: FPR DWARF register numbers are not consecutive.
488881ad6265SDimitry Andric switch (regNum) {
488981ad6265SDimitry Andric case UNW_S390X_F0:
489081ad6265SDimitry Andric return _registers.__fpr[0];
489181ad6265SDimitry Andric case UNW_S390X_F1:
489281ad6265SDimitry Andric return _registers.__fpr[1];
489381ad6265SDimitry Andric case UNW_S390X_F2:
489481ad6265SDimitry Andric return _registers.__fpr[2];
489581ad6265SDimitry Andric case UNW_S390X_F3:
489681ad6265SDimitry Andric return _registers.__fpr[3];
489781ad6265SDimitry Andric case UNW_S390X_F4:
489881ad6265SDimitry Andric return _registers.__fpr[4];
489981ad6265SDimitry Andric case UNW_S390X_F5:
490081ad6265SDimitry Andric return _registers.__fpr[5];
490181ad6265SDimitry Andric case UNW_S390X_F6:
490281ad6265SDimitry Andric return _registers.__fpr[6];
490381ad6265SDimitry Andric case UNW_S390X_F7:
490481ad6265SDimitry Andric return _registers.__fpr[7];
490581ad6265SDimitry Andric case UNW_S390X_F8:
490681ad6265SDimitry Andric return _registers.__fpr[8];
490781ad6265SDimitry Andric case UNW_S390X_F9:
490881ad6265SDimitry Andric return _registers.__fpr[9];
490981ad6265SDimitry Andric case UNW_S390X_F10:
491081ad6265SDimitry Andric return _registers.__fpr[10];
491181ad6265SDimitry Andric case UNW_S390X_F11:
491281ad6265SDimitry Andric return _registers.__fpr[11];
491381ad6265SDimitry Andric case UNW_S390X_F12:
491481ad6265SDimitry Andric return _registers.__fpr[12];
491581ad6265SDimitry Andric case UNW_S390X_F13:
491681ad6265SDimitry Andric return _registers.__fpr[13];
491781ad6265SDimitry Andric case UNW_S390X_F14:
491881ad6265SDimitry Andric return _registers.__fpr[14];
491981ad6265SDimitry Andric case UNW_S390X_F15:
492081ad6265SDimitry Andric return _registers.__fpr[15];
492181ad6265SDimitry Andric }
492281ad6265SDimitry Andric _LIBUNWIND_ABORT("unsupported s390x register");
492381ad6265SDimitry Andric }
492481ad6265SDimitry Andric
setFloatRegister(int regNum,double value)492581ad6265SDimitry Andric inline void Registers_s390x::setFloatRegister(int regNum, double value) {
492681ad6265SDimitry Andric // NOTE: FPR DWARF register numbers are not consecutive.
492781ad6265SDimitry Andric switch (regNum) {
492881ad6265SDimitry Andric case UNW_S390X_F0:
492981ad6265SDimitry Andric _registers.__fpr[0] = value;
493081ad6265SDimitry Andric return;
493181ad6265SDimitry Andric case UNW_S390X_F1:
493281ad6265SDimitry Andric _registers.__fpr[1] = value;
493381ad6265SDimitry Andric return;
493481ad6265SDimitry Andric case UNW_S390X_F2:
493581ad6265SDimitry Andric _registers.__fpr[2] = value;
493681ad6265SDimitry Andric return;
493781ad6265SDimitry Andric case UNW_S390X_F3:
493881ad6265SDimitry Andric _registers.__fpr[3] = value;
493981ad6265SDimitry Andric return;
494081ad6265SDimitry Andric case UNW_S390X_F4:
494181ad6265SDimitry Andric _registers.__fpr[4] = value;
494281ad6265SDimitry Andric return;
494381ad6265SDimitry Andric case UNW_S390X_F5:
494481ad6265SDimitry Andric _registers.__fpr[5] = value;
494581ad6265SDimitry Andric return;
494681ad6265SDimitry Andric case UNW_S390X_F6:
494781ad6265SDimitry Andric _registers.__fpr[6] = value;
494881ad6265SDimitry Andric return;
494981ad6265SDimitry Andric case UNW_S390X_F7:
495081ad6265SDimitry Andric _registers.__fpr[7] = value;
495181ad6265SDimitry Andric return;
495281ad6265SDimitry Andric case UNW_S390X_F8:
495381ad6265SDimitry Andric _registers.__fpr[8] = value;
495481ad6265SDimitry Andric return;
495581ad6265SDimitry Andric case UNW_S390X_F9:
495681ad6265SDimitry Andric _registers.__fpr[9] = value;
495781ad6265SDimitry Andric return;
495881ad6265SDimitry Andric case UNW_S390X_F10:
495981ad6265SDimitry Andric _registers.__fpr[10] = value;
496081ad6265SDimitry Andric return;
496181ad6265SDimitry Andric case UNW_S390X_F11:
496281ad6265SDimitry Andric _registers.__fpr[11] = value;
496381ad6265SDimitry Andric return;
496481ad6265SDimitry Andric case UNW_S390X_F12:
496581ad6265SDimitry Andric _registers.__fpr[12] = value;
496681ad6265SDimitry Andric return;
496781ad6265SDimitry Andric case UNW_S390X_F13:
496881ad6265SDimitry Andric _registers.__fpr[13] = value;
496981ad6265SDimitry Andric return;
497081ad6265SDimitry Andric case UNW_S390X_F14:
497181ad6265SDimitry Andric _registers.__fpr[14] = value;
497281ad6265SDimitry Andric return;
497381ad6265SDimitry Andric case UNW_S390X_F15:
497481ad6265SDimitry Andric _registers.__fpr[15] = value;
497581ad6265SDimitry Andric return;
497681ad6265SDimitry Andric }
497781ad6265SDimitry Andric _LIBUNWIND_ABORT("unsupported s390x register");
497881ad6265SDimitry Andric }
497981ad6265SDimitry Andric
validVectorRegister(int) const498081ad6265SDimitry Andric inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
498181ad6265SDimitry Andric return false;
498281ad6265SDimitry Andric }
498381ad6265SDimitry Andric
getVectorRegister(int) const498481ad6265SDimitry Andric inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const {
498581ad6265SDimitry Andric _LIBUNWIND_ABORT("s390x vector support not implemented");
498681ad6265SDimitry Andric }
498781ad6265SDimitry Andric
setVectorRegister(int,v128)498881ad6265SDimitry Andric inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) {
498981ad6265SDimitry Andric _LIBUNWIND_ABORT("s390x vector support not implemented");
499081ad6265SDimitry Andric }
499181ad6265SDimitry Andric
getRegisterName(int regNum)499281ad6265SDimitry Andric inline const char *Registers_s390x::getRegisterName(int regNum) {
499381ad6265SDimitry Andric switch (regNum) {
499481ad6265SDimitry Andric case UNW_REG_IP:
499581ad6265SDimitry Andric return "ip";
499681ad6265SDimitry Andric case UNW_REG_SP:
499781ad6265SDimitry Andric return "sp";
499881ad6265SDimitry Andric case UNW_S390X_R0:
499981ad6265SDimitry Andric return "r0";
500081ad6265SDimitry Andric case UNW_S390X_R1:
500181ad6265SDimitry Andric return "r1";
500281ad6265SDimitry Andric case UNW_S390X_R2:
500381ad6265SDimitry Andric return "r2";
500481ad6265SDimitry Andric case UNW_S390X_R3:
500581ad6265SDimitry Andric return "r3";
500681ad6265SDimitry Andric case UNW_S390X_R4:
500781ad6265SDimitry Andric return "r4";
500881ad6265SDimitry Andric case UNW_S390X_R5:
500981ad6265SDimitry Andric return "r5";
501081ad6265SDimitry Andric case UNW_S390X_R6:
501181ad6265SDimitry Andric return "r6";
501281ad6265SDimitry Andric case UNW_S390X_R7:
501381ad6265SDimitry Andric return "r7";
501481ad6265SDimitry Andric case UNW_S390X_R8:
501581ad6265SDimitry Andric return "r8";
501681ad6265SDimitry Andric case UNW_S390X_R9:
501781ad6265SDimitry Andric return "r9";
501881ad6265SDimitry Andric case UNW_S390X_R10:
501981ad6265SDimitry Andric return "r10";
502081ad6265SDimitry Andric case UNW_S390X_R11:
502181ad6265SDimitry Andric return "r11";
502281ad6265SDimitry Andric case UNW_S390X_R12:
502381ad6265SDimitry Andric return "r12";
502481ad6265SDimitry Andric case UNW_S390X_R13:
502581ad6265SDimitry Andric return "r13";
502681ad6265SDimitry Andric case UNW_S390X_R14:
502781ad6265SDimitry Andric return "r14";
502881ad6265SDimitry Andric case UNW_S390X_R15:
502981ad6265SDimitry Andric return "r15";
503081ad6265SDimitry Andric case UNW_S390X_F0:
503181ad6265SDimitry Andric return "f0";
503281ad6265SDimitry Andric case UNW_S390X_F1:
503381ad6265SDimitry Andric return "f1";
503481ad6265SDimitry Andric case UNW_S390X_F2:
503581ad6265SDimitry Andric return "f2";
503681ad6265SDimitry Andric case UNW_S390X_F3:
503781ad6265SDimitry Andric return "f3";
503881ad6265SDimitry Andric case UNW_S390X_F4:
503981ad6265SDimitry Andric return "f4";
504081ad6265SDimitry Andric case UNW_S390X_F5:
504181ad6265SDimitry Andric return "f5";
504281ad6265SDimitry Andric case UNW_S390X_F6:
504381ad6265SDimitry Andric return "f6";
504481ad6265SDimitry Andric case UNW_S390X_F7:
504581ad6265SDimitry Andric return "f7";
504681ad6265SDimitry Andric case UNW_S390X_F8:
504781ad6265SDimitry Andric return "f8";
504881ad6265SDimitry Andric case UNW_S390X_F9:
504981ad6265SDimitry Andric return "f9";
505081ad6265SDimitry Andric case UNW_S390X_F10:
505181ad6265SDimitry Andric return "f10";
505281ad6265SDimitry Andric case UNW_S390X_F11:
505381ad6265SDimitry Andric return "f11";
505481ad6265SDimitry Andric case UNW_S390X_F12:
505581ad6265SDimitry Andric return "f12";
505681ad6265SDimitry Andric case UNW_S390X_F13:
505781ad6265SDimitry Andric return "f13";
505881ad6265SDimitry Andric case UNW_S390X_F14:
505981ad6265SDimitry Andric return "f14";
506081ad6265SDimitry Andric case UNW_S390X_F15:
506181ad6265SDimitry Andric return "f15";
506281ad6265SDimitry Andric }
506381ad6265SDimitry Andric return "unknown register";
506481ad6265SDimitry Andric }
506581ad6265SDimitry Andric #endif // _LIBUNWIND_TARGET_S390X
506681ad6265SDimitry Andric
5067bdd1243dSDimitry Andric #if defined(_LIBUNWIND_TARGET_LOONGARCH)
5068bdd1243dSDimitry Andric /// Registers_loongarch holds the register state of a thread in a 64-bit
5069bdd1243dSDimitry Andric /// LoongArch process.
5070bdd1243dSDimitry Andric class _LIBUNWIND_HIDDEN Registers_loongarch {
5071bdd1243dSDimitry Andric public:
5072bdd1243dSDimitry Andric Registers_loongarch();
5073bdd1243dSDimitry Andric Registers_loongarch(const void *registers);
5074bdd1243dSDimitry Andric
5075bdd1243dSDimitry Andric bool validRegister(int num) const;
5076bdd1243dSDimitry Andric uint64_t getRegister(int num) const;
5077bdd1243dSDimitry Andric void setRegister(int num, uint64_t value);
5078bdd1243dSDimitry Andric bool validFloatRegister(int num) const;
5079bdd1243dSDimitry Andric double getFloatRegister(int num) const;
5080bdd1243dSDimitry Andric void setFloatRegister(int num, double value);
5081bdd1243dSDimitry Andric bool validVectorRegister(int num) const;
5082bdd1243dSDimitry Andric v128 getVectorRegister(int num) const;
5083bdd1243dSDimitry Andric void setVectorRegister(int num, v128 value);
5084bdd1243dSDimitry Andric static const char *getRegisterName(int num);
5085bdd1243dSDimitry Andric void jumpto();
lastDwarfRegNum()5086bdd1243dSDimitry Andric static constexpr int lastDwarfRegNum() {
5087bdd1243dSDimitry Andric return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH;
5088bdd1243dSDimitry Andric }
getArch()5089bdd1243dSDimitry Andric static int getArch() { return REGISTERS_LOONGARCH; }
5090bdd1243dSDimitry Andric
getSP() const5091bdd1243dSDimitry Andric uint64_t getSP() const { return _registers.__r[3]; }
setSP(uint64_t value)5092bdd1243dSDimitry Andric void setSP(uint64_t value) { _registers.__r[3] = value; }
getIP() const5093bdd1243dSDimitry Andric uint64_t getIP() const { return _registers.__pc; }
setIP(uint64_t value)5094bdd1243dSDimitry Andric void setIP(uint64_t value) { _registers.__pc = value; }
5095bdd1243dSDimitry Andric
5096bdd1243dSDimitry Andric private:
5097bdd1243dSDimitry Andric struct loongarch_thread_state_t {
5098bdd1243dSDimitry Andric uint64_t __r[32];
5099bdd1243dSDimitry Andric uint64_t __pc;
5100bdd1243dSDimitry Andric };
5101bdd1243dSDimitry Andric
5102bdd1243dSDimitry Andric loongarch_thread_state_t _registers;
5103bdd1243dSDimitry Andric #if __loongarch_frlen == 64
5104bdd1243dSDimitry Andric double _floats[32];
5105bdd1243dSDimitry Andric #endif
5106bdd1243dSDimitry Andric };
5107bdd1243dSDimitry Andric
Registers_loongarch(const void * registers)5108bdd1243dSDimitry Andric inline Registers_loongarch::Registers_loongarch(const void *registers) {
5109bdd1243dSDimitry Andric static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit),
5110bdd1243dSDimitry Andric "loongarch registers do not fit into unw_context_t");
5111bdd1243dSDimitry Andric memcpy(&_registers, registers, sizeof(_registers));
5112bdd1243dSDimitry Andric static_assert(sizeof(_registers) == 0x108,
5113bdd1243dSDimitry Andric "expected float registers to be at offset 264");
5114bdd1243dSDimitry Andric #if __loongarch_frlen == 64
5115bdd1243dSDimitry Andric memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers),
5116bdd1243dSDimitry Andric sizeof(_floats));
5117bdd1243dSDimitry Andric #endif
5118bdd1243dSDimitry Andric }
5119bdd1243dSDimitry Andric
Registers_loongarch()5120bdd1243dSDimitry Andric inline Registers_loongarch::Registers_loongarch() {
5121bdd1243dSDimitry Andric memset(&_registers, 0, sizeof(_registers));
5122bdd1243dSDimitry Andric #if __loongarch_frlen == 64
5123bdd1243dSDimitry Andric memset(&_floats, 0, sizeof(_floats));
5124bdd1243dSDimitry Andric #endif
5125bdd1243dSDimitry Andric }
5126bdd1243dSDimitry Andric
validRegister(int regNum) const5127bdd1243dSDimitry Andric inline bool Registers_loongarch::validRegister(int regNum) const {
5128bdd1243dSDimitry Andric if (regNum == UNW_REG_IP || regNum == UNW_REG_SP)
5129bdd1243dSDimitry Andric return true;
5130bdd1243dSDimitry Andric if (regNum < 0 || regNum > UNW_LOONGARCH_F31)
5131bdd1243dSDimitry Andric return false;
5132bdd1243dSDimitry Andric return true;
5133bdd1243dSDimitry Andric }
5134bdd1243dSDimitry Andric
getRegister(int regNum) const5135bdd1243dSDimitry Andric inline uint64_t Registers_loongarch::getRegister(int regNum) const {
5136bdd1243dSDimitry Andric if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
5137bdd1243dSDimitry Andric return _registers.__r[regNum - UNW_LOONGARCH_R0];
5138bdd1243dSDimitry Andric
5139bdd1243dSDimitry Andric if (regNum == UNW_REG_IP)
5140bdd1243dSDimitry Andric return _registers.__pc;
5141bdd1243dSDimitry Andric if (regNum == UNW_REG_SP)
5142bdd1243dSDimitry Andric return _registers.__r[3];
5143bdd1243dSDimitry Andric _LIBUNWIND_ABORT("unsupported loongarch register");
5144bdd1243dSDimitry Andric }
5145bdd1243dSDimitry Andric
setRegister(int regNum,uint64_t value)5146bdd1243dSDimitry Andric inline void Registers_loongarch::setRegister(int regNum, uint64_t value) {
5147bdd1243dSDimitry Andric if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
5148bdd1243dSDimitry Andric _registers.__r[regNum - UNW_LOONGARCH_R0] = value;
5149bdd1243dSDimitry Andric else if (regNum == UNW_REG_IP)
5150bdd1243dSDimitry Andric _registers.__pc = value;
5151bdd1243dSDimitry Andric else if (regNum == UNW_REG_SP)
5152bdd1243dSDimitry Andric _registers.__r[3] = value;
5153bdd1243dSDimitry Andric else
5154bdd1243dSDimitry Andric _LIBUNWIND_ABORT("unsupported loongarch register");
5155bdd1243dSDimitry Andric }
5156bdd1243dSDimitry Andric
getRegisterName(int regNum)5157bdd1243dSDimitry Andric inline const char *Registers_loongarch::getRegisterName(int regNum) {
5158bdd1243dSDimitry Andric switch (regNum) {
5159bdd1243dSDimitry Andric case UNW_REG_IP:
5160bdd1243dSDimitry Andric return "$pc";
5161bdd1243dSDimitry Andric case UNW_REG_SP:
5162bdd1243dSDimitry Andric return "$sp";
5163bdd1243dSDimitry Andric case UNW_LOONGARCH_R0:
5164bdd1243dSDimitry Andric return "$r0";
5165bdd1243dSDimitry Andric case UNW_LOONGARCH_R1:
5166bdd1243dSDimitry Andric return "$r1";
5167bdd1243dSDimitry Andric case UNW_LOONGARCH_R2:
5168bdd1243dSDimitry Andric return "$r2";
5169bdd1243dSDimitry Andric case UNW_LOONGARCH_R3:
5170bdd1243dSDimitry Andric return "$r3";
5171bdd1243dSDimitry Andric case UNW_LOONGARCH_R4:
5172bdd1243dSDimitry Andric return "$r4";
5173bdd1243dSDimitry Andric case UNW_LOONGARCH_R5:
5174bdd1243dSDimitry Andric return "$r5";
5175bdd1243dSDimitry Andric case UNW_LOONGARCH_R6:
5176bdd1243dSDimitry Andric return "$r6";
5177bdd1243dSDimitry Andric case UNW_LOONGARCH_R7:
5178bdd1243dSDimitry Andric return "$r7";
5179bdd1243dSDimitry Andric case UNW_LOONGARCH_R8:
5180bdd1243dSDimitry Andric return "$r8";
5181bdd1243dSDimitry Andric case UNW_LOONGARCH_R9:
5182bdd1243dSDimitry Andric return "$r9";
5183bdd1243dSDimitry Andric case UNW_LOONGARCH_R10:
5184bdd1243dSDimitry Andric return "$r10";
5185bdd1243dSDimitry Andric case UNW_LOONGARCH_R11:
5186bdd1243dSDimitry Andric return "$r11";
5187bdd1243dSDimitry Andric case UNW_LOONGARCH_R12:
5188bdd1243dSDimitry Andric return "$r12";
5189bdd1243dSDimitry Andric case UNW_LOONGARCH_R13:
5190bdd1243dSDimitry Andric return "$r13";
5191bdd1243dSDimitry Andric case UNW_LOONGARCH_R14:
5192bdd1243dSDimitry Andric return "$r14";
5193bdd1243dSDimitry Andric case UNW_LOONGARCH_R15:
5194bdd1243dSDimitry Andric return "$r15";
5195bdd1243dSDimitry Andric case UNW_LOONGARCH_R16:
5196bdd1243dSDimitry Andric return "$r16";
5197bdd1243dSDimitry Andric case UNW_LOONGARCH_R17:
5198bdd1243dSDimitry Andric return "$r17";
5199bdd1243dSDimitry Andric case UNW_LOONGARCH_R18:
5200bdd1243dSDimitry Andric return "$r18";
5201bdd1243dSDimitry Andric case UNW_LOONGARCH_R19:
5202bdd1243dSDimitry Andric return "$r19";
5203bdd1243dSDimitry Andric case UNW_LOONGARCH_R20:
5204bdd1243dSDimitry Andric return "$r20";
5205bdd1243dSDimitry Andric case UNW_LOONGARCH_R21:
5206bdd1243dSDimitry Andric return "$r21";
5207bdd1243dSDimitry Andric case UNW_LOONGARCH_R22:
5208bdd1243dSDimitry Andric return "$r22";
5209bdd1243dSDimitry Andric case UNW_LOONGARCH_R23:
5210bdd1243dSDimitry Andric return "$r23";
5211bdd1243dSDimitry Andric case UNW_LOONGARCH_R24:
5212bdd1243dSDimitry Andric return "$r24";
5213bdd1243dSDimitry Andric case UNW_LOONGARCH_R25:
5214bdd1243dSDimitry Andric return "$r25";
5215bdd1243dSDimitry Andric case UNW_LOONGARCH_R26:
5216bdd1243dSDimitry Andric return "$r26";
5217bdd1243dSDimitry Andric case UNW_LOONGARCH_R27:
5218bdd1243dSDimitry Andric return "$r27";
5219bdd1243dSDimitry Andric case UNW_LOONGARCH_R28:
5220bdd1243dSDimitry Andric return "$r28";
5221bdd1243dSDimitry Andric case UNW_LOONGARCH_R29:
5222bdd1243dSDimitry Andric return "$r29";
5223bdd1243dSDimitry Andric case UNW_LOONGARCH_R30:
5224bdd1243dSDimitry Andric return "$r30";
5225bdd1243dSDimitry Andric case UNW_LOONGARCH_R31:
5226bdd1243dSDimitry Andric return "$r31";
5227bdd1243dSDimitry Andric case UNW_LOONGARCH_F0:
5228bdd1243dSDimitry Andric return "$f0";
5229bdd1243dSDimitry Andric case UNW_LOONGARCH_F1:
5230bdd1243dSDimitry Andric return "$f1";
5231bdd1243dSDimitry Andric case UNW_LOONGARCH_F2:
5232bdd1243dSDimitry Andric return "$f2";
5233bdd1243dSDimitry Andric case UNW_LOONGARCH_F3:
5234bdd1243dSDimitry Andric return "$f3";
5235bdd1243dSDimitry Andric case UNW_LOONGARCH_F4:
5236bdd1243dSDimitry Andric return "$f4";
5237bdd1243dSDimitry Andric case UNW_LOONGARCH_F5:
5238bdd1243dSDimitry Andric return "$f5";
5239bdd1243dSDimitry Andric case UNW_LOONGARCH_F6:
5240bdd1243dSDimitry Andric return "$f6";
5241bdd1243dSDimitry Andric case UNW_LOONGARCH_F7:
5242bdd1243dSDimitry Andric return "$f7";
5243bdd1243dSDimitry Andric case UNW_LOONGARCH_F8:
5244bdd1243dSDimitry Andric return "$f8";
5245bdd1243dSDimitry Andric case UNW_LOONGARCH_F9:
5246bdd1243dSDimitry Andric return "$f9";
5247bdd1243dSDimitry Andric case UNW_LOONGARCH_F10:
5248bdd1243dSDimitry Andric return "$f10";
5249bdd1243dSDimitry Andric case UNW_LOONGARCH_F11:
5250bdd1243dSDimitry Andric return "$f11";
5251bdd1243dSDimitry Andric case UNW_LOONGARCH_F12:
5252bdd1243dSDimitry Andric return "$f12";
5253bdd1243dSDimitry Andric case UNW_LOONGARCH_F13:
5254bdd1243dSDimitry Andric return "$f13";
5255bdd1243dSDimitry Andric case UNW_LOONGARCH_F14:
5256bdd1243dSDimitry Andric return "$f14";
5257bdd1243dSDimitry Andric case UNW_LOONGARCH_F15:
5258bdd1243dSDimitry Andric return "$f15";
5259bdd1243dSDimitry Andric case UNW_LOONGARCH_F16:
5260bdd1243dSDimitry Andric return "$f16";
5261bdd1243dSDimitry Andric case UNW_LOONGARCH_F17:
5262bdd1243dSDimitry Andric return "$f17";
5263bdd1243dSDimitry Andric case UNW_LOONGARCH_F18:
5264bdd1243dSDimitry Andric return "$f18";
5265bdd1243dSDimitry Andric case UNW_LOONGARCH_F19:
5266bdd1243dSDimitry Andric return "$f19";
5267bdd1243dSDimitry Andric case UNW_LOONGARCH_F20:
5268bdd1243dSDimitry Andric return "$f20";
5269bdd1243dSDimitry Andric case UNW_LOONGARCH_F21:
5270bdd1243dSDimitry Andric return "$f21";
5271bdd1243dSDimitry Andric case UNW_LOONGARCH_F22:
5272bdd1243dSDimitry Andric return "$f22";
5273bdd1243dSDimitry Andric case UNW_LOONGARCH_F23:
5274bdd1243dSDimitry Andric return "$f23";
5275bdd1243dSDimitry Andric case UNW_LOONGARCH_F24:
5276bdd1243dSDimitry Andric return "$f24";
5277bdd1243dSDimitry Andric case UNW_LOONGARCH_F25:
5278bdd1243dSDimitry Andric return "$f25";
5279bdd1243dSDimitry Andric case UNW_LOONGARCH_F26:
5280bdd1243dSDimitry Andric return "$f26";
5281bdd1243dSDimitry Andric case UNW_LOONGARCH_F27:
5282bdd1243dSDimitry Andric return "$f27";
5283bdd1243dSDimitry Andric case UNW_LOONGARCH_F28:
5284bdd1243dSDimitry Andric return "$f28";
5285bdd1243dSDimitry Andric case UNW_LOONGARCH_F29:
5286bdd1243dSDimitry Andric return "$f29";
5287bdd1243dSDimitry Andric case UNW_LOONGARCH_F30:
5288bdd1243dSDimitry Andric return "$f30";
5289bdd1243dSDimitry Andric case UNW_LOONGARCH_F31:
5290bdd1243dSDimitry Andric return "$f31";
5291bdd1243dSDimitry Andric default:
5292bdd1243dSDimitry Andric return "unknown register";
5293bdd1243dSDimitry Andric }
5294bdd1243dSDimitry Andric }
5295bdd1243dSDimitry Andric
validFloatRegister(int regNum) const5296bdd1243dSDimitry Andric inline bool Registers_loongarch::validFloatRegister(int regNum) const {
5297bdd1243dSDimitry Andric if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31)
5298bdd1243dSDimitry Andric return false;
5299bdd1243dSDimitry Andric return true;
5300bdd1243dSDimitry Andric }
5301bdd1243dSDimitry Andric
getFloatRegister(int regNum) const5302bdd1243dSDimitry Andric inline double Registers_loongarch::getFloatRegister(int regNum) const {
5303bdd1243dSDimitry Andric #if __loongarch_frlen == 64
5304bdd1243dSDimitry Andric assert(validFloatRegister(regNum));
5305bdd1243dSDimitry Andric return _floats[regNum - UNW_LOONGARCH_F0];
5306bdd1243dSDimitry Andric #else
5307bdd1243dSDimitry Andric _LIBUNWIND_ABORT("libunwind not built with float support");
5308bdd1243dSDimitry Andric #endif
5309bdd1243dSDimitry Andric }
5310bdd1243dSDimitry Andric
setFloatRegister(int regNum,double value)5311bdd1243dSDimitry Andric inline void Registers_loongarch::setFloatRegister(int regNum, double value) {
5312bdd1243dSDimitry Andric #if __loongarch_frlen == 64
5313bdd1243dSDimitry Andric assert(validFloatRegister(regNum));
5314bdd1243dSDimitry Andric _floats[regNum - UNW_LOONGARCH_F0] = value;
5315bdd1243dSDimitry Andric #else
5316bdd1243dSDimitry Andric _LIBUNWIND_ABORT("libunwind not built with float support");
5317bdd1243dSDimitry Andric #endif
5318bdd1243dSDimitry Andric }
5319bdd1243dSDimitry Andric
validVectorRegister(int) const5320bdd1243dSDimitry Andric inline bool Registers_loongarch::validVectorRegister(int) const {
5321bdd1243dSDimitry Andric return false;
5322bdd1243dSDimitry Andric }
5323bdd1243dSDimitry Andric
getVectorRegister(int) const5324bdd1243dSDimitry Andric inline v128 Registers_loongarch::getVectorRegister(int) const {
5325bdd1243dSDimitry Andric _LIBUNWIND_ABORT("loongarch vector support not implemented");
5326bdd1243dSDimitry Andric }
5327bdd1243dSDimitry Andric
setVectorRegister(int,v128)5328bdd1243dSDimitry Andric inline void Registers_loongarch::setVectorRegister(int, v128) {
5329bdd1243dSDimitry Andric _LIBUNWIND_ABORT("loongarch vector support not implemented");
5330bdd1243dSDimitry Andric }
5331bdd1243dSDimitry Andric #endif //_LIBUNWIND_TARGET_LOONGARCH
533281ad6265SDimitry Andric
53330b57cec5SDimitry Andric } // namespace libunwind
53340b57cec5SDimitry Andric
53350b57cec5SDimitry Andric #endif // __REGISTERS_HPP__
5336