Path: blob/main/contrib/llvm-project/libunwind/src/Registers.hpp
96309 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//7// Models register sets for supported processors.8//9//===----------------------------------------------------------------------===//1011#ifndef __REGISTERS_HPP__12#define __REGISTERS_HPP__1314#include <stdint.h>15#include <string.h>1617#include "cet_unwind.h"18#include "config.h"19#include "libunwind.h"2021namespace libunwind {2223// For emulating 128-bit registers24struct v128 { uint32_t vec[4]; };2526enum {27REGISTERS_X86,28REGISTERS_X86_64,29REGISTERS_PPC,30REGISTERS_PPC64,31REGISTERS_ARM64,32REGISTERS_ARM,33REGISTERS_OR1K,34REGISTERS_MIPS_O32,35REGISTERS_MIPS_NEWABI,36REGISTERS_SPARC,37REGISTERS_SPARC64,38REGISTERS_HEXAGON,39REGISTERS_RISCV,40REGISTERS_VE,41REGISTERS_S390X,42REGISTERS_LOONGARCH,43};4445#if defined(_LIBUNWIND_TARGET_I386)46class _LIBUNWIND_HIDDEN Registers_x86;47extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);4849#if defined(_LIBUNWIND_USE_CET)50extern "C" void *__libunwind_cet_get_jump_target() {51return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto);52}53#endif5455/// Registers_x86 holds the register state of a thread in a 32-bit intel56/// process.57class _LIBUNWIND_HIDDEN Registers_x86 {58public:59Registers_x86();60Registers_x86(const void *registers);6162bool validRegister(int num) const;63uint32_t getRegister(int num) const;64void setRegister(int num, uint32_t value);65bool validFloatRegister(int) const { return false; }66double getFloatRegister(int num) const;67void setFloatRegister(int num, double value);68bool validVectorRegister(int) const { return false; }69v128 getVectorRegister(int num) const;70void setVectorRegister(int num, v128 value);71static const char *getRegisterName(int num);72void jumpto() { __libunwind_Registers_x86_jumpto(this); }73static constexpr int lastDwarfRegNum() {74return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86;75}76static int getArch() { return REGISTERS_X86; }7778uint32_t getSP() const { return _registers.__esp; }79void setSP(uint32_t value) { _registers.__esp = value; }80uint32_t getIP() const { return _registers.__eip; }81void setIP(uint32_t value) { _registers.__eip = value; }82uint32_t getEBP() const { return _registers.__ebp; }83void setEBP(uint32_t value) { _registers.__ebp = value; }84uint32_t getEBX() const { return _registers.__ebx; }85void setEBX(uint32_t value) { _registers.__ebx = value; }86uint32_t getECX() const { return _registers.__ecx; }87void setECX(uint32_t value) { _registers.__ecx = value; }88uint32_t getEDX() const { return _registers.__edx; }89void setEDX(uint32_t value) { _registers.__edx = value; }90uint32_t getESI() const { return _registers.__esi; }91void setESI(uint32_t value) { _registers.__esi = value; }92uint32_t getEDI() const { return _registers.__edi; }93void setEDI(uint32_t value) { _registers.__edi = value; }9495private:96struct GPRs {97unsigned int __eax;98unsigned int __ebx;99unsigned int __ecx;100unsigned int __edx;101unsigned int __edi;102unsigned int __esi;103unsigned int __ebp;104unsigned int __esp;105unsigned int __ss;106unsigned int __eflags;107unsigned int __eip;108unsigned int __cs;109unsigned int __ds;110unsigned int __es;111unsigned int __fs;112unsigned int __gs;113};114115GPRs _registers;116};117118inline Registers_x86::Registers_x86(const void *registers) {119static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),120"x86 registers do not fit into unw_context_t");121memcpy(&_registers, registers, sizeof(_registers));122}123124inline Registers_x86::Registers_x86() {125memset(&_registers, 0, sizeof(_registers));126}127128inline bool Registers_x86::validRegister(int regNum) const {129if (regNum == UNW_REG_IP)130return true;131if (regNum == UNW_REG_SP)132return true;133if (regNum < 0)134return false;135if (regNum > 7)136return false;137return true;138}139140inline uint32_t Registers_x86::getRegister(int regNum) const {141switch (regNum) {142case UNW_REG_IP:143return _registers.__eip;144case UNW_REG_SP:145return _registers.__esp;146case UNW_X86_EAX:147return _registers.__eax;148case UNW_X86_ECX:149return _registers.__ecx;150case UNW_X86_EDX:151return _registers.__edx;152case UNW_X86_EBX:153return _registers.__ebx;154#if !defined(__APPLE__)155case UNW_X86_ESP:156#else157case UNW_X86_EBP:158#endif159return _registers.__ebp;160#if !defined(__APPLE__)161case UNW_X86_EBP:162#else163case UNW_X86_ESP:164#endif165return _registers.__esp;166case UNW_X86_ESI:167return _registers.__esi;168case UNW_X86_EDI:169return _registers.__edi;170}171_LIBUNWIND_ABORT("unsupported x86 register");172}173174inline void Registers_x86::setRegister(int regNum, uint32_t value) {175switch (regNum) {176case UNW_REG_IP:177_registers.__eip = value;178return;179case UNW_REG_SP:180_registers.__esp = value;181return;182case UNW_X86_EAX:183_registers.__eax = value;184return;185case UNW_X86_ECX:186_registers.__ecx = value;187return;188case UNW_X86_EDX:189_registers.__edx = value;190return;191case UNW_X86_EBX:192_registers.__ebx = value;193return;194#if !defined(__APPLE__)195case UNW_X86_ESP:196#else197case UNW_X86_EBP:198#endif199_registers.__ebp = value;200return;201#if !defined(__APPLE__)202case UNW_X86_EBP:203#else204case UNW_X86_ESP:205#endif206_registers.__esp = value;207return;208case UNW_X86_ESI:209_registers.__esi = value;210return;211case UNW_X86_EDI:212_registers.__edi = value;213return;214}215_LIBUNWIND_ABORT("unsupported x86 register");216}217218inline const char *Registers_x86::getRegisterName(int regNum) {219switch (regNum) {220case UNW_REG_IP:221return "ip";222case UNW_REG_SP:223return "esp";224case UNW_X86_EAX:225return "eax";226case UNW_X86_ECX:227return "ecx";228case UNW_X86_EDX:229return "edx";230case UNW_X86_EBX:231return "ebx";232case UNW_X86_EBP:233return "ebp";234case UNW_X86_ESP:235return "esp";236case UNW_X86_ESI:237return "esi";238case UNW_X86_EDI:239return "edi";240default:241return "unknown register";242}243}244245inline double Registers_x86::getFloatRegister(int) const {246_LIBUNWIND_ABORT("no x86 float registers");247}248249inline void Registers_x86::setFloatRegister(int, double) {250_LIBUNWIND_ABORT("no x86 float registers");251}252253inline v128 Registers_x86::getVectorRegister(int) const {254_LIBUNWIND_ABORT("no x86 vector registers");255}256257inline void Registers_x86::setVectorRegister(int, v128) {258_LIBUNWIND_ABORT("no x86 vector registers");259}260#endif // _LIBUNWIND_TARGET_I386261262263#if defined(_LIBUNWIND_TARGET_X86_64)264/// Registers_x86_64 holds the register state of a thread in a 64-bit intel265/// process.266class _LIBUNWIND_HIDDEN Registers_x86_64;267extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);268269#if defined(_LIBUNWIND_USE_CET)270extern "C" void *__libunwind_cet_get_jump_target() {271return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto);272}273#endif274275class _LIBUNWIND_HIDDEN Registers_x86_64 {276public:277Registers_x86_64();278Registers_x86_64(const void *registers);279280bool validRegister(int num) const;281uint64_t getRegister(int num) const;282void setRegister(int num, uint64_t value);283bool validFloatRegister(int) const { return false; }284double getFloatRegister(int num) const;285void setFloatRegister(int num, double value);286bool validVectorRegister(int) const;287v128 getVectorRegister(int num) const;288void setVectorRegister(int num, v128 value);289static const char *getRegisterName(int num);290void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }291static constexpr int lastDwarfRegNum() {292return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64;293}294static int getArch() { return REGISTERS_X86_64; }295296uint64_t getSP() const { return _registers.__rsp; }297void setSP(uint64_t value) { _registers.__rsp = value; }298uint64_t getIP() const { return _registers.__rip; }299void setIP(uint64_t value) { _registers.__rip = value; }300uint64_t getRBP() const { return _registers.__rbp; }301void setRBP(uint64_t value) { _registers.__rbp = value; }302uint64_t getRBX() const { return _registers.__rbx; }303void setRBX(uint64_t value) { _registers.__rbx = value; }304uint64_t getR12() const { return _registers.__r12; }305void setR12(uint64_t value) { _registers.__r12 = value; }306uint64_t getR13() const { return _registers.__r13; }307void setR13(uint64_t value) { _registers.__r13 = value; }308uint64_t getR14() const { return _registers.__r14; }309void setR14(uint64_t value) { _registers.__r14 = value; }310uint64_t getR15() const { return _registers.__r15; }311void setR15(uint64_t value) { _registers.__r15 = value; }312313private:314struct GPRs {315uint64_t __rax;316uint64_t __rbx;317uint64_t __rcx;318uint64_t __rdx;319uint64_t __rdi;320uint64_t __rsi;321uint64_t __rbp;322uint64_t __rsp;323uint64_t __r8;324uint64_t __r9;325uint64_t __r10;326uint64_t __r11;327uint64_t __r12;328uint64_t __r13;329uint64_t __r14;330uint64_t __r15;331uint64_t __rip;332uint64_t __rflags;333uint64_t __cs;334uint64_t __fs;335uint64_t __gs;336#if defined(_WIN64)337uint64_t __padding; // 16-byte align338#endif339};340GPRs _registers;341#if defined(_WIN64)342v128 _xmm[16];343#endif344};345346inline Registers_x86_64::Registers_x86_64(const void *registers) {347static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),348"x86_64 registers do not fit into unw_context_t");349memcpy(&_registers, registers, sizeof(_registers));350}351352inline Registers_x86_64::Registers_x86_64() {353memset(&_registers, 0, sizeof(_registers));354}355356inline bool Registers_x86_64::validRegister(int regNum) const {357if (regNum == UNW_REG_IP)358return true;359if (regNum == UNW_REG_SP)360return true;361if (regNum < 0)362return false;363if (regNum > 16)364return false;365return true;366}367368inline uint64_t Registers_x86_64::getRegister(int regNum) const {369switch (regNum) {370case UNW_REG_IP:371case UNW_X86_64_RIP:372return _registers.__rip;373case UNW_REG_SP:374return _registers.__rsp;375case UNW_X86_64_RAX:376return _registers.__rax;377case UNW_X86_64_RDX:378return _registers.__rdx;379case UNW_X86_64_RCX:380return _registers.__rcx;381case UNW_X86_64_RBX:382return _registers.__rbx;383case UNW_X86_64_RSI:384return _registers.__rsi;385case UNW_X86_64_RDI:386return _registers.__rdi;387case UNW_X86_64_RBP:388return _registers.__rbp;389case UNW_X86_64_RSP:390return _registers.__rsp;391case UNW_X86_64_R8:392return _registers.__r8;393case UNW_X86_64_R9:394return _registers.__r9;395case UNW_X86_64_R10:396return _registers.__r10;397case UNW_X86_64_R11:398return _registers.__r11;399case UNW_X86_64_R12:400return _registers.__r12;401case UNW_X86_64_R13:402return _registers.__r13;403case UNW_X86_64_R14:404return _registers.__r14;405case UNW_X86_64_R15:406return _registers.__r15;407}408_LIBUNWIND_ABORT("unsupported x86_64 register");409}410411inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {412switch (regNum) {413case UNW_REG_IP:414case UNW_X86_64_RIP:415_registers.__rip = value;416return;417case UNW_REG_SP:418_registers.__rsp = value;419return;420case UNW_X86_64_RAX:421_registers.__rax = value;422return;423case UNW_X86_64_RDX:424_registers.__rdx = value;425return;426case UNW_X86_64_RCX:427_registers.__rcx = value;428return;429case UNW_X86_64_RBX:430_registers.__rbx = value;431return;432case UNW_X86_64_RSI:433_registers.__rsi = value;434return;435case UNW_X86_64_RDI:436_registers.__rdi = value;437return;438case UNW_X86_64_RBP:439_registers.__rbp = value;440return;441case UNW_X86_64_RSP:442_registers.__rsp = value;443return;444case UNW_X86_64_R8:445_registers.__r8 = value;446return;447case UNW_X86_64_R9:448_registers.__r9 = value;449return;450case UNW_X86_64_R10:451_registers.__r10 = value;452return;453case UNW_X86_64_R11:454_registers.__r11 = value;455return;456case UNW_X86_64_R12:457_registers.__r12 = value;458return;459case UNW_X86_64_R13:460_registers.__r13 = value;461return;462case UNW_X86_64_R14:463_registers.__r14 = value;464return;465case UNW_X86_64_R15:466_registers.__r15 = value;467return;468}469_LIBUNWIND_ABORT("unsupported x86_64 register");470}471472inline const char *Registers_x86_64::getRegisterName(int regNum) {473switch (regNum) {474case UNW_REG_IP:475case UNW_X86_64_RIP:476return "rip";477case UNW_REG_SP:478return "rsp";479case UNW_X86_64_RAX:480return "rax";481case UNW_X86_64_RDX:482return "rdx";483case UNW_X86_64_RCX:484return "rcx";485case UNW_X86_64_RBX:486return "rbx";487case UNW_X86_64_RSI:488return "rsi";489case UNW_X86_64_RDI:490return "rdi";491case UNW_X86_64_RBP:492return "rbp";493case UNW_X86_64_RSP:494return "rsp";495case UNW_X86_64_R8:496return "r8";497case UNW_X86_64_R9:498return "r9";499case UNW_X86_64_R10:500return "r10";501case UNW_X86_64_R11:502return "r11";503case UNW_X86_64_R12:504return "r12";505case UNW_X86_64_R13:506return "r13";507case UNW_X86_64_R14:508return "r14";509case UNW_X86_64_R15:510return "r15";511case UNW_X86_64_XMM0:512return "xmm0";513case UNW_X86_64_XMM1:514return "xmm1";515case UNW_X86_64_XMM2:516return "xmm2";517case UNW_X86_64_XMM3:518return "xmm3";519case UNW_X86_64_XMM4:520return "xmm4";521case UNW_X86_64_XMM5:522return "xmm5";523case UNW_X86_64_XMM6:524return "xmm6";525case UNW_X86_64_XMM7:526return "xmm7";527case UNW_X86_64_XMM8:528return "xmm8";529case UNW_X86_64_XMM9:530return "xmm9";531case UNW_X86_64_XMM10:532return "xmm10";533case UNW_X86_64_XMM11:534return "xmm11";535case UNW_X86_64_XMM12:536return "xmm12";537case UNW_X86_64_XMM13:538return "xmm13";539case UNW_X86_64_XMM14:540return "xmm14";541case UNW_X86_64_XMM15:542return "xmm15";543default:544return "unknown register";545}546}547548inline double Registers_x86_64::getFloatRegister(int) const {549_LIBUNWIND_ABORT("no x86_64 float registers");550}551552inline void Registers_x86_64::setFloatRegister(int, double) {553_LIBUNWIND_ABORT("no x86_64 float registers");554}555556inline bool Registers_x86_64::validVectorRegister(int regNum) const {557#if defined(_WIN64)558if (regNum < UNW_X86_64_XMM0)559return false;560if (regNum > UNW_X86_64_XMM15)561return false;562return true;563#else564(void)regNum; // suppress unused parameter warning565return false;566#endif567}568569inline v128 Registers_x86_64::getVectorRegister(int regNum) const {570#if defined(_WIN64)571assert(validVectorRegister(regNum));572return _xmm[regNum - UNW_X86_64_XMM0];573#else574(void)regNum; // suppress unused parameter warning575_LIBUNWIND_ABORT("no x86_64 vector registers");576#endif577}578579inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {580#if defined(_WIN64)581assert(validVectorRegister(regNum));582_xmm[regNum - UNW_X86_64_XMM0] = value;583#else584(void)regNum; (void)value; // suppress unused parameter warnings585_LIBUNWIND_ABORT("no x86_64 vector registers");586#endif587}588#endif // _LIBUNWIND_TARGET_X86_64589590591#if defined(_LIBUNWIND_TARGET_PPC)592/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC593/// process.594class _LIBUNWIND_HIDDEN Registers_ppc {595public:596Registers_ppc();597Registers_ppc(const void *registers);598599bool validRegister(int num) const;600uint32_t getRegister(int num) const;601void setRegister(int num, uint32_t value);602bool validFloatRegister(int num) const;603double getFloatRegister(int num) const;604void setFloatRegister(int num, double value);605bool validVectorRegister(int num) const;606v128 getVectorRegister(int num) const;607void setVectorRegister(int num, v128 value);608static const char *getRegisterName(int num);609void jumpto();610static constexpr int lastDwarfRegNum() {611return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC;612}613static int getArch() { return REGISTERS_PPC; }614615uint64_t getSP() const { return _registers.__r1; }616void setSP(uint32_t value) { _registers.__r1 = value; }617uint64_t getIP() const { return _registers.__srr0; }618void setIP(uint32_t value) { _registers.__srr0 = value; }619uint64_t getCR() const { return _registers.__cr; }620void setCR(uint32_t value) { _registers.__cr = value; }621uint64_t getLR() const { return _registers.__lr; }622void setLR(uint32_t value) { _registers.__lr = value; }623624private:625struct ppc_thread_state_t {626unsigned int __srr0; /* Instruction address register (PC) */627unsigned int __srr1; /* Machine state register (supervisor) */628unsigned int __r0;629unsigned int __r1;630unsigned int __r2;631unsigned int __r3;632unsigned int __r4;633unsigned int __r5;634unsigned int __r6;635unsigned int __r7;636unsigned int __r8;637unsigned int __r9;638unsigned int __r10;639unsigned int __r11;640unsigned int __r12;641unsigned int __r13;642unsigned int __r14;643unsigned int __r15;644unsigned int __r16;645unsigned int __r17;646unsigned int __r18;647unsigned int __r19;648unsigned int __r20;649unsigned int __r21;650unsigned int __r22;651unsigned int __r23;652unsigned int __r24;653unsigned int __r25;654unsigned int __r26;655unsigned int __r27;656unsigned int __r28;657unsigned int __r29;658unsigned int __r30;659unsigned int __r31;660unsigned int __cr; /* Condition register */661unsigned int __xer; /* User's integer exception register */662unsigned int __lr; /* Link register */663unsigned int __ctr; /* Count register */664unsigned int __mq; /* MQ register (601 only) */665unsigned int __vrsave; /* Vector Save Register */666};667668struct ppc_float_state_t {669double __fpregs[32];670671unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */672unsigned int __fpscr; /* floating point status register */673};674675ppc_thread_state_t _registers;676ppc_float_state_t _floatRegisters;677v128 _vectorRegisters[32]; // offset 424678};679680inline Registers_ppc::Registers_ppc(const void *registers) {681static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),682"ppc registers do not fit into unw_context_t");683memcpy(&_registers, static_cast<const uint8_t *>(registers),684sizeof(_registers));685static_assert(sizeof(ppc_thread_state_t) == 160,686"expected float register offset to be 160");687memcpy(&_floatRegisters,688static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),689sizeof(_floatRegisters));690static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,691"expected vector register offset to be 424 bytes");692memcpy(_vectorRegisters,693static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +694sizeof(ppc_float_state_t),695sizeof(_vectorRegisters));696}697698inline Registers_ppc::Registers_ppc() {699memset(&_registers, 0, sizeof(_registers));700memset(&_floatRegisters, 0, sizeof(_floatRegisters));701memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));702}703704inline bool Registers_ppc::validRegister(int regNum) const {705if (regNum == UNW_REG_IP)706return true;707if (regNum == UNW_REG_SP)708return true;709if (regNum == UNW_PPC_VRSAVE)710return true;711if (regNum < 0)712return false;713if (regNum <= UNW_PPC_R31)714return true;715if (regNum == UNW_PPC_MQ)716return true;717if (regNum == UNW_PPC_LR)718return true;719if (regNum == UNW_PPC_CTR)720return true;721if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))722return true;723return false;724}725726inline uint32_t Registers_ppc::getRegister(int regNum) const {727switch (regNum) {728case UNW_REG_IP:729return _registers.__srr0;730case UNW_REG_SP:731return _registers.__r1;732case UNW_PPC_R0:733return _registers.__r0;734case UNW_PPC_R1:735return _registers.__r1;736case UNW_PPC_R2:737return _registers.__r2;738case UNW_PPC_R3:739return _registers.__r3;740case UNW_PPC_R4:741return _registers.__r4;742case UNW_PPC_R5:743return _registers.__r5;744case UNW_PPC_R6:745return _registers.__r6;746case UNW_PPC_R7:747return _registers.__r7;748case UNW_PPC_R8:749return _registers.__r8;750case UNW_PPC_R9:751return _registers.__r9;752case UNW_PPC_R10:753return _registers.__r10;754case UNW_PPC_R11:755return _registers.__r11;756case UNW_PPC_R12:757return _registers.__r12;758case UNW_PPC_R13:759return _registers.__r13;760case UNW_PPC_R14:761return _registers.__r14;762case UNW_PPC_R15:763return _registers.__r15;764case UNW_PPC_R16:765return _registers.__r16;766case UNW_PPC_R17:767return _registers.__r17;768case UNW_PPC_R18:769return _registers.__r18;770case UNW_PPC_R19:771return _registers.__r19;772case UNW_PPC_R20:773return _registers.__r20;774case UNW_PPC_R21:775return _registers.__r21;776case UNW_PPC_R22:777return _registers.__r22;778case UNW_PPC_R23:779return _registers.__r23;780case UNW_PPC_R24:781return _registers.__r24;782case UNW_PPC_R25:783return _registers.__r25;784case UNW_PPC_R26:785return _registers.__r26;786case UNW_PPC_R27:787return _registers.__r27;788case UNW_PPC_R28:789return _registers.__r28;790case UNW_PPC_R29:791return _registers.__r29;792case UNW_PPC_R30:793return _registers.__r30;794case UNW_PPC_R31:795return _registers.__r31;796case UNW_PPC_LR:797return _registers.__lr;798case UNW_PPC_CR0:799return (_registers.__cr & 0xF0000000);800case UNW_PPC_CR1:801return (_registers.__cr & 0x0F000000);802case UNW_PPC_CR2:803return (_registers.__cr & 0x00F00000);804case UNW_PPC_CR3:805return (_registers.__cr & 0x000F0000);806case UNW_PPC_CR4:807return (_registers.__cr & 0x0000F000);808case UNW_PPC_CR5:809return (_registers.__cr & 0x00000F00);810case UNW_PPC_CR6:811return (_registers.__cr & 0x000000F0);812case UNW_PPC_CR7:813return (_registers.__cr & 0x0000000F);814case UNW_PPC_VRSAVE:815return _registers.__vrsave;816}817_LIBUNWIND_ABORT("unsupported ppc register");818}819820inline void Registers_ppc::setRegister(int regNum, uint32_t value) {821//fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);822switch (regNum) {823case UNW_REG_IP:824_registers.__srr0 = value;825return;826case UNW_REG_SP:827_registers.__r1 = value;828return;829case UNW_PPC_R0:830_registers.__r0 = value;831return;832case UNW_PPC_R1:833_registers.__r1 = value;834return;835case UNW_PPC_R2:836_registers.__r2 = value;837return;838case UNW_PPC_R3:839_registers.__r3 = value;840return;841case UNW_PPC_R4:842_registers.__r4 = value;843return;844case UNW_PPC_R5:845_registers.__r5 = value;846return;847case UNW_PPC_R6:848_registers.__r6 = value;849return;850case UNW_PPC_R7:851_registers.__r7 = value;852return;853case UNW_PPC_R8:854_registers.__r8 = value;855return;856case UNW_PPC_R9:857_registers.__r9 = value;858return;859case UNW_PPC_R10:860_registers.__r10 = value;861return;862case UNW_PPC_R11:863_registers.__r11 = value;864return;865case UNW_PPC_R12:866_registers.__r12 = value;867return;868case UNW_PPC_R13:869_registers.__r13 = value;870return;871case UNW_PPC_R14:872_registers.__r14 = value;873return;874case UNW_PPC_R15:875_registers.__r15 = value;876return;877case UNW_PPC_R16:878_registers.__r16 = value;879return;880case UNW_PPC_R17:881_registers.__r17 = value;882return;883case UNW_PPC_R18:884_registers.__r18 = value;885return;886case UNW_PPC_R19:887_registers.__r19 = value;888return;889case UNW_PPC_R20:890_registers.__r20 = value;891return;892case UNW_PPC_R21:893_registers.__r21 = value;894return;895case UNW_PPC_R22:896_registers.__r22 = value;897return;898case UNW_PPC_R23:899_registers.__r23 = value;900return;901case UNW_PPC_R24:902_registers.__r24 = value;903return;904case UNW_PPC_R25:905_registers.__r25 = value;906return;907case UNW_PPC_R26:908_registers.__r26 = value;909return;910case UNW_PPC_R27:911_registers.__r27 = value;912return;913case UNW_PPC_R28:914_registers.__r28 = value;915return;916case UNW_PPC_R29:917_registers.__r29 = value;918return;919case UNW_PPC_R30:920_registers.__r30 = value;921return;922case UNW_PPC_R31:923_registers.__r31 = value;924return;925case UNW_PPC_MQ:926_registers.__mq = value;927return;928case UNW_PPC_LR:929_registers.__lr = value;930return;931case UNW_PPC_CTR:932_registers.__ctr = value;933return;934case UNW_PPC_CR0:935_registers.__cr &= 0x0FFFFFFF;936_registers.__cr |= (value & 0xF0000000);937return;938case UNW_PPC_CR1:939_registers.__cr &= 0xF0FFFFFF;940_registers.__cr |= (value & 0x0F000000);941return;942case UNW_PPC_CR2:943_registers.__cr &= 0xFF0FFFFF;944_registers.__cr |= (value & 0x00F00000);945return;946case UNW_PPC_CR3:947_registers.__cr &= 0xFFF0FFFF;948_registers.__cr |= (value & 0x000F0000);949return;950case UNW_PPC_CR4:951_registers.__cr &= 0xFFFF0FFF;952_registers.__cr |= (value & 0x0000F000);953return;954case UNW_PPC_CR5:955_registers.__cr &= 0xFFFFF0FF;956_registers.__cr |= (value & 0x00000F00);957return;958case UNW_PPC_CR6:959_registers.__cr &= 0xFFFFFF0F;960_registers.__cr |= (value & 0x000000F0);961return;962case UNW_PPC_CR7:963_registers.__cr &= 0xFFFFFFF0;964_registers.__cr |= (value & 0x0000000F);965return;966case UNW_PPC_VRSAVE:967_registers.__vrsave = value;968return;969// not saved970return;971case UNW_PPC_XER:972_registers.__xer = value;973return;974case UNW_PPC_AP:975case UNW_PPC_VSCR:976case UNW_PPC_SPEFSCR:977// not saved978return;979}980_LIBUNWIND_ABORT("unsupported ppc register");981}982983inline bool Registers_ppc::validFloatRegister(int regNum) const {984if (regNum < UNW_PPC_F0)985return false;986if (regNum > UNW_PPC_F31)987return false;988return true;989}990991inline double Registers_ppc::getFloatRegister(int regNum) const {992assert(validFloatRegister(regNum));993return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];994}995996inline void Registers_ppc::setFloatRegister(int regNum, double value) {997assert(validFloatRegister(regNum));998_floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;999}10001001inline bool Registers_ppc::validVectorRegister(int regNum) const {1002if (regNum < UNW_PPC_V0)1003return false;1004if (regNum > UNW_PPC_V31)1005return false;1006return true;1007}10081009inline v128 Registers_ppc::getVectorRegister(int regNum) const {1010assert(validVectorRegister(regNum));1011v128 result = _vectorRegisters[regNum - UNW_PPC_V0];1012return result;1013}10141015inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {1016assert(validVectorRegister(regNum));1017_vectorRegisters[regNum - UNW_PPC_V0] = value;1018}10191020inline const char *Registers_ppc::getRegisterName(int regNum) {1021switch (regNum) {1022case UNW_REG_IP:1023return "ip";1024case UNW_REG_SP:1025return "sp";1026case UNW_PPC_R0:1027return "r0";1028case UNW_PPC_R1:1029return "r1";1030case UNW_PPC_R2:1031return "r2";1032case UNW_PPC_R3:1033return "r3";1034case UNW_PPC_R4:1035return "r4";1036case UNW_PPC_R5:1037return "r5";1038case UNW_PPC_R6:1039return "r6";1040case UNW_PPC_R7:1041return "r7";1042case UNW_PPC_R8:1043return "r8";1044case UNW_PPC_R9:1045return "r9";1046case UNW_PPC_R10:1047return "r10";1048case UNW_PPC_R11:1049return "r11";1050case UNW_PPC_R12:1051return "r12";1052case UNW_PPC_R13:1053return "r13";1054case UNW_PPC_R14:1055return "r14";1056case UNW_PPC_R15:1057return "r15";1058case UNW_PPC_R16:1059return "r16";1060case UNW_PPC_R17:1061return "r17";1062case UNW_PPC_R18:1063return "r18";1064case UNW_PPC_R19:1065return "r19";1066case UNW_PPC_R20:1067return "r20";1068case UNW_PPC_R21:1069return "r21";1070case UNW_PPC_R22:1071return "r22";1072case UNW_PPC_R23:1073return "r23";1074case UNW_PPC_R24:1075return "r24";1076case UNW_PPC_R25:1077return "r25";1078case UNW_PPC_R26:1079return "r26";1080case UNW_PPC_R27:1081return "r27";1082case UNW_PPC_R28:1083return "r28";1084case UNW_PPC_R29:1085return "r29";1086case UNW_PPC_R30:1087return "r30";1088case UNW_PPC_R31:1089return "r31";1090case UNW_PPC_F0:1091return "fp0";1092case UNW_PPC_F1:1093return "fp1";1094case UNW_PPC_F2:1095return "fp2";1096case UNW_PPC_F3:1097return "fp3";1098case UNW_PPC_F4:1099return "fp4";1100case UNW_PPC_F5:1101return "fp5";1102case UNW_PPC_F6:1103return "fp6";1104case UNW_PPC_F7:1105return "fp7";1106case UNW_PPC_F8:1107return "fp8";1108case UNW_PPC_F9:1109return "fp9";1110case UNW_PPC_F10:1111return "fp10";1112case UNW_PPC_F11:1113return "fp11";1114case UNW_PPC_F12:1115return "fp12";1116case UNW_PPC_F13:1117return "fp13";1118case UNW_PPC_F14:1119return "fp14";1120case UNW_PPC_F15:1121return "fp15";1122case UNW_PPC_F16:1123return "fp16";1124case UNW_PPC_F17:1125return "fp17";1126case UNW_PPC_F18:1127return "fp18";1128case UNW_PPC_F19:1129return "fp19";1130case UNW_PPC_F20:1131return "fp20";1132case UNW_PPC_F21:1133return "fp21";1134case UNW_PPC_F22:1135return "fp22";1136case UNW_PPC_F23:1137return "fp23";1138case UNW_PPC_F24:1139return "fp24";1140case UNW_PPC_F25:1141return "fp25";1142case UNW_PPC_F26:1143return "fp26";1144case UNW_PPC_F27:1145return "fp27";1146case UNW_PPC_F28:1147return "fp28";1148case UNW_PPC_F29:1149return "fp29";1150case UNW_PPC_F30:1151return "fp30";1152case UNW_PPC_F31:1153return "fp31";1154case UNW_PPC_LR:1155return "lr";1156default:1157return "unknown register";1158}11591160}1161#endif // _LIBUNWIND_TARGET_PPC11621163#if defined(_LIBUNWIND_TARGET_PPC64)1164/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC1165/// process.1166class _LIBUNWIND_HIDDEN Registers_ppc64 {1167public:1168Registers_ppc64();1169Registers_ppc64(const void *registers);11701171bool validRegister(int num) const;1172uint64_t getRegister(int num) const;1173void setRegister(int num, uint64_t value);1174bool validFloatRegister(int num) const;1175double getFloatRegister(int num) const;1176void setFloatRegister(int num, double value);1177bool validVectorRegister(int num) const;1178v128 getVectorRegister(int num) const;1179void setVectorRegister(int num, v128 value);1180static const char *getRegisterName(int num);1181void jumpto();1182static constexpr int lastDwarfRegNum() {1183return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64;1184}1185static int getArch() { return REGISTERS_PPC64; }11861187uint64_t getSP() const { return _registers.__r1; }1188void setSP(uint64_t value) { _registers.__r1 = value; }1189uint64_t getIP() const { return _registers.__srr0; }1190void setIP(uint64_t value) { _registers.__srr0 = value; }1191uint64_t getCR() const { return _registers.__cr; }1192void setCR(uint64_t value) { _registers.__cr = value; }1193uint64_t getLR() const { return _registers.__lr; }1194void setLR(uint64_t value) { _registers.__lr = value; }11951196private:1197struct ppc64_thread_state_t {1198uint64_t __srr0; // Instruction address register (PC)1199uint64_t __srr1; // Machine state register (supervisor)1200uint64_t __r0;1201uint64_t __r1;1202uint64_t __r2;1203uint64_t __r3;1204uint64_t __r4;1205uint64_t __r5;1206uint64_t __r6;1207uint64_t __r7;1208uint64_t __r8;1209uint64_t __r9;1210uint64_t __r10;1211uint64_t __r11;1212uint64_t __r12;1213uint64_t __r13;1214uint64_t __r14;1215uint64_t __r15;1216uint64_t __r16;1217uint64_t __r17;1218uint64_t __r18;1219uint64_t __r19;1220uint64_t __r20;1221uint64_t __r21;1222uint64_t __r22;1223uint64_t __r23;1224uint64_t __r24;1225uint64_t __r25;1226uint64_t __r26;1227uint64_t __r27;1228uint64_t __r28;1229uint64_t __r29;1230uint64_t __r30;1231uint64_t __r31;1232uint64_t __cr; // Condition register1233uint64_t __xer; // User's integer exception register1234uint64_t __lr; // Link register1235uint64_t __ctr; // Count register1236uint64_t __vrsave; // Vector Save Register1237};12381239union ppc64_vsr_t {1240struct asfloat_s {1241double f;1242uint64_t v2;1243} asfloat;1244v128 v;1245};12461247ppc64_thread_state_t _registers;1248ppc64_vsr_t _vectorScalarRegisters[64];12491250static int getVectorRegNum(int num);1251};12521253inline Registers_ppc64::Registers_ppc64(const void *registers) {1254static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),1255"ppc64 registers do not fit into unw_context_t");1256memcpy(&_registers, static_cast<const uint8_t *>(registers),1257sizeof(_registers));1258static_assert(sizeof(_registers) == 312,1259"expected vector scalar register offset to be 312");1260memcpy(&_vectorScalarRegisters,1261static_cast<const uint8_t *>(registers) + sizeof(_registers),1262sizeof(_vectorScalarRegisters));1263static_assert(sizeof(_registers) +1264sizeof(_vectorScalarRegisters) == 1336,1265"expected vector register offset to be 1336 bytes");1266}12671268inline Registers_ppc64::Registers_ppc64() {1269memset(&_registers, 0, sizeof(_registers));1270memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));1271}12721273inline bool Registers_ppc64::validRegister(int regNum) const {1274switch (regNum) {1275case UNW_REG_IP:1276case UNW_REG_SP:1277case UNW_PPC64_XER:1278case UNW_PPC64_LR:1279case UNW_PPC64_CTR:1280case UNW_PPC64_VRSAVE:1281return true;1282}12831284if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)1285return true;1286if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)1287return true;12881289return false;1290}12911292inline uint64_t Registers_ppc64::getRegister(int regNum) const {1293switch (regNum) {1294case UNW_REG_IP:1295return _registers.__srr0;1296case UNW_PPC64_R0:1297return _registers.__r0;1298case UNW_PPC64_R1:1299case UNW_REG_SP:1300return _registers.__r1;1301case UNW_PPC64_R2:1302return _registers.__r2;1303case UNW_PPC64_R3:1304return _registers.__r3;1305case UNW_PPC64_R4:1306return _registers.__r4;1307case UNW_PPC64_R5:1308return _registers.__r5;1309case UNW_PPC64_R6:1310return _registers.__r6;1311case UNW_PPC64_R7:1312return _registers.__r7;1313case UNW_PPC64_R8:1314return _registers.__r8;1315case UNW_PPC64_R9:1316return _registers.__r9;1317case UNW_PPC64_R10:1318return _registers.__r10;1319case UNW_PPC64_R11:1320return _registers.__r11;1321case UNW_PPC64_R12:1322return _registers.__r12;1323case UNW_PPC64_R13:1324return _registers.__r13;1325case UNW_PPC64_R14:1326return _registers.__r14;1327case UNW_PPC64_R15:1328return _registers.__r15;1329case UNW_PPC64_R16:1330return _registers.__r16;1331case UNW_PPC64_R17:1332return _registers.__r17;1333case UNW_PPC64_R18:1334return _registers.__r18;1335case UNW_PPC64_R19:1336return _registers.__r19;1337case UNW_PPC64_R20:1338return _registers.__r20;1339case UNW_PPC64_R21:1340return _registers.__r21;1341case UNW_PPC64_R22:1342return _registers.__r22;1343case UNW_PPC64_R23:1344return _registers.__r23;1345case UNW_PPC64_R24:1346return _registers.__r24;1347case UNW_PPC64_R25:1348return _registers.__r25;1349case UNW_PPC64_R26:1350return _registers.__r26;1351case UNW_PPC64_R27:1352return _registers.__r27;1353case UNW_PPC64_R28:1354return _registers.__r28;1355case UNW_PPC64_R29:1356return _registers.__r29;1357case UNW_PPC64_R30:1358return _registers.__r30;1359case UNW_PPC64_R31:1360return _registers.__r31;1361case UNW_PPC64_CR0:1362return (_registers.__cr & 0xF0000000);1363case UNW_PPC64_CR1:1364return (_registers.__cr & 0x0F000000);1365case UNW_PPC64_CR2:1366return (_registers.__cr & 0x00F00000);1367case UNW_PPC64_CR3:1368return (_registers.__cr & 0x000F0000);1369case UNW_PPC64_CR4:1370return (_registers.__cr & 0x0000F000);1371case UNW_PPC64_CR5:1372return (_registers.__cr & 0x00000F00);1373case UNW_PPC64_CR6:1374return (_registers.__cr & 0x000000F0);1375case UNW_PPC64_CR7:1376return (_registers.__cr & 0x0000000F);1377case UNW_PPC64_XER:1378return _registers.__xer;1379case UNW_PPC64_LR:1380return _registers.__lr;1381case UNW_PPC64_CTR:1382return _registers.__ctr;1383case UNW_PPC64_VRSAVE:1384return _registers.__vrsave;1385}1386_LIBUNWIND_ABORT("unsupported ppc64 register");1387}13881389inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {1390switch (regNum) {1391case UNW_REG_IP:1392_registers.__srr0 = value;1393return;1394case UNW_PPC64_R0:1395_registers.__r0 = value;1396return;1397case UNW_PPC64_R1:1398case UNW_REG_SP:1399_registers.__r1 = value;1400return;1401case UNW_PPC64_R2:1402_registers.__r2 = value;1403return;1404case UNW_PPC64_R3:1405_registers.__r3 = value;1406return;1407case UNW_PPC64_R4:1408_registers.__r4 = value;1409return;1410case UNW_PPC64_R5:1411_registers.__r5 = value;1412return;1413case UNW_PPC64_R6:1414_registers.__r6 = value;1415return;1416case UNW_PPC64_R7:1417_registers.__r7 = value;1418return;1419case UNW_PPC64_R8:1420_registers.__r8 = value;1421return;1422case UNW_PPC64_R9:1423_registers.__r9 = value;1424return;1425case UNW_PPC64_R10:1426_registers.__r10 = value;1427return;1428case UNW_PPC64_R11:1429_registers.__r11 = value;1430return;1431case UNW_PPC64_R12:1432_registers.__r12 = value;1433return;1434case UNW_PPC64_R13:1435_registers.__r13 = value;1436return;1437case UNW_PPC64_R14:1438_registers.__r14 = value;1439return;1440case UNW_PPC64_R15:1441_registers.__r15 = value;1442return;1443case UNW_PPC64_R16:1444_registers.__r16 = value;1445return;1446case UNW_PPC64_R17:1447_registers.__r17 = value;1448return;1449case UNW_PPC64_R18:1450_registers.__r18 = value;1451return;1452case UNW_PPC64_R19:1453_registers.__r19 = value;1454return;1455case UNW_PPC64_R20:1456_registers.__r20 = value;1457return;1458case UNW_PPC64_R21:1459_registers.__r21 = value;1460return;1461case UNW_PPC64_R22:1462_registers.__r22 = value;1463return;1464case UNW_PPC64_R23:1465_registers.__r23 = value;1466return;1467case UNW_PPC64_R24:1468_registers.__r24 = value;1469return;1470case UNW_PPC64_R25:1471_registers.__r25 = value;1472return;1473case UNW_PPC64_R26:1474_registers.__r26 = value;1475return;1476case UNW_PPC64_R27:1477_registers.__r27 = value;1478return;1479case UNW_PPC64_R28:1480_registers.__r28 = value;1481return;1482case UNW_PPC64_R29:1483_registers.__r29 = value;1484return;1485case UNW_PPC64_R30:1486_registers.__r30 = value;1487return;1488case UNW_PPC64_R31:1489_registers.__r31 = value;1490return;1491case UNW_PPC64_CR0:1492_registers.__cr &= 0x0FFFFFFF;1493_registers.__cr |= (value & 0xF0000000);1494return;1495case UNW_PPC64_CR1:1496_registers.__cr &= 0xF0FFFFFF;1497_registers.__cr |= (value & 0x0F000000);1498return;1499case UNW_PPC64_CR2:1500_registers.__cr &= 0xFF0FFFFF;1501_registers.__cr |= (value & 0x00F00000);1502return;1503case UNW_PPC64_CR3:1504_registers.__cr &= 0xFFF0FFFF;1505_registers.__cr |= (value & 0x000F0000);1506return;1507case UNW_PPC64_CR4:1508_registers.__cr &= 0xFFFF0FFF;1509_registers.__cr |= (value & 0x0000F000);1510return;1511case UNW_PPC64_CR5:1512_registers.__cr &= 0xFFFFF0FF;1513_registers.__cr |= (value & 0x00000F00);1514return;1515case UNW_PPC64_CR6:1516_registers.__cr &= 0xFFFFFF0F;1517_registers.__cr |= (value & 0x000000F0);1518return;1519case UNW_PPC64_CR7:1520_registers.__cr &= 0xFFFFFFF0;1521_registers.__cr |= (value & 0x0000000F);1522return;1523case UNW_PPC64_XER:1524_registers.__xer = value;1525return;1526case UNW_PPC64_LR:1527_registers.__lr = value;1528return;1529case UNW_PPC64_CTR:1530_registers.__ctr = value;1531return;1532case UNW_PPC64_VRSAVE:1533_registers.__vrsave = value;1534return;1535}1536_LIBUNWIND_ABORT("unsupported ppc64 register");1537}15381539inline bool Registers_ppc64::validFloatRegister(int regNum) const {1540return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;1541}15421543inline double Registers_ppc64::getFloatRegister(int regNum) const {1544assert(validFloatRegister(regNum));1545return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;1546}15471548inline void Registers_ppc64::setFloatRegister(int regNum, double value) {1549assert(validFloatRegister(regNum));1550_vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;1551}15521553inline bool Registers_ppc64::validVectorRegister(int regNum) const {1554#if defined(__VSX__)1555if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)1556return true;1557if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)1558return true;1559#elif defined(__ALTIVEC__)1560if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)1561return true;1562#endif1563return false;1564}15651566inline int Registers_ppc64::getVectorRegNum(int num)1567{1568if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)1569return num - UNW_PPC64_VS0;1570else1571return num - UNW_PPC64_VS32 + 32;1572}15731574inline v128 Registers_ppc64::getVectorRegister(int regNum) const {1575assert(validVectorRegister(regNum));1576return _vectorScalarRegisters[getVectorRegNum(regNum)].v;1577}15781579inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {1580assert(validVectorRegister(regNum));1581_vectorScalarRegisters[getVectorRegNum(regNum)].v = value;1582}15831584inline const char *Registers_ppc64::getRegisterName(int regNum) {1585switch (regNum) {1586case UNW_REG_IP:1587return "ip";1588case UNW_REG_SP:1589return "sp";1590case UNW_PPC64_R0:1591return "r0";1592case UNW_PPC64_R1:1593return "r1";1594case UNW_PPC64_R2:1595return "r2";1596case UNW_PPC64_R3:1597return "r3";1598case UNW_PPC64_R4:1599return "r4";1600case UNW_PPC64_R5:1601return "r5";1602case UNW_PPC64_R6:1603return "r6";1604case UNW_PPC64_R7:1605return "r7";1606case UNW_PPC64_R8:1607return "r8";1608case UNW_PPC64_R9:1609return "r9";1610case UNW_PPC64_R10:1611return "r10";1612case UNW_PPC64_R11:1613return "r11";1614case UNW_PPC64_R12:1615return "r12";1616case UNW_PPC64_R13:1617return "r13";1618case UNW_PPC64_R14:1619return "r14";1620case UNW_PPC64_R15:1621return "r15";1622case UNW_PPC64_R16:1623return "r16";1624case UNW_PPC64_R17:1625return "r17";1626case UNW_PPC64_R18:1627return "r18";1628case UNW_PPC64_R19:1629return "r19";1630case UNW_PPC64_R20:1631return "r20";1632case UNW_PPC64_R21:1633return "r21";1634case UNW_PPC64_R22:1635return "r22";1636case UNW_PPC64_R23:1637return "r23";1638case UNW_PPC64_R24:1639return "r24";1640case UNW_PPC64_R25:1641return "r25";1642case UNW_PPC64_R26:1643return "r26";1644case UNW_PPC64_R27:1645return "r27";1646case UNW_PPC64_R28:1647return "r28";1648case UNW_PPC64_R29:1649return "r29";1650case UNW_PPC64_R30:1651return "r30";1652case UNW_PPC64_R31:1653return "r31";1654case UNW_PPC64_CR0:1655return "cr0";1656case UNW_PPC64_CR1:1657return "cr1";1658case UNW_PPC64_CR2:1659return "cr2";1660case UNW_PPC64_CR3:1661return "cr3";1662case UNW_PPC64_CR4:1663return "cr4";1664case UNW_PPC64_CR5:1665return "cr5";1666case UNW_PPC64_CR6:1667return "cr6";1668case UNW_PPC64_CR7:1669return "cr7";1670case UNW_PPC64_XER:1671return "xer";1672case UNW_PPC64_LR:1673return "lr";1674case UNW_PPC64_CTR:1675return "ctr";1676case UNW_PPC64_VRSAVE:1677return "vrsave";1678case UNW_PPC64_F0:1679return "fp0";1680case UNW_PPC64_F1:1681return "fp1";1682case UNW_PPC64_F2:1683return "fp2";1684case UNW_PPC64_F3:1685return "fp3";1686case UNW_PPC64_F4:1687return "fp4";1688case UNW_PPC64_F5:1689return "fp5";1690case UNW_PPC64_F6:1691return "fp6";1692case UNW_PPC64_F7:1693return "fp7";1694case UNW_PPC64_F8:1695return "fp8";1696case UNW_PPC64_F9:1697return "fp9";1698case UNW_PPC64_F10:1699return "fp10";1700case UNW_PPC64_F11:1701return "fp11";1702case UNW_PPC64_F12:1703return "fp12";1704case UNW_PPC64_F13:1705return "fp13";1706case UNW_PPC64_F14:1707return "fp14";1708case UNW_PPC64_F15:1709return "fp15";1710case UNW_PPC64_F16:1711return "fp16";1712case UNW_PPC64_F17:1713return "fp17";1714case UNW_PPC64_F18:1715return "fp18";1716case UNW_PPC64_F19:1717return "fp19";1718case UNW_PPC64_F20:1719return "fp20";1720case UNW_PPC64_F21:1721return "fp21";1722case UNW_PPC64_F22:1723return "fp22";1724case UNW_PPC64_F23:1725return "fp23";1726case UNW_PPC64_F24:1727return "fp24";1728case UNW_PPC64_F25:1729return "fp25";1730case UNW_PPC64_F26:1731return "fp26";1732case UNW_PPC64_F27:1733return "fp27";1734case UNW_PPC64_F28:1735return "fp28";1736case UNW_PPC64_F29:1737return "fp29";1738case UNW_PPC64_F30:1739return "fp30";1740case UNW_PPC64_F31:1741return "fp31";1742case UNW_PPC64_V0:1743return "v0";1744case UNW_PPC64_V1:1745return "v1";1746case UNW_PPC64_V2:1747return "v2";1748case UNW_PPC64_V3:1749return "v3";1750case UNW_PPC64_V4:1751return "v4";1752case UNW_PPC64_V5:1753return "v5";1754case UNW_PPC64_V6:1755return "v6";1756case UNW_PPC64_V7:1757return "v7";1758case UNW_PPC64_V8:1759return "v8";1760case UNW_PPC64_V9:1761return "v9";1762case UNW_PPC64_V10:1763return "v10";1764case UNW_PPC64_V11:1765return "v11";1766case UNW_PPC64_V12:1767return "v12";1768case UNW_PPC64_V13:1769return "v13";1770case UNW_PPC64_V14:1771return "v14";1772case UNW_PPC64_V15:1773return "v15";1774case UNW_PPC64_V16:1775return "v16";1776case UNW_PPC64_V17:1777return "v17";1778case UNW_PPC64_V18:1779return "v18";1780case UNW_PPC64_V19:1781return "v19";1782case UNW_PPC64_V20:1783return "v20";1784case UNW_PPC64_V21:1785return "v21";1786case UNW_PPC64_V22:1787return "v22";1788case UNW_PPC64_V23:1789return "v23";1790case UNW_PPC64_V24:1791return "v24";1792case UNW_PPC64_V25:1793return "v25";1794case UNW_PPC64_V26:1795return "v26";1796case UNW_PPC64_V27:1797return "v27";1798case UNW_PPC64_V28:1799return "v28";1800case UNW_PPC64_V29:1801return "v29";1802case UNW_PPC64_V30:1803return "v30";1804case UNW_PPC64_V31:1805return "v31";1806}1807return "unknown register";1808}1809#endif // _LIBUNWIND_TARGET_PPC64181018111812#if defined(_LIBUNWIND_TARGET_AARCH64)1813/// Registers_arm64 holds the register state of a thread in a 64-bit arm1814/// process.1815class _LIBUNWIND_HIDDEN Registers_arm64;1816extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);18171818#if defined(_LIBUNWIND_USE_GCS)1819extern "C" void *__libunwind_cet_get_jump_target() {1820return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto);1821}1822#endif18231824class _LIBUNWIND_HIDDEN Registers_arm64 {1825public:1826Registers_arm64();1827Registers_arm64(const void *registers);18281829bool validRegister(int num) const;1830uint64_t getRegister(int num) const;1831void setRegister(int num, uint64_t value);1832bool validFloatRegister(int num) const;1833double getFloatRegister(int num) const;1834void setFloatRegister(int num, double value);1835bool validVectorRegister(int num) const;1836v128 getVectorRegister(int num) const;1837void setVectorRegister(int num, v128 value);1838static const char *getRegisterName(int num);1839void jumpto() { __libunwind_Registers_arm64_jumpto(this); }1840static constexpr int lastDwarfRegNum() {1841return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;1842}1843static int getArch() { return REGISTERS_ARM64; }18441845uint64_t getSP() const { return _registers.__sp; }1846void setSP(uint64_t value) { _registers.__sp = value; }1847uint64_t getIP() const { return _registers.__pc; }1848void setIP(uint64_t value) { _registers.__pc = value; }1849uint64_t getFP() const { return _registers.__fp; }1850void setFP(uint64_t value) { _registers.__fp = value; }18511852private:1853struct GPRs {1854uint64_t __x[29]; // x0-x281855uint64_t __fp; // Frame pointer x291856uint64_t __lr; // Link register x301857uint64_t __sp; // Stack pointer x311858uint64_t __pc; // Program counter1859uint64_t __ra_sign_state; // RA sign state register1860};18611862GPRs _registers;1863double _vectorHalfRegisters[32];1864// Currently only the lower double in 128-bit vectore registers1865// is perserved during unwinding. We could define new register1866// numbers (> 96) which mean whole vector registers, then this1867// struct would need to change to contain whole vector registers.1868};18691870inline Registers_arm64::Registers_arm64(const void *registers) {1871static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),1872"arm64 registers do not fit into unw_context_t");1873memcpy(&_registers, registers, sizeof(_registers));1874static_assert(sizeof(GPRs) == 0x110,1875"expected VFP registers to be at offset 272");1876memcpy(_vectorHalfRegisters,1877static_cast<const uint8_t *>(registers) + sizeof(GPRs),1878sizeof(_vectorHalfRegisters));1879}18801881inline Registers_arm64::Registers_arm64() {1882memset(&_registers, 0, sizeof(_registers));1883memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));1884}18851886inline bool Registers_arm64::validRegister(int regNum) const {1887if (regNum == UNW_REG_IP)1888return true;1889if (regNum == UNW_REG_SP)1890return true;1891if (regNum < 0)1892return false;1893if (regNum > 95)1894return false;1895if (regNum == UNW_AARCH64_RA_SIGN_STATE)1896return true;1897if ((regNum > 32) && (regNum < 64))1898return false;1899return true;1900}19011902inline uint64_t Registers_arm64::getRegister(int regNum) const {1903if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)1904return _registers.__pc;1905if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)1906return _registers.__sp;1907if (regNum == UNW_AARCH64_RA_SIGN_STATE)1908return _registers.__ra_sign_state;1909if (regNum == UNW_AARCH64_FP)1910return _registers.__fp;1911if (regNum == UNW_AARCH64_LR)1912return _registers.__lr;1913if ((regNum >= 0) && (regNum < 29))1914return _registers.__x[regNum];1915_LIBUNWIND_ABORT("unsupported arm64 register");1916}19171918inline void Registers_arm64::setRegister(int regNum, uint64_t value) {1919if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)1920_registers.__pc = value;1921else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)1922_registers.__sp = value;1923else if (regNum == UNW_AARCH64_RA_SIGN_STATE)1924_registers.__ra_sign_state = value;1925else if (regNum == UNW_AARCH64_FP)1926_registers.__fp = value;1927else if (regNum == UNW_AARCH64_LR)1928_registers.__lr = value;1929else if ((regNum >= 0) && (regNum < 29))1930_registers.__x[regNum] = value;1931else1932_LIBUNWIND_ABORT("unsupported arm64 register");1933}19341935inline const char *Registers_arm64::getRegisterName(int regNum) {1936switch (regNum) {1937case UNW_REG_IP:1938return "pc";1939case UNW_REG_SP:1940return "sp";1941case UNW_AARCH64_X0:1942return "x0";1943case UNW_AARCH64_X1:1944return "x1";1945case UNW_AARCH64_X2:1946return "x2";1947case UNW_AARCH64_X3:1948return "x3";1949case UNW_AARCH64_X4:1950return "x4";1951case UNW_AARCH64_X5:1952return "x5";1953case UNW_AARCH64_X6:1954return "x6";1955case UNW_AARCH64_X7:1956return "x7";1957case UNW_AARCH64_X8:1958return "x8";1959case UNW_AARCH64_X9:1960return "x9";1961case UNW_AARCH64_X10:1962return "x10";1963case UNW_AARCH64_X11:1964return "x11";1965case UNW_AARCH64_X12:1966return "x12";1967case UNW_AARCH64_X13:1968return "x13";1969case UNW_AARCH64_X14:1970return "x14";1971case UNW_AARCH64_X15:1972return "x15";1973case UNW_AARCH64_X16:1974return "x16";1975case UNW_AARCH64_X17:1976return "x17";1977case UNW_AARCH64_X18:1978return "x18";1979case UNW_AARCH64_X19:1980return "x19";1981case UNW_AARCH64_X20:1982return "x20";1983case UNW_AARCH64_X21:1984return "x21";1985case UNW_AARCH64_X22:1986return "x22";1987case UNW_AARCH64_X23:1988return "x23";1989case UNW_AARCH64_X24:1990return "x24";1991case UNW_AARCH64_X25:1992return "x25";1993case UNW_AARCH64_X26:1994return "x26";1995case UNW_AARCH64_X27:1996return "x27";1997case UNW_AARCH64_X28:1998return "x28";1999case UNW_AARCH64_FP:2000return "fp";2001case UNW_AARCH64_LR:2002return "lr";2003case UNW_AARCH64_SP:2004return "sp";2005case UNW_AARCH64_PC:2006return "pc";2007case UNW_AARCH64_V0:2008return "d0";2009case UNW_AARCH64_V1:2010return "d1";2011case UNW_AARCH64_V2:2012return "d2";2013case UNW_AARCH64_V3:2014return "d3";2015case UNW_AARCH64_V4:2016return "d4";2017case UNW_AARCH64_V5:2018return "d5";2019case UNW_AARCH64_V6:2020return "d6";2021case UNW_AARCH64_V7:2022return "d7";2023case UNW_AARCH64_V8:2024return "d8";2025case UNW_AARCH64_V9:2026return "d9";2027case UNW_AARCH64_V10:2028return "d10";2029case UNW_AARCH64_V11:2030return "d11";2031case UNW_AARCH64_V12:2032return "d12";2033case UNW_AARCH64_V13:2034return "d13";2035case UNW_AARCH64_V14:2036return "d14";2037case UNW_AARCH64_V15:2038return "d15";2039case UNW_AARCH64_V16:2040return "d16";2041case UNW_AARCH64_V17:2042return "d17";2043case UNW_AARCH64_V18:2044return "d18";2045case UNW_AARCH64_V19:2046return "d19";2047case UNW_AARCH64_V20:2048return "d20";2049case UNW_AARCH64_V21:2050return "d21";2051case UNW_AARCH64_V22:2052return "d22";2053case UNW_AARCH64_V23:2054return "d23";2055case UNW_AARCH64_V24:2056return "d24";2057case UNW_AARCH64_V25:2058return "d25";2059case UNW_AARCH64_V26:2060return "d26";2061case UNW_AARCH64_V27:2062return "d27";2063case UNW_AARCH64_V28:2064return "d28";2065case UNW_AARCH64_V29:2066return "d29";2067case UNW_AARCH64_V30:2068return "d30";2069case UNW_AARCH64_V31:2070return "d31";2071default:2072return "unknown register";2073}2074}20752076inline bool Registers_arm64::validFloatRegister(int regNum) const {2077if (regNum < UNW_AARCH64_V0)2078return false;2079if (regNum > UNW_AARCH64_V31)2080return false;2081return true;2082}20832084inline double Registers_arm64::getFloatRegister(int regNum) const {2085assert(validFloatRegister(regNum));2086return _vectorHalfRegisters[regNum - UNW_AARCH64_V0];2087}20882089inline void Registers_arm64::setFloatRegister(int regNum, double value) {2090assert(validFloatRegister(regNum));2091_vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value;2092}20932094inline bool Registers_arm64::validVectorRegister(int) const {2095return false;2096}20972098inline v128 Registers_arm64::getVectorRegister(int) const {2099_LIBUNWIND_ABORT("no arm64 vector register support yet");2100}21012102inline void Registers_arm64::setVectorRegister(int, v128) {2103_LIBUNWIND_ABORT("no arm64 vector register support yet");2104}2105#endif // _LIBUNWIND_TARGET_AARCH6421062107#if defined(_LIBUNWIND_TARGET_ARM)2108/// Registers_arm holds the register state of a thread in a 32-bit arm2109/// process.2110///2111/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,2112/// this uses more memory than required.2113class _LIBUNWIND_HIDDEN Registers_arm {2114public:2115Registers_arm();2116Registers_arm(const void *registers);21172118bool validRegister(int num) const;2119uint32_t getRegister(int num) const;2120void setRegister(int num, uint32_t value);2121bool validFloatRegister(int num) const;2122unw_fpreg_t getFloatRegister(int num);2123void setFloatRegister(int num, unw_fpreg_t value);2124bool validVectorRegister(int num) const;2125v128 getVectorRegister(int num) const;2126void setVectorRegister(int num, v128 value);2127static const char *getRegisterName(int num);2128void jumpto() {2129restoreSavedFloatRegisters();2130restoreCoreAndJumpTo();2131}2132static constexpr int lastDwarfRegNum() {2133return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM;2134}2135static int getArch() { return REGISTERS_ARM; }21362137uint32_t getSP() const { return _registers.__sp; }2138void setSP(uint32_t value) { _registers.__sp = value; }2139uint32_t getIP() const { return _registers.__pc; }2140void setIP(uint32_t value) { _registers.__pc = value; }21412142void saveVFPAsX() {2143assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);2144_use_X_for_vfp_save = true;2145}21462147void restoreSavedFloatRegisters() {2148if (_saved_vfp_d0_d15) {2149if (_use_X_for_vfp_save)2150restoreVFPWithFLDMX(_vfp_d0_d15_pad);2151else2152restoreVFPWithFLDMD(_vfp_d0_d15_pad);2153}2154if (_saved_vfp_d16_d31)2155restoreVFPv3(_vfp_d16_d31);2156#if defined(__ARM_WMMX)2157if (_saved_iwmmx)2158restoreiWMMX(_iwmmx);2159if (_saved_iwmmx_control)2160restoreiWMMXControl(_iwmmx_control);2161#endif2162}21632164private:2165struct GPRs {2166uint32_t __r[13]; // r0-r122167uint32_t __sp; // Stack pointer r132168uint32_t __lr; // Link register r142169uint32_t __pc; // Program counter r152170};21712172struct PseudoRegisters {2173uint32_t __pac; // Return Authentication Code (PAC)2174};21752176static void saveVFPWithFSTMD(void*);2177static void saveVFPWithFSTMX(void*);2178static void saveVFPv3(void*);2179static void restoreVFPWithFLDMD(void*);2180static void restoreVFPWithFLDMX(void*);2181static void restoreVFPv3(void*);2182#if defined(__ARM_WMMX)2183static void saveiWMMX(void*);2184static void saveiWMMXControl(uint32_t*);2185static void restoreiWMMX(void*);2186static void restoreiWMMXControl(uint32_t*);2187#endif2188void restoreCoreAndJumpTo();21892190// ARM registers2191GPRs _registers;2192PseudoRegisters _pseudo_registers;21932194// We save floating point registers lazily because we can't know ahead of2195// time which ones are used. See EHABI #4.7.21962197// Whether D0-D15 are saved in the FTSMX instead of FSTMD format.2198//2199// See EHABI #7.5 that explains how matching instruction sequences for load2200// and store need to be used to correctly restore the exact register bits.2201bool _use_X_for_vfp_save;2202// Whether VFP D0-D15 are saved.2203bool _saved_vfp_d0_d15;2204// Whether VFPv3 D16-D31 are saved.2205bool _saved_vfp_d16_d31;2206// VFP registers D0-D15, + padding if saved using FSTMX2207unw_fpreg_t _vfp_d0_d15_pad[17];2208// VFPv3 registers D16-D31, always saved using FSTMD2209unw_fpreg_t _vfp_d16_d31[16];2210#if defined(__ARM_WMMX)2211// Whether iWMMX data registers are saved.2212bool _saved_iwmmx;2213// Whether iWMMX control registers are saved.2214mutable bool _saved_iwmmx_control;2215// iWMMX registers2216unw_fpreg_t _iwmmx[16];2217// iWMMX control registers2218mutable uint32_t _iwmmx_control[4];2219#endif2220};22212222inline Registers_arm::Registers_arm(const void *registers)2223: _use_X_for_vfp_save(false),2224_saved_vfp_d0_d15(false),2225_saved_vfp_d16_d31(false) {2226static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),2227"arm registers do not fit into unw_context_t");2228// See __unw_getcontext() note about data.2229memcpy(&_registers, registers, sizeof(_registers));2230memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));2231memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));2232memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));2233#if defined(__ARM_WMMX)2234_saved_iwmmx = false;2235_saved_iwmmx_control = false;2236memset(&_iwmmx, 0, sizeof(_iwmmx));2237memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));2238#endif2239}22402241inline Registers_arm::Registers_arm()2242: _use_X_for_vfp_save(false),2243_saved_vfp_d0_d15(false),2244_saved_vfp_d16_d31(false) {2245memset(&_registers, 0, sizeof(_registers));2246memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));2247memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));2248memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));2249#if defined(__ARM_WMMX)2250_saved_iwmmx = false;2251_saved_iwmmx_control = false;2252memset(&_iwmmx, 0, sizeof(_iwmmx));2253memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));2254#endif2255}22562257inline bool Registers_arm::validRegister(int regNum) const {2258// Returns true for all non-VFP registers supported by the EHABI2259// virtual register set (VRS).2260if (regNum == UNW_REG_IP)2261return true;22622263if (regNum == UNW_REG_SP)2264return true;22652266if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)2267return true;22682269#if defined(__ARM_WMMX)2270if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)2271return true;2272#endif22732274#ifdef __ARM_FEATURE_PAUTH2275if (regNum == UNW_ARM_RA_AUTH_CODE)2276return true;2277#endif22782279return false;2280}22812282inline uint32_t Registers_arm::getRegister(int regNum) const {2283if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)2284return _registers.__sp;22852286if (regNum == UNW_ARM_LR)2287return _registers.__lr;22882289if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)2290return _registers.__pc;22912292if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)2293return _registers.__r[regNum];22942295#if defined(__ARM_WMMX)2296if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {2297if (!_saved_iwmmx_control) {2298_saved_iwmmx_control = true;2299saveiWMMXControl(_iwmmx_control);2300}2301return _iwmmx_control[regNum - UNW_ARM_WC0];2302}2303#endif23042305#ifdef __ARM_FEATURE_PAUTH2306if (regNum == UNW_ARM_RA_AUTH_CODE)2307return _pseudo_registers.__pac;2308#endif23092310_LIBUNWIND_ABORT("unsupported arm register");2311}23122313inline void Registers_arm::setRegister(int regNum, uint32_t value) {2314if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {2315_registers.__sp = value;2316return;2317}23182319if (regNum == UNW_ARM_LR) {2320_registers.__lr = value;2321return;2322}23232324if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {2325_registers.__pc = value;2326return;2327}23282329if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {2330_registers.__r[regNum] = value;2331return;2332}23332334#if defined(__ARM_WMMX)2335if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {2336if (!_saved_iwmmx_control) {2337_saved_iwmmx_control = true;2338saveiWMMXControl(_iwmmx_control);2339}2340_iwmmx_control[regNum - UNW_ARM_WC0] = value;2341return;2342}2343#endif23442345if (regNum == UNW_ARM_RA_AUTH_CODE) {2346_pseudo_registers.__pac = value;2347return;2348}23492350_LIBUNWIND_ABORT("unsupported arm register");2351}23522353inline const char *Registers_arm::getRegisterName(int regNum) {2354switch (regNum) {2355case UNW_REG_IP:2356case UNW_ARM_IP: // UNW_ARM_R15 is alias2357return "pc";2358case UNW_ARM_LR: // UNW_ARM_R14 is alias2359return "lr";2360case UNW_REG_SP:2361case UNW_ARM_SP: // UNW_ARM_R13 is alias2362return "sp";2363case UNW_ARM_R0:2364return "r0";2365case UNW_ARM_R1:2366return "r1";2367case UNW_ARM_R2:2368return "r2";2369case UNW_ARM_R3:2370return "r3";2371case UNW_ARM_R4:2372return "r4";2373case UNW_ARM_R5:2374return "r5";2375case UNW_ARM_R6:2376return "r6";2377case UNW_ARM_R7:2378return "r7";2379case UNW_ARM_R8:2380return "r8";2381case UNW_ARM_R9:2382return "r9";2383case UNW_ARM_R10:2384return "r10";2385case UNW_ARM_R11:2386return "r11";2387case UNW_ARM_R12:2388return "r12";2389case UNW_ARM_S0:2390return "s0";2391case UNW_ARM_S1:2392return "s1";2393case UNW_ARM_S2:2394return "s2";2395case UNW_ARM_S3:2396return "s3";2397case UNW_ARM_S4:2398return "s4";2399case UNW_ARM_S5:2400return "s5";2401case UNW_ARM_S6:2402return "s6";2403case UNW_ARM_S7:2404return "s7";2405case UNW_ARM_S8:2406return "s8";2407case UNW_ARM_S9:2408return "s9";2409case UNW_ARM_S10:2410return "s10";2411case UNW_ARM_S11:2412return "s11";2413case UNW_ARM_S12:2414return "s12";2415case UNW_ARM_S13:2416return "s13";2417case UNW_ARM_S14:2418return "s14";2419case UNW_ARM_S15:2420return "s15";2421case UNW_ARM_S16:2422return "s16";2423case UNW_ARM_S17:2424return "s17";2425case UNW_ARM_S18:2426return "s18";2427case UNW_ARM_S19:2428return "s19";2429case UNW_ARM_S20:2430return "s20";2431case UNW_ARM_S21:2432return "s21";2433case UNW_ARM_S22:2434return "s22";2435case UNW_ARM_S23:2436return "s23";2437case UNW_ARM_S24:2438return "s24";2439case UNW_ARM_S25:2440return "s25";2441case UNW_ARM_S26:2442return "s26";2443case UNW_ARM_S27:2444return "s27";2445case UNW_ARM_S28:2446return "s28";2447case UNW_ARM_S29:2448return "s29";2449case UNW_ARM_S30:2450return "s30";2451case UNW_ARM_S31:2452return "s31";2453case UNW_ARM_D0:2454return "d0";2455case UNW_ARM_D1:2456return "d1";2457case UNW_ARM_D2:2458return "d2";2459case UNW_ARM_D3:2460return "d3";2461case UNW_ARM_D4:2462return "d4";2463case UNW_ARM_D5:2464return "d5";2465case UNW_ARM_D6:2466return "d6";2467case UNW_ARM_D7:2468return "d7";2469case UNW_ARM_D8:2470return "d8";2471case UNW_ARM_D9:2472return "d9";2473case UNW_ARM_D10:2474return "d10";2475case UNW_ARM_D11:2476return "d11";2477case UNW_ARM_D12:2478return "d12";2479case UNW_ARM_D13:2480return "d13";2481case UNW_ARM_D14:2482return "d14";2483case UNW_ARM_D15:2484return "d15";2485case UNW_ARM_D16:2486return "d16";2487case UNW_ARM_D17:2488return "d17";2489case UNW_ARM_D18:2490return "d18";2491case UNW_ARM_D19:2492return "d19";2493case UNW_ARM_D20:2494return "d20";2495case UNW_ARM_D21:2496return "d21";2497case UNW_ARM_D22:2498return "d22";2499case UNW_ARM_D23:2500return "d23";2501case UNW_ARM_D24:2502return "d24";2503case UNW_ARM_D25:2504return "d25";2505case UNW_ARM_D26:2506return "d26";2507case UNW_ARM_D27:2508return "d27";2509case UNW_ARM_D28:2510return "d28";2511case UNW_ARM_D29:2512return "d29";2513case UNW_ARM_D30:2514return "d30";2515case UNW_ARM_D31:2516return "d31";2517default:2518return "unknown register";2519}2520}25212522inline bool Registers_arm::validFloatRegister(int regNum) const {2523// NOTE: Consider the intel MMX registers floating points so the2524// __unw_get_fpreg can be used to transmit the 64-bit data back.2525return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))2526#if defined(__ARM_WMMX)2527|| ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))2528#endif2529;2530}25312532inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {2533if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {2534if (!_saved_vfp_d0_d15) {2535_saved_vfp_d0_d15 = true;2536if (_use_X_for_vfp_save)2537saveVFPWithFSTMX(_vfp_d0_d15_pad);2538else2539saveVFPWithFSTMD(_vfp_d0_d15_pad);2540}2541return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];2542}25432544if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {2545if (!_saved_vfp_d16_d31) {2546_saved_vfp_d16_d31 = true;2547saveVFPv3(_vfp_d16_d31);2548}2549return _vfp_d16_d31[regNum - UNW_ARM_D16];2550}25512552#if defined(__ARM_WMMX)2553if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {2554if (!_saved_iwmmx) {2555_saved_iwmmx = true;2556saveiWMMX(_iwmmx);2557}2558return _iwmmx[regNum - UNW_ARM_WR0];2559}2560#endif25612562_LIBUNWIND_ABORT("Unknown ARM float register");2563}25642565inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {2566if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {2567if (!_saved_vfp_d0_d15) {2568_saved_vfp_d0_d15 = true;2569if (_use_X_for_vfp_save)2570saveVFPWithFSTMX(_vfp_d0_d15_pad);2571else2572saveVFPWithFSTMD(_vfp_d0_d15_pad);2573}2574_vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;2575return;2576}25772578if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {2579if (!_saved_vfp_d16_d31) {2580_saved_vfp_d16_d31 = true;2581saveVFPv3(_vfp_d16_d31);2582}2583_vfp_d16_d31[regNum - UNW_ARM_D16] = value;2584return;2585}25862587#if defined(__ARM_WMMX)2588if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {2589if (!_saved_iwmmx) {2590_saved_iwmmx = true;2591saveiWMMX(_iwmmx);2592}2593_iwmmx[regNum - UNW_ARM_WR0] = value;2594return;2595}2596#endif25972598_LIBUNWIND_ABORT("Unknown ARM float register");2599}26002601inline bool Registers_arm::validVectorRegister(int) const {2602return false;2603}26042605inline v128 Registers_arm::getVectorRegister(int) const {2606_LIBUNWIND_ABORT("ARM vector support not implemented");2607}26082609inline void Registers_arm::setVectorRegister(int, v128) {2610_LIBUNWIND_ABORT("ARM vector support not implemented");2611}2612#endif // _LIBUNWIND_TARGET_ARM261326142615#if defined(_LIBUNWIND_TARGET_OR1K)2616/// Registers_or1k holds the register state of a thread in an OpenRISC10002617/// process.2618class _LIBUNWIND_HIDDEN Registers_or1k {2619public:2620Registers_or1k();2621Registers_or1k(const void *registers);26222623bool validRegister(int num) const;2624uint32_t getRegister(int num) const;2625void setRegister(int num, uint32_t value);2626bool validFloatRegister(int num) const;2627double getFloatRegister(int num) const;2628void setFloatRegister(int num, double value);2629bool validVectorRegister(int num) const;2630v128 getVectorRegister(int num) const;2631void setVectorRegister(int num, v128 value);2632static const char *getRegisterName(int num);2633void jumpto();2634static constexpr int lastDwarfRegNum() {2635return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K;2636}2637static int getArch() { return REGISTERS_OR1K; }26382639uint64_t getSP() const { return _registers.__r[1]; }2640void setSP(uint32_t value) { _registers.__r[1] = value; }2641uint64_t getIP() const { return _registers.__pc; }2642void setIP(uint32_t value) { _registers.__pc = value; }26432644private:2645struct or1k_thread_state_t {2646unsigned int __r[32]; // r0-r312647unsigned int __pc; // Program counter2648unsigned int __epcr; // Program counter at exception2649};26502651or1k_thread_state_t _registers;2652};26532654inline Registers_or1k::Registers_or1k(const void *registers) {2655static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),2656"or1k registers do not fit into unw_context_t");2657memcpy(&_registers, static_cast<const uint8_t *>(registers),2658sizeof(_registers));2659}26602661inline Registers_or1k::Registers_or1k() {2662memset(&_registers, 0, sizeof(_registers));2663}26642665inline bool Registers_or1k::validRegister(int regNum) const {2666if (regNum == UNW_REG_IP)2667return true;2668if (regNum == UNW_REG_SP)2669return true;2670if (regNum < 0)2671return false;2672if (regNum <= UNW_OR1K_R31)2673return true;2674if (regNum == UNW_OR1K_EPCR)2675return true;2676return false;2677}26782679inline uint32_t Registers_or1k::getRegister(int regNum) const {2680if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)2681return _registers.__r[regNum - UNW_OR1K_R0];26822683switch (regNum) {2684case UNW_REG_IP:2685return _registers.__pc;2686case UNW_REG_SP:2687return _registers.__r[1];2688case UNW_OR1K_EPCR:2689return _registers.__epcr;2690}2691_LIBUNWIND_ABORT("unsupported or1k register");2692}26932694inline void Registers_or1k::setRegister(int regNum, uint32_t value) {2695if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {2696_registers.__r[regNum - UNW_OR1K_R0] = value;2697return;2698}26992700switch (regNum) {2701case UNW_REG_IP:2702_registers.__pc = value;2703return;2704case UNW_REG_SP:2705_registers.__r[1] = value;2706return;2707case UNW_OR1K_EPCR:2708_registers.__epcr = value;2709return;2710}2711_LIBUNWIND_ABORT("unsupported or1k register");2712}27132714inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {2715return false;2716}27172718inline double Registers_or1k::getFloatRegister(int /* regNum */) const {2719_LIBUNWIND_ABORT("or1k float support not implemented");2720}27212722inline void Registers_or1k::setFloatRegister(int /* regNum */,2723double /* value */) {2724_LIBUNWIND_ABORT("or1k float support not implemented");2725}27262727inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {2728return false;2729}27302731inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {2732_LIBUNWIND_ABORT("or1k vector support not implemented");2733}27342735inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {2736_LIBUNWIND_ABORT("or1k vector support not implemented");2737}27382739inline const char *Registers_or1k::getRegisterName(int regNum) {2740switch (regNum) {2741case UNW_OR1K_R0:2742return "r0";2743case UNW_OR1K_R1:2744return "r1";2745case UNW_OR1K_R2:2746return "r2";2747case UNW_OR1K_R3:2748return "r3";2749case UNW_OR1K_R4:2750return "r4";2751case UNW_OR1K_R5:2752return "r5";2753case UNW_OR1K_R6:2754return "r6";2755case UNW_OR1K_R7:2756return "r7";2757case UNW_OR1K_R8:2758return "r8";2759case UNW_OR1K_R9:2760return "r9";2761case UNW_OR1K_R10:2762return "r10";2763case UNW_OR1K_R11:2764return "r11";2765case UNW_OR1K_R12:2766return "r12";2767case UNW_OR1K_R13:2768return "r13";2769case UNW_OR1K_R14:2770return "r14";2771case UNW_OR1K_R15:2772return "r15";2773case UNW_OR1K_R16:2774return "r16";2775case UNW_OR1K_R17:2776return "r17";2777case UNW_OR1K_R18:2778return "r18";2779case UNW_OR1K_R19:2780return "r19";2781case UNW_OR1K_R20:2782return "r20";2783case UNW_OR1K_R21:2784return "r21";2785case UNW_OR1K_R22:2786return "r22";2787case UNW_OR1K_R23:2788return "r23";2789case UNW_OR1K_R24:2790return "r24";2791case UNW_OR1K_R25:2792return "r25";2793case UNW_OR1K_R26:2794return "r26";2795case UNW_OR1K_R27:2796return "r27";2797case UNW_OR1K_R28:2798return "r28";2799case UNW_OR1K_R29:2800return "r29";2801case UNW_OR1K_R30:2802return "r30";2803case UNW_OR1K_R31:2804return "r31";2805case UNW_OR1K_EPCR:2806return "EPCR";2807default:2808return "unknown register";2809}28102811}2812#endif // _LIBUNWIND_TARGET_OR1K28132814#if defined(_LIBUNWIND_TARGET_MIPS_O32)2815/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS2816/// process.2817class _LIBUNWIND_HIDDEN Registers_mips_o32 {2818public:2819Registers_mips_o32();2820Registers_mips_o32(const void *registers);28212822bool validRegister(int num) const;2823uint32_t getRegister(int num) const;2824void setRegister(int num, uint32_t value);2825bool validFloatRegister(int num) const;2826double getFloatRegister(int num) const;2827void setFloatRegister(int num, double value);2828bool validVectorRegister(int num) const;2829v128 getVectorRegister(int num) const;2830void setVectorRegister(int num, v128 value);2831static const char *getRegisterName(int num);2832void jumpto();2833static constexpr int lastDwarfRegNum() {2834return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;2835}2836static int getArch() { return REGISTERS_MIPS_O32; }28372838uint32_t getSP() const { return _registers.__r[29]; }2839void setSP(uint32_t value) { _registers.__r[29] = value; }2840uint32_t getIP() const { return _registers.__pc; }2841void setIP(uint32_t value) { _registers.__pc = value; }28422843private:2844struct mips_o32_thread_state_t {2845uint32_t __r[32];2846uint32_t __pc;2847uint32_t __hi;2848uint32_t __lo;2849};28502851mips_o32_thread_state_t _registers;2852#ifdef __mips_hard_float2853/// O32 with 32-bit floating point registers only uses half of this2854/// space. However, using the same layout for 32-bit vs 64-bit2855/// floating point registers results in a single context size for2856/// O32 with hard float.2857uint32_t _padding;2858double _floats[32];2859#endif2860};28612862inline Registers_mips_o32::Registers_mips_o32(const void *registers) {2863static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),2864"mips_o32 registers do not fit into unw_context_t");2865memcpy(&_registers, static_cast<const uint8_t *>(registers),2866sizeof(_registers));2867}28682869inline Registers_mips_o32::Registers_mips_o32() {2870memset(&_registers, 0, sizeof(_registers));2871}28722873inline bool Registers_mips_o32::validRegister(int regNum) const {2874if (regNum == UNW_REG_IP)2875return true;2876if (regNum == UNW_REG_SP)2877return true;2878if (regNum < 0)2879return false;2880if (regNum <= UNW_MIPS_R31)2881return true;2882#if __mips_isa_rev < 62883if (regNum == UNW_MIPS_HI)2884return true;2885if (regNum == UNW_MIPS_LO)2886return true;2887#endif2888#if defined(__mips_hard_float) && __mips_fpr == 322889if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)2890return true;2891#endif2892// FIXME: DSP accumulator registers, MSA registers2893return false;2894}28952896inline uint32_t Registers_mips_o32::getRegister(int regNum) const {2897if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)2898return _registers.__r[regNum - UNW_MIPS_R0];2899#if defined(__mips_hard_float) && __mips_fpr == 322900if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {2901uint32_t *p;29022903if (regNum % 2 == 0)2904p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];2905else2906p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;2907return *p;2908}2909#endif29102911switch (regNum) {2912case UNW_REG_IP:2913return _registers.__pc;2914case UNW_REG_SP:2915return _registers.__r[29];2916#if __mips_isa_rev < 62917case UNW_MIPS_HI:2918return _registers.__hi;2919case UNW_MIPS_LO:2920return _registers.__lo;2921#endif2922}2923_LIBUNWIND_ABORT("unsupported mips_o32 register");2924}29252926inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {2927if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {2928_registers.__r[regNum - UNW_MIPS_R0] = value;2929return;2930}2931#if defined(__mips_hard_float) && __mips_fpr == 322932if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {2933uint32_t *p;29342935if (regNum % 2 == 0)2936p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];2937else2938p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;2939*p = value;2940return;2941}2942#endif29432944switch (regNum) {2945case UNW_REG_IP:2946_registers.__pc = value;2947return;2948case UNW_REG_SP:2949_registers.__r[29] = value;2950return;2951#if __mips_isa_rev < 62952case UNW_MIPS_HI:2953_registers.__hi = value;2954return;2955case UNW_MIPS_LO:2956_registers.__lo = value;2957#endif2958return;2959}2960_LIBUNWIND_ABORT("unsupported mips_o32 register");2961}29622963inline bool Registers_mips_o32::validFloatRegister(int regNum) const {2964#if defined(__mips_hard_float) && __mips_fpr == 642965if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)2966return true;2967#else2968(void)regNum;2969#endif2970return false;2971}29722973inline double Registers_mips_o32::getFloatRegister(int regNum) const {2974#if defined(__mips_hard_float) && __mips_fpr == 642975assert(validFloatRegister(regNum));2976return _floats[regNum - UNW_MIPS_F0];2977#else2978(void)regNum;2979_LIBUNWIND_ABORT("mips_o32 float support not implemented");2980#endif2981}29822983inline void Registers_mips_o32::setFloatRegister(int regNum,2984double value) {2985#if defined(__mips_hard_float) && __mips_fpr == 642986assert(validFloatRegister(regNum));2987_floats[regNum - UNW_MIPS_F0] = value;2988#else2989(void)regNum;2990(void)value;2991_LIBUNWIND_ABORT("mips_o32 float support not implemented");2992#endif2993}29942995inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {2996return false;2997}29982999inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {3000_LIBUNWIND_ABORT("mips_o32 vector support not implemented");3001}30023003inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {3004_LIBUNWIND_ABORT("mips_o32 vector support not implemented");3005}30063007inline const char *Registers_mips_o32::getRegisterName(int regNum) {3008switch (regNum) {3009case UNW_MIPS_R0:3010return "$0";3011case UNW_MIPS_R1:3012return "$1";3013case UNW_MIPS_R2:3014return "$2";3015case UNW_MIPS_R3:3016return "$3";3017case UNW_MIPS_R4:3018return "$4";3019case UNW_MIPS_R5:3020return "$5";3021case UNW_MIPS_R6:3022return "$6";3023case UNW_MIPS_R7:3024return "$7";3025case UNW_MIPS_R8:3026return "$8";3027case UNW_MIPS_R9:3028return "$9";3029case UNW_MIPS_R10:3030return "$10";3031case UNW_MIPS_R11:3032return "$11";3033case UNW_MIPS_R12:3034return "$12";3035case UNW_MIPS_R13:3036return "$13";3037case UNW_MIPS_R14:3038return "$14";3039case UNW_MIPS_R15:3040return "$15";3041case UNW_MIPS_R16:3042return "$16";3043case UNW_MIPS_R17:3044return "$17";3045case UNW_MIPS_R18:3046return "$18";3047case UNW_MIPS_R19:3048return "$19";3049case UNW_MIPS_R20:3050return "$20";3051case UNW_MIPS_R21:3052return "$21";3053case UNW_MIPS_R22:3054return "$22";3055case UNW_MIPS_R23:3056return "$23";3057case UNW_MIPS_R24:3058return "$24";3059case UNW_MIPS_R25:3060return "$25";3061case UNW_MIPS_R26:3062return "$26";3063case UNW_MIPS_R27:3064return "$27";3065case UNW_MIPS_R28:3066return "$28";3067case UNW_MIPS_R29:3068return "$29";3069case UNW_MIPS_R30:3070return "$30";3071case UNW_MIPS_R31:3072return "$31";3073case UNW_MIPS_F0:3074return "$f0";3075case UNW_MIPS_F1:3076return "$f1";3077case UNW_MIPS_F2:3078return "$f2";3079case UNW_MIPS_F3:3080return "$f3";3081case UNW_MIPS_F4:3082return "$f4";3083case UNW_MIPS_F5:3084return "$f5";3085case UNW_MIPS_F6:3086return "$f6";3087case UNW_MIPS_F7:3088return "$f7";3089case UNW_MIPS_F8:3090return "$f8";3091case UNW_MIPS_F9:3092return "$f9";3093case UNW_MIPS_F10:3094return "$f10";3095case UNW_MIPS_F11:3096return "$f11";3097case UNW_MIPS_F12:3098return "$f12";3099case UNW_MIPS_F13:3100return "$f13";3101case UNW_MIPS_F14:3102return "$f14";3103case UNW_MIPS_F15:3104return "$f15";3105case UNW_MIPS_F16:3106return "$f16";3107case UNW_MIPS_F17:3108return "$f17";3109case UNW_MIPS_F18:3110return "$f18";3111case UNW_MIPS_F19:3112return "$f19";3113case UNW_MIPS_F20:3114return "$f20";3115case UNW_MIPS_F21:3116return "$f21";3117case UNW_MIPS_F22:3118return "$f22";3119case UNW_MIPS_F23:3120return "$f23";3121case UNW_MIPS_F24:3122return "$f24";3123case UNW_MIPS_F25:3124return "$f25";3125case UNW_MIPS_F26:3126return "$f26";3127case UNW_MIPS_F27:3128return "$f27";3129case UNW_MIPS_F28:3130return "$f28";3131case UNW_MIPS_F29:3132return "$f29";3133case UNW_MIPS_F30:3134return "$f30";3135case UNW_MIPS_F31:3136return "$f31";3137#if __mips_isa_rev < 63138case UNW_MIPS_HI:3139return "$hi";3140case UNW_MIPS_LO:3141return "$lo";3142#endif3143default:3144return "unknown register";3145}3146}3147#endif // _LIBUNWIND_TARGET_MIPS_O3231483149#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)3150/// Registers_mips_newabi holds the register state of a thread in a3151/// MIPS process using NEWABI (the N32 or N64 ABIs).3152class _LIBUNWIND_HIDDEN Registers_mips_newabi {3153public:3154Registers_mips_newabi();3155Registers_mips_newabi(const void *registers);31563157bool validRegister(int num) const;3158uint64_t getRegister(int num) const;3159void setRegister(int num, uint64_t value);3160bool validFloatRegister(int num) const;3161double getFloatRegister(int num) const;3162void setFloatRegister(int num, double value);3163bool validVectorRegister(int num) const;3164v128 getVectorRegister(int num) const;3165void setVectorRegister(int num, v128 value);3166static const char *getRegisterName(int num);3167void jumpto();3168static constexpr int lastDwarfRegNum() {3169return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;3170}3171static int getArch() { return REGISTERS_MIPS_NEWABI; }31723173uint64_t getSP() const { return _registers.__r[29]; }3174void setSP(uint64_t value) { _registers.__r[29] = value; }3175uint64_t getIP() const { return _registers.__pc; }3176void setIP(uint64_t value) { _registers.__pc = value; }31773178private:3179struct mips_newabi_thread_state_t {3180uint64_t __r[32];3181uint64_t __pc;3182uint64_t __hi;3183uint64_t __lo;3184};31853186mips_newabi_thread_state_t _registers;3187#ifdef __mips_hard_float3188double _floats[32];3189#endif3190};31913192inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {3193static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),3194"mips_newabi registers do not fit into unw_context_t");3195memcpy(&_registers, static_cast<const uint8_t *>(registers),3196sizeof(_registers));3197}31983199inline Registers_mips_newabi::Registers_mips_newabi() {3200memset(&_registers, 0, sizeof(_registers));3201}32023203inline bool Registers_mips_newabi::validRegister(int regNum) const {3204if (regNum == UNW_REG_IP)3205return true;3206if (regNum == UNW_REG_SP)3207return true;3208if (regNum < 0)3209return false;3210if (regNum <= UNW_MIPS_R31)3211return true;3212#if __mips_isa_rev < 63213if (regNum == UNW_MIPS_HI)3214return true;3215if (regNum == UNW_MIPS_LO)3216return true;3217#endif3218// FIXME: Hard float, DSP accumulator registers, MSA registers3219return false;3220}32213222inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {3223if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)3224return _registers.__r[regNum - UNW_MIPS_R0];32253226switch (regNum) {3227case UNW_REG_IP:3228return _registers.__pc;3229case UNW_REG_SP:3230return _registers.__r[29];3231#if __mips_isa_rev < 63232case UNW_MIPS_HI:3233return _registers.__hi;3234case UNW_MIPS_LO:3235return _registers.__lo;3236#endif3237}3238_LIBUNWIND_ABORT("unsupported mips_newabi register");3239}32403241inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {3242if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {3243_registers.__r[regNum - UNW_MIPS_R0] = value;3244return;3245}32463247switch (regNum) {3248case UNW_REG_IP:3249_registers.__pc = value;3250return;3251case UNW_REG_SP:3252_registers.__r[29] = value;3253return;3254#if __mips_isa_rev < 63255case UNW_MIPS_HI:3256_registers.__hi = value;3257return;3258case UNW_MIPS_LO:3259_registers.__lo = value;3260return;3261#endif3262}3263_LIBUNWIND_ABORT("unsupported mips_newabi register");3264}32653266inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {3267#ifdef __mips_hard_float3268if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)3269return true;3270#else3271(void)regNum;3272#endif3273return false;3274}32753276inline double Registers_mips_newabi::getFloatRegister(int regNum) const {3277#ifdef __mips_hard_float3278assert(validFloatRegister(regNum));3279return _floats[regNum - UNW_MIPS_F0];3280#else3281(void)regNum;3282_LIBUNWIND_ABORT("mips_newabi float support not implemented");3283#endif3284}32853286inline void Registers_mips_newabi::setFloatRegister(int regNum,3287double value) {3288#ifdef __mips_hard_float3289assert(validFloatRegister(regNum));3290_floats[regNum - UNW_MIPS_F0] = value;3291#else3292(void)regNum;3293(void)value;3294_LIBUNWIND_ABORT("mips_newabi float support not implemented");3295#endif3296}32973298inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {3299return false;3300}33013302inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {3303_LIBUNWIND_ABORT("mips_newabi vector support not implemented");3304}33053306inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {3307_LIBUNWIND_ABORT("mips_newabi vector support not implemented");3308}33093310inline const char *Registers_mips_newabi::getRegisterName(int regNum) {3311switch (regNum) {3312case UNW_MIPS_R0:3313return "$0";3314case UNW_MIPS_R1:3315return "$1";3316case UNW_MIPS_R2:3317return "$2";3318case UNW_MIPS_R3:3319return "$3";3320case UNW_MIPS_R4:3321return "$4";3322case UNW_MIPS_R5:3323return "$5";3324case UNW_MIPS_R6:3325return "$6";3326case UNW_MIPS_R7:3327return "$7";3328case UNW_MIPS_R8:3329return "$8";3330case UNW_MIPS_R9:3331return "$9";3332case UNW_MIPS_R10:3333return "$10";3334case UNW_MIPS_R11:3335return "$11";3336case UNW_MIPS_R12:3337return "$12";3338case UNW_MIPS_R13:3339return "$13";3340case UNW_MIPS_R14:3341return "$14";3342case UNW_MIPS_R15:3343return "$15";3344case UNW_MIPS_R16:3345return "$16";3346case UNW_MIPS_R17:3347return "$17";3348case UNW_MIPS_R18:3349return "$18";3350case UNW_MIPS_R19:3351return "$19";3352case UNW_MIPS_R20:3353return "$20";3354case UNW_MIPS_R21:3355return "$21";3356case UNW_MIPS_R22:3357return "$22";3358case UNW_MIPS_R23:3359return "$23";3360case UNW_MIPS_R24:3361return "$24";3362case UNW_MIPS_R25:3363return "$25";3364case UNW_MIPS_R26:3365return "$26";3366case UNW_MIPS_R27:3367return "$27";3368case UNW_MIPS_R28:3369return "$28";3370case UNW_MIPS_R29:3371return "$29";3372case UNW_MIPS_R30:3373return "$30";3374case UNW_MIPS_R31:3375return "$31";3376case UNW_MIPS_F0:3377return "$f0";3378case UNW_MIPS_F1:3379return "$f1";3380case UNW_MIPS_F2:3381return "$f2";3382case UNW_MIPS_F3:3383return "$f3";3384case UNW_MIPS_F4:3385return "$f4";3386case UNW_MIPS_F5:3387return "$f5";3388case UNW_MIPS_F6:3389return "$f6";3390case UNW_MIPS_F7:3391return "$f7";3392case UNW_MIPS_F8:3393return "$f8";3394case UNW_MIPS_F9:3395return "$f9";3396case UNW_MIPS_F10:3397return "$f10";3398case UNW_MIPS_F11:3399return "$f11";3400case UNW_MIPS_F12:3401return "$f12";3402case UNW_MIPS_F13:3403return "$f13";3404case UNW_MIPS_F14:3405return "$f14";3406case UNW_MIPS_F15:3407return "$f15";3408case UNW_MIPS_F16:3409return "$f16";3410case UNW_MIPS_F17:3411return "$f17";3412case UNW_MIPS_F18:3413return "$f18";3414case UNW_MIPS_F19:3415return "$f19";3416case UNW_MIPS_F20:3417return "$f20";3418case UNW_MIPS_F21:3419return "$f21";3420case UNW_MIPS_F22:3421return "$f22";3422case UNW_MIPS_F23:3423return "$f23";3424case UNW_MIPS_F24:3425return "$f24";3426case UNW_MIPS_F25:3427return "$f25";3428case UNW_MIPS_F26:3429return "$f26";3430case UNW_MIPS_F27:3431return "$f27";3432case UNW_MIPS_F28:3433return "$f28";3434case UNW_MIPS_F29:3435return "$f29";3436case UNW_MIPS_F30:3437return "$f30";3438case UNW_MIPS_F31:3439return "$f31";3440#if __mips_isa_rev < 63441case UNW_MIPS_HI:3442return "$hi";3443case UNW_MIPS_LO:3444return "$lo";3445#endif3446default:3447return "unknown register";3448}3449}3450#endif // _LIBUNWIND_TARGET_MIPS_NEWABI34513452#if defined(_LIBUNWIND_TARGET_SPARC)3453/// Registers_sparc holds the register state of a thread in a 32-bit Sparc3454/// process.3455class _LIBUNWIND_HIDDEN Registers_sparc {3456public:3457Registers_sparc();3458Registers_sparc(const void *registers);34593460bool validRegister(int num) const;3461uint32_t getRegister(int num) const;3462void setRegister(int num, uint32_t value);3463bool validFloatRegister(int num) const;3464double getFloatRegister(int num) const;3465void setFloatRegister(int num, double value);3466bool validVectorRegister(int num) const;3467v128 getVectorRegister(int num) const;3468void setVectorRegister(int num, v128 value);3469static const char *getRegisterName(int num);3470void jumpto();3471static constexpr int lastDwarfRegNum() {3472return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC;3473}3474static int getArch() { return REGISTERS_SPARC; }34753476uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }3477void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }3478uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }3479void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }34803481private:3482struct sparc_thread_state_t {3483unsigned int __regs[32];3484};34853486sparc_thread_state_t _registers;3487};34883489inline Registers_sparc::Registers_sparc(const void *registers) {3490static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),3491"sparc registers do not fit into unw_context_t");3492memcpy(&_registers, static_cast<const uint8_t *>(registers),3493sizeof(_registers));3494}34953496inline Registers_sparc::Registers_sparc() {3497memset(&_registers, 0, sizeof(_registers));3498}34993500inline bool Registers_sparc::validRegister(int regNum) const {3501if (regNum == UNW_REG_IP)3502return true;3503if (regNum == UNW_REG_SP)3504return true;3505if (regNum < 0)3506return false;3507if (regNum <= UNW_SPARC_I7)3508return true;3509return false;3510}35113512inline uint32_t Registers_sparc::getRegister(int regNum) const {3513if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {3514return _registers.__regs[regNum];3515}35163517switch (regNum) {3518case UNW_REG_IP:3519return _registers.__regs[UNW_SPARC_O7];3520case UNW_REG_SP:3521return _registers.__regs[UNW_SPARC_O6];3522}3523_LIBUNWIND_ABORT("unsupported sparc register");3524}35253526inline void Registers_sparc::setRegister(int regNum, uint32_t value) {3527if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {3528_registers.__regs[regNum] = value;3529return;3530}35313532switch (regNum) {3533case UNW_REG_IP:3534_registers.__regs[UNW_SPARC_O7] = value;3535return;3536case UNW_REG_SP:3537_registers.__regs[UNW_SPARC_O6] = value;3538return;3539}3540_LIBUNWIND_ABORT("unsupported sparc register");3541}35423543inline bool Registers_sparc::validFloatRegister(int) const { return false; }35443545inline double Registers_sparc::getFloatRegister(int) const {3546_LIBUNWIND_ABORT("no Sparc float registers");3547}35483549inline void Registers_sparc::setFloatRegister(int, double) {3550_LIBUNWIND_ABORT("no Sparc float registers");3551}35523553inline bool Registers_sparc::validVectorRegister(int) const { return false; }35543555inline v128 Registers_sparc::getVectorRegister(int) const {3556_LIBUNWIND_ABORT("no Sparc vector registers");3557}35583559inline void Registers_sparc::setVectorRegister(int, v128) {3560_LIBUNWIND_ABORT("no Sparc vector registers");3561}35623563inline const char *Registers_sparc::getRegisterName(int regNum) {3564switch (regNum) {3565case UNW_REG_IP:3566return "pc";3567case UNW_SPARC_G0:3568return "g0";3569case UNW_SPARC_G1:3570return "g1";3571case UNW_SPARC_G2:3572return "g2";3573case UNW_SPARC_G3:3574return "g3";3575case UNW_SPARC_G4:3576return "g4";3577case UNW_SPARC_G5:3578return "g5";3579case UNW_SPARC_G6:3580return "g6";3581case UNW_SPARC_G7:3582return "g7";3583case UNW_SPARC_O0:3584return "o0";3585case UNW_SPARC_O1:3586return "o1";3587case UNW_SPARC_O2:3588return "o2";3589case UNW_SPARC_O3:3590return "o3";3591case UNW_SPARC_O4:3592return "o4";3593case UNW_SPARC_O5:3594return "o5";3595case UNW_REG_SP:3596case UNW_SPARC_O6:3597return "sp";3598case UNW_SPARC_O7:3599return "o7";3600case UNW_SPARC_L0:3601return "l0";3602case UNW_SPARC_L1:3603return "l1";3604case UNW_SPARC_L2:3605return "l2";3606case UNW_SPARC_L3:3607return "l3";3608case UNW_SPARC_L4:3609return "l4";3610case UNW_SPARC_L5:3611return "l5";3612case UNW_SPARC_L6:3613return "l6";3614case UNW_SPARC_L7:3615return "l7";3616case UNW_SPARC_I0:3617return "i0";3618case UNW_SPARC_I1:3619return "i1";3620case UNW_SPARC_I2:3621return "i2";3622case UNW_SPARC_I3:3623return "i3";3624case UNW_SPARC_I4:3625return "i4";3626case UNW_SPARC_I5:3627return "i5";3628case UNW_SPARC_I6:3629return "fp";3630case UNW_SPARC_I7:3631return "i7";3632default:3633return "unknown register";3634}3635}3636#endif // _LIBUNWIND_TARGET_SPARC36373638#if defined(_LIBUNWIND_TARGET_SPARC64)3639/// Registers_sparc64 holds the register state of a thread in a 64-bit3640/// sparc process.3641class _LIBUNWIND_HIDDEN Registers_sparc64 {3642public:3643Registers_sparc64() = default;3644Registers_sparc64(const void *registers);36453646bool validRegister(int num) const;3647uint64_t getRegister(int num) const;3648void setRegister(int num, uint64_t value);3649bool validFloatRegister(int num) const;3650double getFloatRegister(int num) const;3651void setFloatRegister(int num, double value);3652bool validVectorRegister(int num) const;3653v128 getVectorRegister(int num) const;3654void setVectorRegister(int num, v128 value);3655const char *getRegisterName(int num);3656void jumpto();3657static constexpr int lastDwarfRegNum() {3658return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;3659}3660static int getArch() { return REGISTERS_SPARC64; }36613662uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; }3663void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; }3664uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }3665void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; }3666uint64_t getWCookie() const { return _wcookie; }36673668private:3669struct sparc64_thread_state_t {3670uint64_t __regs[32];3671};36723673sparc64_thread_state_t _registers{};3674uint64_t _wcookie = 0;3675};36763677inline Registers_sparc64::Registers_sparc64(const void *registers) {3678static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit),3679"sparc64 registers do not fit into unw_context_t");3680memcpy(&_registers, registers, sizeof(_registers));3681memcpy(&_wcookie,3682static_cast<const uint8_t *>(registers) + sizeof(_registers),3683sizeof(_wcookie));3684}36853686inline bool Registers_sparc64::validRegister(int regNum) const {3687if (regNum == UNW_REG_IP)3688return true;3689if (regNum == UNW_REG_SP)3690return true;3691if (regNum < 0)3692return false;3693if (regNum <= UNW_SPARC_I7)3694return true;3695return false;3696}36973698inline uint64_t Registers_sparc64::getRegister(int regNum) const {3699if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7)3700return _registers.__regs[regNum];37013702switch (regNum) {3703case UNW_REG_IP:3704return _registers.__regs[UNW_SPARC_O7];3705case UNW_REG_SP:3706return _registers.__regs[UNW_SPARC_O6] + 2047;3707}3708_LIBUNWIND_ABORT("unsupported sparc64 register");3709}37103711inline void Registers_sparc64::setRegister(int regNum, uint64_t value) {3712if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) {3713_registers.__regs[regNum] = value;3714return;3715}37163717switch (regNum) {3718case UNW_REG_IP:3719_registers.__regs[UNW_SPARC_O7] = value;3720return;3721case UNW_REG_SP:3722_registers.__regs[UNW_SPARC_O6] = value - 2047;3723return;3724}3725_LIBUNWIND_ABORT("unsupported sparc64 register");3726}37273728inline bool Registers_sparc64::validFloatRegister(int) const { return false; }37293730inline double Registers_sparc64::getFloatRegister(int) const {3731_LIBUNWIND_ABORT("no sparc64 float registers");3732}37333734inline void Registers_sparc64::setFloatRegister(int, double) {3735_LIBUNWIND_ABORT("no sparc64 float registers");3736}37373738inline bool Registers_sparc64::validVectorRegister(int) const { return false; }37393740inline v128 Registers_sparc64::getVectorRegister(int) const {3741_LIBUNWIND_ABORT("no sparc64 vector registers");3742}37433744inline void Registers_sparc64::setVectorRegister(int, v128) {3745_LIBUNWIND_ABORT("no sparc64 vector registers");3746}37473748inline const char *Registers_sparc64::getRegisterName(int regNum) {3749switch (regNum) {3750case UNW_REG_IP:3751return "pc";3752case UNW_SPARC_G0:3753return "g0";3754case UNW_SPARC_G1:3755return "g1";3756case UNW_SPARC_G2:3757return "g2";3758case UNW_SPARC_G3:3759return "g3";3760case UNW_SPARC_G4:3761return "g4";3762case UNW_SPARC_G5:3763return "g5";3764case UNW_SPARC_G6:3765return "g6";3766case UNW_SPARC_G7:3767return "g7";3768case UNW_SPARC_O0:3769return "o0";3770case UNW_SPARC_O1:3771return "o1";3772case UNW_SPARC_O2:3773return "o2";3774case UNW_SPARC_O3:3775return "o3";3776case UNW_SPARC_O4:3777return "o4";3778case UNW_SPARC_O5:3779return "o5";3780case UNW_REG_SP:3781case UNW_SPARC_O6:3782return "o6";3783case UNW_SPARC_O7:3784return "o7";3785case UNW_SPARC_L0:3786return "l0";3787case UNW_SPARC_L1:3788return "l1";3789case UNW_SPARC_L2:3790return "l2";3791case UNW_SPARC_L3:3792return "l3";3793case UNW_SPARC_L4:3794return "l4";3795case UNW_SPARC_L5:3796return "l5";3797case UNW_SPARC_L6:3798return "l6";3799case UNW_SPARC_L7:3800return "l7";3801case UNW_SPARC_I0:3802return "i0";3803case UNW_SPARC_I1:3804return "i1";3805case UNW_SPARC_I2:3806return "i2";3807case UNW_SPARC_I3:3808return "i3";3809case UNW_SPARC_I4:3810return "i4";3811case UNW_SPARC_I5:3812return "i5";3813case UNW_SPARC_I6:3814return "i6";3815case UNW_SPARC_I7:3816return "i7";3817default:3818return "unknown register";3819}3820}3821#endif // _LIBUNWIND_TARGET_SPARC6438223823#if defined(_LIBUNWIND_TARGET_HEXAGON)3824/// Registers_hexagon holds the register state of a thread in a Hexagon QDSP63825/// process.3826class _LIBUNWIND_HIDDEN Registers_hexagon {3827public:3828Registers_hexagon();3829Registers_hexagon(const void *registers);38303831bool validRegister(int num) const;3832uint32_t getRegister(int num) const;3833void setRegister(int num, uint32_t value);3834bool validFloatRegister(int num) const;3835double getFloatRegister(int num) const;3836void setFloatRegister(int num, double value);3837bool validVectorRegister(int num) const;3838v128 getVectorRegister(int num) const;3839void setVectorRegister(int num, v128 value);3840const char *getRegisterName(int num);3841void jumpto();3842static constexpr int lastDwarfRegNum() {3843return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON;3844}3845static int getArch() { return REGISTERS_HEXAGON; }38463847uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }3848void setSP(uint32_t value) { _registers.__r[UNW_HEXAGON_R29] = value; }3849uint32_t getIP() const { return _registers.__r[UNW_HEXAGON_PC]; }3850void setIP(uint32_t value) { _registers.__r[UNW_HEXAGON_PC] = value; }38513852private:3853struct hexagon_thread_state_t {3854unsigned int __r[35];3855};38563857hexagon_thread_state_t _registers;3858};38593860inline Registers_hexagon::Registers_hexagon(const void *registers) {3861static_assert((check_fit<Registers_hexagon, unw_context_t>::does_fit),3862"hexagon registers do not fit into unw_context_t");3863memcpy(&_registers, static_cast<const uint8_t *>(registers),3864sizeof(_registers));3865}38663867inline Registers_hexagon::Registers_hexagon() {3868memset(&_registers, 0, sizeof(_registers));3869}38703871inline bool Registers_hexagon::validRegister(int regNum) const {3872if (regNum <= UNW_HEXAGON_R31)3873return true;3874return false;3875}38763877inline uint32_t Registers_hexagon::getRegister(int regNum) const {3878if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31)3879return _registers.__r[regNum - UNW_HEXAGON_R0];38803881switch (regNum) {3882case UNW_REG_IP:3883return _registers.__r[UNW_HEXAGON_PC];3884case UNW_REG_SP:3885return _registers.__r[UNW_HEXAGON_R29];3886}3887_LIBUNWIND_ABORT("unsupported hexagon register");3888}38893890inline void Registers_hexagon::setRegister(int regNum, uint32_t value) {3891if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) {3892_registers.__r[regNum - UNW_HEXAGON_R0] = value;3893return;3894}38953896switch (regNum) {3897case UNW_REG_IP:3898_registers.__r[UNW_HEXAGON_PC] = value;3899return;3900case UNW_REG_SP:3901_registers.__r[UNW_HEXAGON_R29] = value;3902return;3903}3904_LIBUNWIND_ABORT("unsupported hexagon register");3905}39063907inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {3908return false;3909}39103911inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {3912_LIBUNWIND_ABORT("hexagon float support not implemented");3913}39143915inline void Registers_hexagon::setFloatRegister(int /* regNum */,3916double /* value */) {3917_LIBUNWIND_ABORT("hexagon float support not implemented");3918}39193920inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {3921return false;3922}39233924inline v128 Registers_hexagon::getVectorRegister(int /* regNum */) const {3925_LIBUNWIND_ABORT("hexagon vector support not implemented");3926}39273928inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128 /* value */) {3929_LIBUNWIND_ABORT("hexagon vector support not implemented");3930}39313932inline const char *Registers_hexagon::getRegisterName(int regNum) {3933switch (regNum) {3934case UNW_HEXAGON_R0:3935return "r0";3936case UNW_HEXAGON_R1:3937return "r1";3938case UNW_HEXAGON_R2:3939return "r2";3940case UNW_HEXAGON_R3:3941return "r3";3942case UNW_HEXAGON_R4:3943return "r4";3944case UNW_HEXAGON_R5:3945return "r5";3946case UNW_HEXAGON_R6:3947return "r6";3948case UNW_HEXAGON_R7:3949return "r7";3950case UNW_HEXAGON_R8:3951return "r8";3952case UNW_HEXAGON_R9:3953return "r9";3954case UNW_HEXAGON_R10:3955return "r10";3956case UNW_HEXAGON_R11:3957return "r11";3958case UNW_HEXAGON_R12:3959return "r12";3960case UNW_HEXAGON_R13:3961return "r13";3962case UNW_HEXAGON_R14:3963return "r14";3964case UNW_HEXAGON_R15:3965return "r15";3966case UNW_HEXAGON_R16:3967return "r16";3968case UNW_HEXAGON_R17:3969return "r17";3970case UNW_HEXAGON_R18:3971return "r18";3972case UNW_HEXAGON_R19:3973return "r19";3974case UNW_HEXAGON_R20:3975return "r20";3976case UNW_HEXAGON_R21:3977return "r21";3978case UNW_HEXAGON_R22:3979return "r22";3980case UNW_HEXAGON_R23:3981return "r23";3982case UNW_HEXAGON_R24:3983return "r24";3984case UNW_HEXAGON_R25:3985return "r25";3986case UNW_HEXAGON_R26:3987return "r26";3988case UNW_HEXAGON_R27:3989return "r27";3990case UNW_HEXAGON_R28:3991return "r28";3992case UNW_HEXAGON_R29:3993return "r29";3994case UNW_HEXAGON_R30:3995return "r30";3996case UNW_HEXAGON_R31:3997return "r31";3998default:3999return "unknown register";4000}40014002}4003#endif // _LIBUNWIND_TARGET_HEXAGON400440054006#if defined(_LIBUNWIND_TARGET_RISCV)4007/// Registers_riscv holds the register state of a thread in a RISC-V4008/// process.40094010// This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.4011# ifdef __riscv4012# if __riscv_xlen == 324013typedef uint32_t reg_t;4014# elif __riscv_xlen == 644015typedef uint64_t reg_t;4016# else4017# error "Unsupported __riscv_xlen"4018# endif40194020# if defined(__riscv_flen)4021# if __riscv_flen == 644022typedef double fp_t;4023# elif __riscv_flen == 324024typedef float fp_t;4025# else4026# error "Unsupported __riscv_flen"4027# endif4028# else4029// This is just for suppressing undeclared error of fp_t.4030typedef double fp_t;4031# endif4032# else4033// Use Max possible width when cross unwinding4034typedef uint64_t reg_t;4035typedef double fp_t;4036# define __riscv_xlen 644037# define __riscv_flen 644038#endif40394040/// Registers_riscv holds the register state of a thread.4041class _LIBUNWIND_HIDDEN Registers_riscv {4042public:4043Registers_riscv();4044Registers_riscv(const void *registers);40454046bool validRegister(int num) const;4047reg_t getRegister(int num) const;4048void setRegister(int num, reg_t value);4049bool validFloatRegister(int num) const;4050fp_t getFloatRegister(int num) const;4051void setFloatRegister(int num, fp_t value);4052bool validVectorRegister(int num) const;4053v128 getVectorRegister(int num) const;4054void setVectorRegister(int num, v128 value);4055static const char *getRegisterName(int num);4056void jumpto();4057static constexpr int lastDwarfRegNum() {4058return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV;4059}4060static int getArch() { return REGISTERS_RISCV; }40614062reg_t getSP() const { return _registers[2]; }4063void setSP(reg_t value) { _registers[2] = value; }4064reg_t getIP() const { return _registers[0]; }4065void setIP(reg_t value) { _registers[0] = value; }40664067private:4068// _registers[0] holds the pc4069reg_t _registers[32];4070# if defined(__riscv_flen)4071fp_t _floats[32];4072# endif4073};40744075inline Registers_riscv::Registers_riscv(const void *registers) {4076static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit),4077"riscv registers do not fit into unw_context_t");4078memcpy(&_registers, registers, sizeof(_registers));4079# if __riscv_xlen == 324080static_assert(sizeof(_registers) == 0x80,4081"expected float registers to be at offset 128");4082# elif __riscv_xlen == 644083static_assert(sizeof(_registers) == 0x100,4084"expected float registers to be at offset 256");4085# else4086# error "Unexpected float registers."4087# endif40884089# if defined(__riscv_flen)4090memcpy(_floats,4091static_cast<const uint8_t *>(registers) + sizeof(_registers),4092sizeof(_floats));4093# endif4094}40954096inline Registers_riscv::Registers_riscv() {4097memset(&_registers, 0, sizeof(_registers));4098# if defined(__riscv_flen)4099memset(&_floats, 0, sizeof(_floats));4100# endif4101}41024103inline bool Registers_riscv::validRegister(int regNum) const {4104if (regNum == UNW_REG_IP)4105return true;4106if (regNum == UNW_REG_SP)4107return true;4108if (regNum < 0)4109return false;4110if (regNum == UNW_RISCV_VLENB)4111return true;4112if (regNum > UNW_RISCV_F31)4113return false;4114return true;4115}41164117inline reg_t Registers_riscv::getRegister(int regNum) const {4118if (regNum == UNW_REG_IP)4119return _registers[0];4120if (regNum == UNW_REG_SP)4121return _registers[2];4122if (regNum == UNW_RISCV_X0)4123return 0;4124if ((regNum > 0) && (regNum < 32))4125return _registers[regNum];4126if (regNum == UNW_RISCV_VLENB) {4127reg_t vlenb;4128__asm__("csrr %0, 0xC22" : "=r"(vlenb));4129return vlenb;4130}4131_LIBUNWIND_ABORT("unsupported riscv register");4132}41334134inline void Registers_riscv::setRegister(int regNum, reg_t value) {4135if (regNum == UNW_REG_IP)4136_registers[0] = value;4137else if (regNum == UNW_REG_SP)4138_registers[2] = value;4139else if (regNum == UNW_RISCV_X0)4140/* x0 is hardwired to zero */4141return;4142else if ((regNum > 0) && (regNum < 32))4143_registers[regNum] = value;4144else4145_LIBUNWIND_ABORT("unsupported riscv register");4146}41474148inline const char *Registers_riscv::getRegisterName(int regNum) {4149switch (regNum) {4150case UNW_REG_IP:4151return "pc";4152case UNW_REG_SP:4153return "sp";4154case UNW_RISCV_X0:4155return "zero";4156case UNW_RISCV_X1:4157return "ra";4158case UNW_RISCV_X2:4159return "sp";4160case UNW_RISCV_X3:4161return "gp";4162case UNW_RISCV_X4:4163return "tp";4164case UNW_RISCV_X5:4165return "t0";4166case UNW_RISCV_X6:4167return "t1";4168case UNW_RISCV_X7:4169return "t2";4170case UNW_RISCV_X8:4171return "s0";4172case UNW_RISCV_X9:4173return "s1";4174case UNW_RISCV_X10:4175return "a0";4176case UNW_RISCV_X11:4177return "a1";4178case UNW_RISCV_X12:4179return "a2";4180case UNW_RISCV_X13:4181return "a3";4182case UNW_RISCV_X14:4183return "a4";4184case UNW_RISCV_X15:4185return "a5";4186case UNW_RISCV_X16:4187return "a6";4188case UNW_RISCV_X17:4189return "a7";4190case UNW_RISCV_X18:4191return "s2";4192case UNW_RISCV_X19:4193return "s3";4194case UNW_RISCV_X20:4195return "s4";4196case UNW_RISCV_X21:4197return "s5";4198case UNW_RISCV_X22:4199return "s6";4200case UNW_RISCV_X23:4201return "s7";4202case UNW_RISCV_X24:4203return "s8";4204case UNW_RISCV_X25:4205return "s9";4206case UNW_RISCV_X26:4207return "s10";4208case UNW_RISCV_X27:4209return "s11";4210case UNW_RISCV_X28:4211return "t3";4212case UNW_RISCV_X29:4213return "t4";4214case UNW_RISCV_X30:4215return "t5";4216case UNW_RISCV_X31:4217return "t6";4218case UNW_RISCV_F0:4219return "ft0";4220case UNW_RISCV_F1:4221return "ft1";4222case UNW_RISCV_F2:4223return "ft2";4224case UNW_RISCV_F3:4225return "ft3";4226case UNW_RISCV_F4:4227return "ft4";4228case UNW_RISCV_F5:4229return "ft5";4230case UNW_RISCV_F6:4231return "ft6";4232case UNW_RISCV_F7:4233return "ft7";4234case UNW_RISCV_F8:4235return "fs0";4236case UNW_RISCV_F9:4237return "fs1";4238case UNW_RISCV_F10:4239return "fa0";4240case UNW_RISCV_F11:4241return "fa1";4242case UNW_RISCV_F12:4243return "fa2";4244case UNW_RISCV_F13:4245return "fa3";4246case UNW_RISCV_F14:4247return "fa4";4248case UNW_RISCV_F15:4249return "fa5";4250case UNW_RISCV_F16:4251return "fa6";4252case UNW_RISCV_F17:4253return "fa7";4254case UNW_RISCV_F18:4255return "fs2";4256case UNW_RISCV_F19:4257return "fs3";4258case UNW_RISCV_F20:4259return "fs4";4260case UNW_RISCV_F21:4261return "fs5";4262case UNW_RISCV_F22:4263return "fs6";4264case UNW_RISCV_F23:4265return "fs7";4266case UNW_RISCV_F24:4267return "fs8";4268case UNW_RISCV_F25:4269return "fs9";4270case UNW_RISCV_F26:4271return "fs10";4272case UNW_RISCV_F27:4273return "fs11";4274case UNW_RISCV_F28:4275return "ft8";4276case UNW_RISCV_F29:4277return "ft9";4278case UNW_RISCV_F30:4279return "ft10";4280case UNW_RISCV_F31:4281return "ft11";4282case UNW_RISCV_VLENB:4283return "vlenb";4284default:4285return "unknown register";4286}4287}42884289inline bool Registers_riscv::validFloatRegister(int regNum) const {4290# if defined(__riscv_flen)4291if (regNum < UNW_RISCV_F0)4292return false;4293if (regNum > UNW_RISCV_F31)4294return false;4295return true;4296# else4297(void)regNum;4298return false;4299# endif4300}43014302inline fp_t Registers_riscv::getFloatRegister(int regNum) const {4303# if defined(__riscv_flen)4304assert(validFloatRegister(regNum));4305return _floats[regNum - UNW_RISCV_F0];4306# else4307(void)regNum;4308_LIBUNWIND_ABORT("libunwind not built with float support");4309# endif4310}43114312inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) {4313# if defined(__riscv_flen)4314assert(validFloatRegister(regNum));4315_floats[regNum - UNW_RISCV_F0] = value;4316# else4317(void)regNum;4318(void)value;4319_LIBUNWIND_ABORT("libunwind not built with float support");4320# endif4321}43224323inline bool Registers_riscv::validVectorRegister(int) const {4324return false;4325}43264327inline v128 Registers_riscv::getVectorRegister(int) const {4328_LIBUNWIND_ABORT("no riscv vector register support yet");4329}43304331inline void Registers_riscv::setVectorRegister(int, v128) {4332_LIBUNWIND_ABORT("no riscv vector register support yet");4333}4334#endif // _LIBUNWIND_TARGET_RISCV43354336#if defined(_LIBUNWIND_TARGET_VE)4337/// Registers_ve holds the register state of a thread in a VE process.4338class _LIBUNWIND_HIDDEN Registers_ve {4339public:4340Registers_ve();4341Registers_ve(const void *registers);43424343bool validRegister(int num) const;4344uint64_t getRegister(int num) const;4345void setRegister(int num, uint64_t value);4346bool validFloatRegister(int num) const;4347double getFloatRegister(int num) const;4348void setFloatRegister(int num, double value);4349bool validVectorRegister(int num) const;4350v128 getVectorRegister(int num) const;4351void setVectorRegister(int num, v128 value);4352static const char *getRegisterName(int num);4353void jumpto();4354static constexpr int lastDwarfRegNum() {4355return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE;4356}4357static int getArch() { return REGISTERS_VE; }43584359uint64_t getSP() const { return _registers.__s[11]; }4360void setSP(uint64_t value) { _registers.__s[11] = value; }4361uint64_t getIP() const { return _registers.__ic; }4362void setIP(uint64_t value) { _registers.__ic = value; }43634364private:4365// FIXME: Need to store not only scalar registers but also vector and vector4366// mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes4367// 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for4368// SjLj exception support only, so Registers_ve is not implemented completely.4369struct ve_thread_state_t {4370uint64_t __s[64]; // s0-s644371uint64_t __ic; // Instruction counter (IC)4372uint64_t __vixr; // Vector Index Register4373uint64_t __vl; // Vector Length Register4374};43754376ve_thread_state_t _registers; // total 67 registers43774378// Currently no vector register is preserved.4379};43804381inline Registers_ve::Registers_ve(const void *registers) {4382static_assert((check_fit<Registers_ve, unw_context_t>::does_fit),4383"ve registers do not fit into unw_context_t");4384memcpy(&_registers, static_cast<const uint8_t *>(registers),4385sizeof(_registers));4386static_assert(sizeof(_registers) == 536,4387"expected vector register offset to be 536");4388}43894390inline Registers_ve::Registers_ve() {4391memset(&_registers, 0, sizeof(_registers));4392}43934394inline bool Registers_ve::validRegister(int regNum) const {4395if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)4396return true;43974398switch (regNum) {4399case UNW_REG_IP:4400case UNW_REG_SP:4401case UNW_VE_VIXR:4402case UNW_VE_VL:4403return true;4404default:4405return false;4406}4407}44084409inline uint64_t Registers_ve::getRegister(int regNum) const {4410if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)4411return _registers.__s[regNum - UNW_VE_S0];44124413switch (regNum) {4414case UNW_REG_IP:4415return _registers.__ic;4416case UNW_REG_SP:4417return _registers.__s[11];4418case UNW_VE_VIXR:4419return _registers.__vixr;4420case UNW_VE_VL:4421return _registers.__vl;4422}4423_LIBUNWIND_ABORT("unsupported ve register");4424}44254426inline void Registers_ve::setRegister(int regNum, uint64_t value) {4427if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) {4428_registers.__s[regNum - UNW_VE_S0] = value;4429return;4430}44314432switch (regNum) {4433case UNW_REG_IP:4434_registers.__ic = value;4435return;4436case UNW_REG_SP:4437_registers.__s[11] = value;4438return;4439case UNW_VE_VIXR:4440_registers.__vixr = value;4441return;4442case UNW_VE_VL:4443_registers.__vl = value;4444return;4445}4446_LIBUNWIND_ABORT("unsupported ve register");4447}44484449inline bool Registers_ve::validFloatRegister(int /* regNum */) const {4450return false;4451}44524453inline double Registers_ve::getFloatRegister(int /* regNum */) const {4454_LIBUNWIND_ABORT("VE doesn't have float registers");4455}44564457inline void Registers_ve::setFloatRegister(int /* regNum */,4458double /* value */) {4459_LIBUNWIND_ABORT("VE doesn't have float registers");4460}44614462inline bool Registers_ve::validVectorRegister(int /* regNum */) const {4463return false;4464}44654466inline v128 Registers_ve::getVectorRegister(int /* regNum */) const {4467_LIBUNWIND_ABORT("VE vector support not implemented");4468}44694470inline void Registers_ve::setVectorRegister(int /* regNum */,4471v128 /* value */) {4472_LIBUNWIND_ABORT("VE vector support not implemented");4473}44744475inline const char *Registers_ve::getRegisterName(int regNum) {4476switch (regNum) {4477case UNW_REG_IP:4478return "ip";4479case UNW_REG_SP:4480return "sp";4481case UNW_VE_VIXR:4482return "vixr";4483case UNW_VE_VL:4484return "vl";4485case UNW_VE_S0:4486return "s0";4487case UNW_VE_S1:4488return "s1";4489case UNW_VE_S2:4490return "s2";4491case UNW_VE_S3:4492return "s3";4493case UNW_VE_S4:4494return "s4";4495case UNW_VE_S5:4496return "s5";4497case UNW_VE_S6:4498return "s6";4499case UNW_VE_S7:4500return "s7";4501case UNW_VE_S8:4502return "s8";4503case UNW_VE_S9:4504return "s9";4505case UNW_VE_S10:4506return "s10";4507case UNW_VE_S11:4508return "s11";4509case UNW_VE_S12:4510return "s12";4511case UNW_VE_S13:4512return "s13";4513case UNW_VE_S14:4514return "s14";4515case UNW_VE_S15:4516return "s15";4517case UNW_VE_S16:4518return "s16";4519case UNW_VE_S17:4520return "s17";4521case UNW_VE_S18:4522return "s18";4523case UNW_VE_S19:4524return "s19";4525case UNW_VE_S20:4526return "s20";4527case UNW_VE_S21:4528return "s21";4529case UNW_VE_S22:4530return "s22";4531case UNW_VE_S23:4532return "s23";4533case UNW_VE_S24:4534return "s24";4535case UNW_VE_S25:4536return "s25";4537case UNW_VE_S26:4538return "s26";4539case UNW_VE_S27:4540return "s27";4541case UNW_VE_S28:4542return "s28";4543case UNW_VE_S29:4544return "s29";4545case UNW_VE_S30:4546return "s30";4547case UNW_VE_S31:4548return "s31";4549case UNW_VE_S32:4550return "s32";4551case UNW_VE_S33:4552return "s33";4553case UNW_VE_S34:4554return "s34";4555case UNW_VE_S35:4556return "s35";4557case UNW_VE_S36:4558return "s36";4559case UNW_VE_S37:4560return "s37";4561case UNW_VE_S38:4562return "s38";4563case UNW_VE_S39:4564return "s39";4565case UNW_VE_S40:4566return "s40";4567case UNW_VE_S41:4568return "s41";4569case UNW_VE_S42:4570return "s42";4571case UNW_VE_S43:4572return "s43";4573case UNW_VE_S44:4574return "s44";4575case UNW_VE_S45:4576return "s45";4577case UNW_VE_S46:4578return "s46";4579case UNW_VE_S47:4580return "s47";4581case UNW_VE_S48:4582return "s48";4583case UNW_VE_S49:4584return "s49";4585case UNW_VE_S50:4586return "s50";4587case UNW_VE_S51:4588return "s51";4589case UNW_VE_S52:4590return "s52";4591case UNW_VE_S53:4592return "s53";4593case UNW_VE_S54:4594return "s54";4595case UNW_VE_S55:4596return "s55";4597case UNW_VE_S56:4598return "s56";4599case UNW_VE_S57:4600return "s57";4601case UNW_VE_S58:4602return "s58";4603case UNW_VE_S59:4604return "s59";4605case UNW_VE_S60:4606return "s60";4607case UNW_VE_S61:4608return "s61";4609case UNW_VE_S62:4610return "s62";4611case UNW_VE_S63:4612return "s63";4613case UNW_VE_V0:4614return "v0";4615case UNW_VE_V1:4616return "v1";4617case UNW_VE_V2:4618return "v2";4619case UNW_VE_V3:4620return "v3";4621case UNW_VE_V4:4622return "v4";4623case UNW_VE_V5:4624return "v5";4625case UNW_VE_V6:4626return "v6";4627case UNW_VE_V7:4628return "v7";4629case UNW_VE_V8:4630return "v8";4631case UNW_VE_V9:4632return "v9";4633case UNW_VE_V10:4634return "v10";4635case UNW_VE_V11:4636return "v11";4637case UNW_VE_V12:4638return "v12";4639case UNW_VE_V13:4640return "v13";4641case UNW_VE_V14:4642return "v14";4643case UNW_VE_V15:4644return "v15";4645case UNW_VE_V16:4646return "v16";4647case UNW_VE_V17:4648return "v17";4649case UNW_VE_V18:4650return "v18";4651case UNW_VE_V19:4652return "v19";4653case UNW_VE_V20:4654return "v20";4655case UNW_VE_V21:4656return "v21";4657case UNW_VE_V22:4658return "v22";4659case UNW_VE_V23:4660return "v23";4661case UNW_VE_V24:4662return "v24";4663case UNW_VE_V25:4664return "v25";4665case UNW_VE_V26:4666return "v26";4667case UNW_VE_V27:4668return "v27";4669case UNW_VE_V28:4670return "v28";4671case UNW_VE_V29:4672return "v29";4673case UNW_VE_V30:4674return "v30";4675case UNW_VE_V31:4676return "v31";4677case UNW_VE_V32:4678return "v32";4679case UNW_VE_V33:4680return "v33";4681case UNW_VE_V34:4682return "v34";4683case UNW_VE_V35:4684return "v35";4685case UNW_VE_V36:4686return "v36";4687case UNW_VE_V37:4688return "v37";4689case UNW_VE_V38:4690return "v38";4691case UNW_VE_V39:4692return "v39";4693case UNW_VE_V40:4694return "v40";4695case UNW_VE_V41:4696return "v41";4697case UNW_VE_V42:4698return "v42";4699case UNW_VE_V43:4700return "v43";4701case UNW_VE_V44:4702return "v44";4703case UNW_VE_V45:4704return "v45";4705case UNW_VE_V46:4706return "v46";4707case UNW_VE_V47:4708return "v47";4709case UNW_VE_V48:4710return "v48";4711case UNW_VE_V49:4712return "v49";4713case UNW_VE_V50:4714return "v50";4715case UNW_VE_V51:4716return "v51";4717case UNW_VE_V52:4718return "v52";4719case UNW_VE_V53:4720return "v53";4721case UNW_VE_V54:4722return "v54";4723case UNW_VE_V55:4724return "v55";4725case UNW_VE_V56:4726return "v56";4727case UNW_VE_V57:4728return "v57";4729case UNW_VE_V58:4730return "v58";4731case UNW_VE_V59:4732return "v59";4733case UNW_VE_V60:4734return "v60";4735case UNW_VE_V61:4736return "v61";4737case UNW_VE_V62:4738return "v62";4739case UNW_VE_V63:4740return "v63";4741case UNW_VE_VM0:4742return "vm0";4743case UNW_VE_VM1:4744return "vm1";4745case UNW_VE_VM2:4746return "vm2";4747case UNW_VE_VM3:4748return "vm3";4749case UNW_VE_VM4:4750return "vm4";4751case UNW_VE_VM5:4752return "vm5";4753case UNW_VE_VM6:4754return "vm6";4755case UNW_VE_VM7:4756return "vm7";4757case UNW_VE_VM8:4758return "vm8";4759case UNW_VE_VM9:4760return "vm9";4761case UNW_VE_VM10:4762return "vm10";4763case UNW_VE_VM11:4764return "vm11";4765case UNW_VE_VM12:4766return "vm12";4767case UNW_VE_VM13:4768return "vm13";4769case UNW_VE_VM14:4770return "vm14";4771case UNW_VE_VM15:4772return "vm15";4773}4774return "unknown register";4775}4776#endif // _LIBUNWIND_TARGET_VE47774778#if defined(_LIBUNWIND_TARGET_S390X)4779/// Registers_s390x holds the register state of a thread in a4780/// 64-bit Linux on IBM zSystems process.4781class _LIBUNWIND_HIDDEN Registers_s390x {4782public:4783Registers_s390x();4784Registers_s390x(const void *registers);47854786bool validRegister(int num) const;4787uint64_t getRegister(int num) const;4788void setRegister(int num, uint64_t value);4789bool validFloatRegister(int num) const;4790double getFloatRegister(int num) const;4791void setFloatRegister(int num, double value);4792bool validVectorRegister(int num) const;4793v128 getVectorRegister(int num) const;4794void setVectorRegister(int num, v128 value);4795static const char *getRegisterName(int num);4796void jumpto();4797static constexpr int lastDwarfRegNum() {4798return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X;4799}4800static int getArch() { return REGISTERS_S390X; }48014802uint64_t getSP() const { return _registers.__gpr[15]; }4803void setSP(uint64_t value) { _registers.__gpr[15] = value; }4804uint64_t getIP() const { return _registers.__pswa; }4805void setIP(uint64_t value) { _registers.__pswa = value; }48064807private:4808struct s390x_thread_state_t {4809uint64_t __pswm; // Problem Status Word: Mask4810uint64_t __pswa; // Problem Status Word: Address (PC)4811uint64_t __gpr[16]; // General Purpose Registers4812double __fpr[16]; // Floating-Point Registers4813};48144815s390x_thread_state_t _registers;4816};48174818inline Registers_s390x::Registers_s390x(const void *registers) {4819static_assert((check_fit<Registers_s390x, unw_context_t>::does_fit),4820"s390x registers do not fit into unw_context_t");4821memcpy(&_registers, static_cast<const uint8_t *>(registers),4822sizeof(_registers));4823}48244825inline Registers_s390x::Registers_s390x() {4826memset(&_registers, 0, sizeof(_registers));4827}48284829inline bool Registers_s390x::validRegister(int regNum) const {4830switch (regNum) {4831case UNW_S390X_PSWM:4832case UNW_S390X_PSWA:4833case UNW_REG_IP:4834case UNW_REG_SP:4835return true;4836}48374838if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)4839return true;48404841return false;4842}48434844inline uint64_t Registers_s390x::getRegister(int regNum) const {4845if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)4846return _registers.__gpr[regNum - UNW_S390X_R0];48474848switch (regNum) {4849case UNW_S390X_PSWM:4850return _registers.__pswm;4851case UNW_S390X_PSWA:4852case UNW_REG_IP:4853return _registers.__pswa;4854case UNW_REG_SP:4855return _registers.__gpr[15];4856}4857_LIBUNWIND_ABORT("unsupported s390x register");4858}48594860inline void Registers_s390x::setRegister(int regNum, uint64_t value) {4861if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) {4862_registers.__gpr[regNum - UNW_S390X_R0] = value;4863return;4864}48654866switch (regNum) {4867case UNW_S390X_PSWM:4868_registers.__pswm = value;4869return;4870case UNW_S390X_PSWA:4871case UNW_REG_IP:4872_registers.__pswa = value;4873return;4874case UNW_REG_SP:4875_registers.__gpr[15] = value;4876return;4877}4878_LIBUNWIND_ABORT("unsupported s390x register");4879}48804881inline bool Registers_s390x::validFloatRegister(int regNum) const {4882return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15;4883}48844885inline double Registers_s390x::getFloatRegister(int regNum) const {4886// NOTE: FPR DWARF register numbers are not consecutive.4887switch (regNum) {4888case UNW_S390X_F0:4889return _registers.__fpr[0];4890case UNW_S390X_F1:4891return _registers.__fpr[1];4892case UNW_S390X_F2:4893return _registers.__fpr[2];4894case UNW_S390X_F3:4895return _registers.__fpr[3];4896case UNW_S390X_F4:4897return _registers.__fpr[4];4898case UNW_S390X_F5:4899return _registers.__fpr[5];4900case UNW_S390X_F6:4901return _registers.__fpr[6];4902case UNW_S390X_F7:4903return _registers.__fpr[7];4904case UNW_S390X_F8:4905return _registers.__fpr[8];4906case UNW_S390X_F9:4907return _registers.__fpr[9];4908case UNW_S390X_F10:4909return _registers.__fpr[10];4910case UNW_S390X_F11:4911return _registers.__fpr[11];4912case UNW_S390X_F12:4913return _registers.__fpr[12];4914case UNW_S390X_F13:4915return _registers.__fpr[13];4916case UNW_S390X_F14:4917return _registers.__fpr[14];4918case UNW_S390X_F15:4919return _registers.__fpr[15];4920}4921_LIBUNWIND_ABORT("unsupported s390x register");4922}49234924inline void Registers_s390x::setFloatRegister(int regNum, double value) {4925// NOTE: FPR DWARF register numbers are not consecutive.4926switch (regNum) {4927case UNW_S390X_F0:4928_registers.__fpr[0] = value;4929return;4930case UNW_S390X_F1:4931_registers.__fpr[1] = value;4932return;4933case UNW_S390X_F2:4934_registers.__fpr[2] = value;4935return;4936case UNW_S390X_F3:4937_registers.__fpr[3] = value;4938return;4939case UNW_S390X_F4:4940_registers.__fpr[4] = value;4941return;4942case UNW_S390X_F5:4943_registers.__fpr[5] = value;4944return;4945case UNW_S390X_F6:4946_registers.__fpr[6] = value;4947return;4948case UNW_S390X_F7:4949_registers.__fpr[7] = value;4950return;4951case UNW_S390X_F8:4952_registers.__fpr[8] = value;4953return;4954case UNW_S390X_F9:4955_registers.__fpr[9] = value;4956return;4957case UNW_S390X_F10:4958_registers.__fpr[10] = value;4959return;4960case UNW_S390X_F11:4961_registers.__fpr[11] = value;4962return;4963case UNW_S390X_F12:4964_registers.__fpr[12] = value;4965return;4966case UNW_S390X_F13:4967_registers.__fpr[13] = value;4968return;4969case UNW_S390X_F14:4970_registers.__fpr[14] = value;4971return;4972case UNW_S390X_F15:4973_registers.__fpr[15] = value;4974return;4975}4976_LIBUNWIND_ABORT("unsupported s390x register");4977}49784979inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {4980return false;4981}49824983inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const {4984_LIBUNWIND_ABORT("s390x vector support not implemented");4985}49864987inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) {4988_LIBUNWIND_ABORT("s390x vector support not implemented");4989}49904991inline const char *Registers_s390x::getRegisterName(int regNum) {4992switch (regNum) {4993case UNW_REG_IP:4994return "ip";4995case UNW_REG_SP:4996return "sp";4997case UNW_S390X_R0:4998return "r0";4999case UNW_S390X_R1:5000return "r1";5001case UNW_S390X_R2:5002return "r2";5003case UNW_S390X_R3:5004return "r3";5005case UNW_S390X_R4:5006return "r4";5007case UNW_S390X_R5:5008return "r5";5009case UNW_S390X_R6:5010return "r6";5011case UNW_S390X_R7:5012return "r7";5013case UNW_S390X_R8:5014return "r8";5015case UNW_S390X_R9:5016return "r9";5017case UNW_S390X_R10:5018return "r10";5019case UNW_S390X_R11:5020return "r11";5021case UNW_S390X_R12:5022return "r12";5023case UNW_S390X_R13:5024return "r13";5025case UNW_S390X_R14:5026return "r14";5027case UNW_S390X_R15:5028return "r15";5029case UNW_S390X_F0:5030return "f0";5031case UNW_S390X_F1:5032return "f1";5033case UNW_S390X_F2:5034return "f2";5035case UNW_S390X_F3:5036return "f3";5037case UNW_S390X_F4:5038return "f4";5039case UNW_S390X_F5:5040return "f5";5041case UNW_S390X_F6:5042return "f6";5043case UNW_S390X_F7:5044return "f7";5045case UNW_S390X_F8:5046return "f8";5047case UNW_S390X_F9:5048return "f9";5049case UNW_S390X_F10:5050return "f10";5051case UNW_S390X_F11:5052return "f11";5053case UNW_S390X_F12:5054return "f12";5055case UNW_S390X_F13:5056return "f13";5057case UNW_S390X_F14:5058return "f14";5059case UNW_S390X_F15:5060return "f15";5061}5062return "unknown register";5063}5064#endif // _LIBUNWIND_TARGET_S390X50655066#if defined(_LIBUNWIND_TARGET_LOONGARCH)5067/// Registers_loongarch holds the register state of a thread in a 64-bit5068/// LoongArch process.5069class _LIBUNWIND_HIDDEN Registers_loongarch {5070public:5071Registers_loongarch();5072Registers_loongarch(const void *registers);50735074bool validRegister(int num) const;5075uint64_t getRegister(int num) const;5076void setRegister(int num, uint64_t value);5077bool validFloatRegister(int num) const;5078double getFloatRegister(int num) const;5079void setFloatRegister(int num, double value);5080bool validVectorRegister(int num) const;5081v128 getVectorRegister(int num) const;5082void setVectorRegister(int num, v128 value);5083static const char *getRegisterName(int num);5084void jumpto();5085static constexpr int lastDwarfRegNum() {5086return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH;5087}5088static int getArch() { return REGISTERS_LOONGARCH; }50895090uint64_t getSP() const { return _registers.__r[3]; }5091void setSP(uint64_t value) { _registers.__r[3] = value; }5092uint64_t getIP() const { return _registers.__pc; }5093void setIP(uint64_t value) { _registers.__pc = value; }50945095private:5096struct loongarch_thread_state_t {5097uint64_t __r[32];5098uint64_t __pc;5099};51005101loongarch_thread_state_t _registers;5102#if __loongarch_frlen == 645103double _floats[32];5104#endif5105};51065107inline Registers_loongarch::Registers_loongarch(const void *registers) {5108static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit),5109"loongarch registers do not fit into unw_context_t");5110memcpy(&_registers, registers, sizeof(_registers));5111static_assert(sizeof(_registers) == 0x108,5112"expected float registers to be at offset 264");5113#if __loongarch_frlen == 645114memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers),5115sizeof(_floats));5116#endif5117}51185119inline Registers_loongarch::Registers_loongarch() {5120memset(&_registers, 0, sizeof(_registers));5121#if __loongarch_frlen == 645122memset(&_floats, 0, sizeof(_floats));5123#endif5124}51255126inline bool Registers_loongarch::validRegister(int regNum) const {5127if (regNum == UNW_REG_IP || regNum == UNW_REG_SP)5128return true;5129if (regNum < 0 || regNum > UNW_LOONGARCH_F31)5130return false;5131return true;5132}51335134inline uint64_t Registers_loongarch::getRegister(int regNum) const {5135if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)5136return _registers.__r[regNum - UNW_LOONGARCH_R0];51375138if (regNum == UNW_REG_IP)5139return _registers.__pc;5140if (regNum == UNW_REG_SP)5141return _registers.__r[3];5142_LIBUNWIND_ABORT("unsupported loongarch register");5143}51445145inline void Registers_loongarch::setRegister(int regNum, uint64_t value) {5146if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)5147_registers.__r[regNum - UNW_LOONGARCH_R0] = value;5148else if (regNum == UNW_REG_IP)5149_registers.__pc = value;5150else if (regNum == UNW_REG_SP)5151_registers.__r[3] = value;5152else5153_LIBUNWIND_ABORT("unsupported loongarch register");5154}51555156inline const char *Registers_loongarch::getRegisterName(int regNum) {5157switch (regNum) {5158case UNW_REG_IP:5159return "$pc";5160case UNW_REG_SP:5161return "$sp";5162case UNW_LOONGARCH_R0:5163return "$r0";5164case UNW_LOONGARCH_R1:5165return "$r1";5166case UNW_LOONGARCH_R2:5167return "$r2";5168case UNW_LOONGARCH_R3:5169return "$r3";5170case UNW_LOONGARCH_R4:5171return "$r4";5172case UNW_LOONGARCH_R5:5173return "$r5";5174case UNW_LOONGARCH_R6:5175return "$r6";5176case UNW_LOONGARCH_R7:5177return "$r7";5178case UNW_LOONGARCH_R8:5179return "$r8";5180case UNW_LOONGARCH_R9:5181return "$r9";5182case UNW_LOONGARCH_R10:5183return "$r10";5184case UNW_LOONGARCH_R11:5185return "$r11";5186case UNW_LOONGARCH_R12:5187return "$r12";5188case UNW_LOONGARCH_R13:5189return "$r13";5190case UNW_LOONGARCH_R14:5191return "$r14";5192case UNW_LOONGARCH_R15:5193return "$r15";5194case UNW_LOONGARCH_R16:5195return "$r16";5196case UNW_LOONGARCH_R17:5197return "$r17";5198case UNW_LOONGARCH_R18:5199return "$r18";5200case UNW_LOONGARCH_R19:5201return "$r19";5202case UNW_LOONGARCH_R20:5203return "$r20";5204case UNW_LOONGARCH_R21:5205return "$r21";5206case UNW_LOONGARCH_R22:5207return "$r22";5208case UNW_LOONGARCH_R23:5209return "$r23";5210case UNW_LOONGARCH_R24:5211return "$r24";5212case UNW_LOONGARCH_R25:5213return "$r25";5214case UNW_LOONGARCH_R26:5215return "$r26";5216case UNW_LOONGARCH_R27:5217return "$r27";5218case UNW_LOONGARCH_R28:5219return "$r28";5220case UNW_LOONGARCH_R29:5221return "$r29";5222case UNW_LOONGARCH_R30:5223return "$r30";5224case UNW_LOONGARCH_R31:5225return "$r31";5226case UNW_LOONGARCH_F0:5227return "$f0";5228case UNW_LOONGARCH_F1:5229return "$f1";5230case UNW_LOONGARCH_F2:5231return "$f2";5232case UNW_LOONGARCH_F3:5233return "$f3";5234case UNW_LOONGARCH_F4:5235return "$f4";5236case UNW_LOONGARCH_F5:5237return "$f5";5238case UNW_LOONGARCH_F6:5239return "$f6";5240case UNW_LOONGARCH_F7:5241return "$f7";5242case UNW_LOONGARCH_F8:5243return "$f8";5244case UNW_LOONGARCH_F9:5245return "$f9";5246case UNW_LOONGARCH_F10:5247return "$f10";5248case UNW_LOONGARCH_F11:5249return "$f11";5250case UNW_LOONGARCH_F12:5251return "$f12";5252case UNW_LOONGARCH_F13:5253return "$f13";5254case UNW_LOONGARCH_F14:5255return "$f14";5256case UNW_LOONGARCH_F15:5257return "$f15";5258case UNW_LOONGARCH_F16:5259return "$f16";5260case UNW_LOONGARCH_F17:5261return "$f17";5262case UNW_LOONGARCH_F18:5263return "$f18";5264case UNW_LOONGARCH_F19:5265return "$f19";5266case UNW_LOONGARCH_F20:5267return "$f20";5268case UNW_LOONGARCH_F21:5269return "$f21";5270case UNW_LOONGARCH_F22:5271return "$f22";5272case UNW_LOONGARCH_F23:5273return "$f23";5274case UNW_LOONGARCH_F24:5275return "$f24";5276case UNW_LOONGARCH_F25:5277return "$f25";5278case UNW_LOONGARCH_F26:5279return "$f26";5280case UNW_LOONGARCH_F27:5281return "$f27";5282case UNW_LOONGARCH_F28:5283return "$f28";5284case UNW_LOONGARCH_F29:5285return "$f29";5286case UNW_LOONGARCH_F30:5287return "$f30";5288case UNW_LOONGARCH_F31:5289return "$f31";5290default:5291return "unknown register";5292}5293}52945295inline bool Registers_loongarch::validFloatRegister(int regNum) const {5296if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31)5297return false;5298return true;5299}53005301inline double Registers_loongarch::getFloatRegister(int regNum) const {5302#if __loongarch_frlen == 645303assert(validFloatRegister(regNum));5304return _floats[regNum - UNW_LOONGARCH_F0];5305#else5306_LIBUNWIND_ABORT("libunwind not built with float support");5307#endif5308}53095310inline void Registers_loongarch::setFloatRegister(int regNum, double value) {5311#if __loongarch_frlen == 645312assert(validFloatRegister(regNum));5313_floats[regNum - UNW_LOONGARCH_F0] = value;5314#else5315_LIBUNWIND_ABORT("libunwind not built with float support");5316#endif5317}53185319inline bool Registers_loongarch::validVectorRegister(int) const {5320return false;5321}53225323inline v128 Registers_loongarch::getVectorRegister(int) const {5324_LIBUNWIND_ABORT("loongarch vector support not implemented");5325}53265327inline void Registers_loongarch::setVectorRegister(int, v128) {5328_LIBUNWIND_ABORT("loongarch vector support not implemented");5329}5330#endif //_LIBUNWIND_TARGET_LOONGARCH53315332} // namespace libunwind53335334#endif // __REGISTERS_HPP__533553365337