1*202cdb0eSrobert //===----------------------------------------------------------------------===//
2f6c50668Spatrick //
3f6c50668Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f6c50668Spatrick // See https://llvm.org/LICENSE.txt for license information.
5f6c50668Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f6c50668Spatrick //
7f6c50668Spatrick //
8f6c50668Spatrick // Models register sets for supported processors.
9f6c50668Spatrick //
10f6c50668Spatrick //===----------------------------------------------------------------------===//
11f6c50668Spatrick
12f6c50668Spatrick #ifndef __REGISTERS_HPP__
13f6c50668Spatrick #define __REGISTERS_HPP__
14f6c50668Spatrick
15f6c50668Spatrick #include <stdint.h>
16f6c50668Spatrick #include <string.h>
17f6c50668Spatrick
18*202cdb0eSrobert #include "cet_unwind.h"
19f6c50668Spatrick #include "config.h"
20*202cdb0eSrobert #include "libunwind.h"
21f6c50668Spatrick
22f6c50668Spatrick namespace libunwind {
23f6c50668Spatrick
24f6c50668Spatrick // For emulating 128-bit registers
25f6c50668Spatrick struct v128 { uint32_t vec[4]; };
26f6c50668Spatrick
27f6c50668Spatrick enum {
28f6c50668Spatrick REGISTERS_X86,
29f6c50668Spatrick REGISTERS_X86_64,
30f6c50668Spatrick REGISTERS_PPC,
31f6c50668Spatrick REGISTERS_PPC64,
32f6c50668Spatrick REGISTERS_ARM64,
33f6c50668Spatrick REGISTERS_ARM,
34f6c50668Spatrick REGISTERS_OR1K,
35f6c50668Spatrick REGISTERS_MIPS_O32,
36f6c50668Spatrick REGISTERS_MIPS_NEWABI,
37f6c50668Spatrick REGISTERS_SPARC,
38974930e3Spatrick REGISTERS_SPARC64,
39f6c50668Spatrick REGISTERS_HEXAGON,
40f6c50668Spatrick REGISTERS_RISCV,
41a0747c9fSpatrick REGISTERS_VE,
42*202cdb0eSrobert REGISTERS_S390X,
43*202cdb0eSrobert REGISTERS_LOONGARCH,
44f6c50668Spatrick };
45f6c50668Spatrick
46f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_I386)
47a0747c9fSpatrick class _LIBUNWIND_HIDDEN Registers_x86;
48a0747c9fSpatrick extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
49*202cdb0eSrobert
50*202cdb0eSrobert #if defined(_LIBUNWIND_USE_CET)
__libunwind_cet_get_jump_target()51*202cdb0eSrobert extern "C" void *__libunwind_cet_get_jump_target() {
52*202cdb0eSrobert return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto);
53*202cdb0eSrobert }
54*202cdb0eSrobert #endif
55*202cdb0eSrobert
56f6c50668Spatrick /// Registers_x86 holds the register state of a thread in a 32-bit intel
57f6c50668Spatrick /// process.
58f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_x86 {
59f6c50668Spatrick public:
60f6c50668Spatrick Registers_x86();
61f6c50668Spatrick Registers_x86(const void *registers);
62f6c50668Spatrick
63f6c50668Spatrick bool validRegister(int num) const;
64f6c50668Spatrick uint32_t getRegister(int num) const;
65f6c50668Spatrick void setRegister(int num, uint32_t value);
validFloatRegister(int) const66f6c50668Spatrick bool validFloatRegister(int) const { return false; }
67f6c50668Spatrick double getFloatRegister(int num) const;
68f6c50668Spatrick void setFloatRegister(int num, double value);
validVectorRegister(int) const69f6c50668Spatrick bool validVectorRegister(int) const { return false; }
70f6c50668Spatrick v128 getVectorRegister(int num) const;
71f6c50668Spatrick void setVectorRegister(int num, v128 value);
72f6c50668Spatrick static const char *getRegisterName(int num);
jumpto()73a0747c9fSpatrick void jumpto() { __libunwind_Registers_x86_jumpto(this); }
lastDwarfRegNum()74*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
75*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86;
76*202cdb0eSrobert }
getArch()77f6c50668Spatrick static int getArch() { return REGISTERS_X86; }
78f6c50668Spatrick
getSP() const79f6c50668Spatrick uint32_t getSP() const { return _registers.__esp; }
setSP(uint32_t value)80f6c50668Spatrick void setSP(uint32_t value) { _registers.__esp = value; }
getIP() const81f6c50668Spatrick uint32_t getIP() const { return _registers.__eip; }
setIP(uint32_t value)82f6c50668Spatrick void setIP(uint32_t value) { _registers.__eip = value; }
getEBP() const83f6c50668Spatrick uint32_t getEBP() const { return _registers.__ebp; }
setEBP(uint32_t value)84f6c50668Spatrick void setEBP(uint32_t value) { _registers.__ebp = value; }
getEBX() const85f6c50668Spatrick uint32_t getEBX() const { return _registers.__ebx; }
setEBX(uint32_t value)86f6c50668Spatrick void setEBX(uint32_t value) { _registers.__ebx = value; }
getECX() const87f6c50668Spatrick uint32_t getECX() const { return _registers.__ecx; }
setECX(uint32_t value)88f6c50668Spatrick void setECX(uint32_t value) { _registers.__ecx = value; }
getEDX() const89f6c50668Spatrick uint32_t getEDX() const { return _registers.__edx; }
setEDX(uint32_t value)90f6c50668Spatrick void setEDX(uint32_t value) { _registers.__edx = value; }
getESI() const91f6c50668Spatrick uint32_t getESI() const { return _registers.__esi; }
setESI(uint32_t value)92f6c50668Spatrick void setESI(uint32_t value) { _registers.__esi = value; }
getEDI() const93f6c50668Spatrick uint32_t getEDI() const { return _registers.__edi; }
setEDI(uint32_t value)94f6c50668Spatrick void setEDI(uint32_t value) { _registers.__edi = value; }
95f6c50668Spatrick
96f6c50668Spatrick private:
97f6c50668Spatrick struct GPRs {
98f6c50668Spatrick unsigned int __eax;
99f6c50668Spatrick unsigned int __ebx;
100f6c50668Spatrick unsigned int __ecx;
101f6c50668Spatrick unsigned int __edx;
102f6c50668Spatrick unsigned int __edi;
103f6c50668Spatrick unsigned int __esi;
104f6c50668Spatrick unsigned int __ebp;
105f6c50668Spatrick unsigned int __esp;
106f6c50668Spatrick unsigned int __ss;
107f6c50668Spatrick unsigned int __eflags;
108f6c50668Spatrick unsigned int __eip;
109f6c50668Spatrick unsigned int __cs;
110f6c50668Spatrick unsigned int __ds;
111f6c50668Spatrick unsigned int __es;
112f6c50668Spatrick unsigned int __fs;
113f6c50668Spatrick unsigned int __gs;
114f6c50668Spatrick };
115f6c50668Spatrick
116f6c50668Spatrick GPRs _registers;
117f6c50668Spatrick };
118f6c50668Spatrick
Registers_x86(const void * registers)119f6c50668Spatrick inline Registers_x86::Registers_x86(const void *registers) {
120f6c50668Spatrick static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
121f6c50668Spatrick "x86 registers do not fit into unw_context_t");
122f6c50668Spatrick memcpy(&_registers, registers, sizeof(_registers));
123f6c50668Spatrick }
124f6c50668Spatrick
Registers_x86()125f6c50668Spatrick inline Registers_x86::Registers_x86() {
126f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
127f6c50668Spatrick }
128f6c50668Spatrick
validRegister(int regNum) const129f6c50668Spatrick inline bool Registers_x86::validRegister(int regNum) const {
130f6c50668Spatrick if (regNum == UNW_REG_IP)
131f6c50668Spatrick return true;
132f6c50668Spatrick if (regNum == UNW_REG_SP)
133f6c50668Spatrick return true;
134f6c50668Spatrick if (regNum < 0)
135f6c50668Spatrick return false;
136f6c50668Spatrick if (regNum > 7)
137f6c50668Spatrick return false;
138f6c50668Spatrick return true;
139f6c50668Spatrick }
140f6c50668Spatrick
getRegister(int regNum) const141f6c50668Spatrick inline uint32_t Registers_x86::getRegister(int regNum) const {
142f6c50668Spatrick switch (regNum) {
143f6c50668Spatrick case UNW_REG_IP:
144f6c50668Spatrick return _registers.__eip;
145f6c50668Spatrick case UNW_REG_SP:
146f6c50668Spatrick return _registers.__esp;
147f6c50668Spatrick case UNW_X86_EAX:
148f6c50668Spatrick return _registers.__eax;
149f6c50668Spatrick case UNW_X86_ECX:
150f6c50668Spatrick return _registers.__ecx;
151f6c50668Spatrick case UNW_X86_EDX:
152f6c50668Spatrick return _registers.__edx;
153f6c50668Spatrick case UNW_X86_EBX:
154f6c50668Spatrick return _registers.__ebx;
155f6c50668Spatrick #if !defined(__APPLE__)
156f6c50668Spatrick case UNW_X86_ESP:
157f6c50668Spatrick #else
158f6c50668Spatrick case UNW_X86_EBP:
159f6c50668Spatrick #endif
160f6c50668Spatrick return _registers.__ebp;
161f6c50668Spatrick #if !defined(__APPLE__)
162f6c50668Spatrick case UNW_X86_EBP:
163f6c50668Spatrick #else
164f6c50668Spatrick case UNW_X86_ESP:
165f6c50668Spatrick #endif
166f6c50668Spatrick return _registers.__esp;
167f6c50668Spatrick case UNW_X86_ESI:
168f6c50668Spatrick return _registers.__esi;
169f6c50668Spatrick case UNW_X86_EDI:
170f6c50668Spatrick return _registers.__edi;
171f6c50668Spatrick }
172f6c50668Spatrick _LIBUNWIND_ABORT("unsupported x86 register");
173f6c50668Spatrick }
174f6c50668Spatrick
setRegister(int regNum,uint32_t value)175f6c50668Spatrick inline void Registers_x86::setRegister(int regNum, uint32_t value) {
176f6c50668Spatrick switch (regNum) {
177f6c50668Spatrick case UNW_REG_IP:
178f6c50668Spatrick _registers.__eip = value;
179f6c50668Spatrick return;
180f6c50668Spatrick case UNW_REG_SP:
181f6c50668Spatrick _registers.__esp = value;
182f6c50668Spatrick return;
183f6c50668Spatrick case UNW_X86_EAX:
184f6c50668Spatrick _registers.__eax = value;
185f6c50668Spatrick return;
186f6c50668Spatrick case UNW_X86_ECX:
187f6c50668Spatrick _registers.__ecx = value;
188f6c50668Spatrick return;
189f6c50668Spatrick case UNW_X86_EDX:
190f6c50668Spatrick _registers.__edx = value;
191f6c50668Spatrick return;
192f6c50668Spatrick case UNW_X86_EBX:
193f6c50668Spatrick _registers.__ebx = value;
194f6c50668Spatrick return;
195f6c50668Spatrick #if !defined(__APPLE__)
196f6c50668Spatrick case UNW_X86_ESP:
197f6c50668Spatrick #else
198f6c50668Spatrick case UNW_X86_EBP:
199f6c50668Spatrick #endif
200f6c50668Spatrick _registers.__ebp = value;
201f6c50668Spatrick return;
202f6c50668Spatrick #if !defined(__APPLE__)
203f6c50668Spatrick case UNW_X86_EBP:
204f6c50668Spatrick #else
205f6c50668Spatrick case UNW_X86_ESP:
206f6c50668Spatrick #endif
207f6c50668Spatrick _registers.__esp = value;
208f6c50668Spatrick return;
209f6c50668Spatrick case UNW_X86_ESI:
210f6c50668Spatrick _registers.__esi = value;
211f6c50668Spatrick return;
212f6c50668Spatrick case UNW_X86_EDI:
213f6c50668Spatrick _registers.__edi = value;
214f6c50668Spatrick return;
215f6c50668Spatrick }
216f6c50668Spatrick _LIBUNWIND_ABORT("unsupported x86 register");
217f6c50668Spatrick }
218f6c50668Spatrick
getRegisterName(int regNum)219f6c50668Spatrick inline const char *Registers_x86::getRegisterName(int regNum) {
220f6c50668Spatrick switch (regNum) {
221f6c50668Spatrick case UNW_REG_IP:
222f6c50668Spatrick return "ip";
223f6c50668Spatrick case UNW_REG_SP:
224f6c50668Spatrick return "esp";
225f6c50668Spatrick case UNW_X86_EAX:
226f6c50668Spatrick return "eax";
227f6c50668Spatrick case UNW_X86_ECX:
228f6c50668Spatrick return "ecx";
229f6c50668Spatrick case UNW_X86_EDX:
230f6c50668Spatrick return "edx";
231f6c50668Spatrick case UNW_X86_EBX:
232f6c50668Spatrick return "ebx";
233f6c50668Spatrick case UNW_X86_EBP:
234f6c50668Spatrick return "ebp";
235f6c50668Spatrick case UNW_X86_ESP:
236f6c50668Spatrick return "esp";
237f6c50668Spatrick case UNW_X86_ESI:
238f6c50668Spatrick return "esi";
239f6c50668Spatrick case UNW_X86_EDI:
240f6c50668Spatrick return "edi";
241f6c50668Spatrick default:
242f6c50668Spatrick return "unknown register";
243f6c50668Spatrick }
244f6c50668Spatrick }
245f6c50668Spatrick
getFloatRegister(int) const246f6c50668Spatrick inline double Registers_x86::getFloatRegister(int) const {
247f6c50668Spatrick _LIBUNWIND_ABORT("no x86 float registers");
248f6c50668Spatrick }
249f6c50668Spatrick
setFloatRegister(int,double)250f6c50668Spatrick inline void Registers_x86::setFloatRegister(int, double) {
251f6c50668Spatrick _LIBUNWIND_ABORT("no x86 float registers");
252f6c50668Spatrick }
253f6c50668Spatrick
getVectorRegister(int) const254f6c50668Spatrick inline v128 Registers_x86::getVectorRegister(int) const {
255f6c50668Spatrick _LIBUNWIND_ABORT("no x86 vector registers");
256f6c50668Spatrick }
257f6c50668Spatrick
setVectorRegister(int,v128)258f6c50668Spatrick inline void Registers_x86::setVectorRegister(int, v128) {
259f6c50668Spatrick _LIBUNWIND_ABORT("no x86 vector registers");
260f6c50668Spatrick }
261f6c50668Spatrick #endif // _LIBUNWIND_TARGET_I386
262f6c50668Spatrick
263f6c50668Spatrick
264f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_X86_64)
265f6c50668Spatrick /// Registers_x86_64 holds the register state of a thread in a 64-bit intel
266f6c50668Spatrick /// process.
267a0747c9fSpatrick class _LIBUNWIND_HIDDEN Registers_x86_64;
268a0747c9fSpatrick extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
269*202cdb0eSrobert
270*202cdb0eSrobert #if defined(_LIBUNWIND_USE_CET)
__libunwind_cet_get_jump_target()271*202cdb0eSrobert extern "C" void *__libunwind_cet_get_jump_target() {
272*202cdb0eSrobert return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto);
273*202cdb0eSrobert }
274*202cdb0eSrobert #endif
275*202cdb0eSrobert
276f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_x86_64 {
277f6c50668Spatrick public:
278f6c50668Spatrick Registers_x86_64();
279f6c50668Spatrick Registers_x86_64(const void *registers);
280f6c50668Spatrick
281f6c50668Spatrick bool validRegister(int num) const;
282f6c50668Spatrick uint64_t getRegister(int num) const;
283f6c50668Spatrick void setRegister(int num, uint64_t value);
validFloatRegister(int) const284f6c50668Spatrick bool validFloatRegister(int) const { return false; }
285f6c50668Spatrick double getFloatRegister(int num) const;
286f6c50668Spatrick void setFloatRegister(int num, double value);
287f6c50668Spatrick bool validVectorRegister(int) const;
288f6c50668Spatrick v128 getVectorRegister(int num) const;
289f6c50668Spatrick void setVectorRegister(int num, v128 value);
290f6c50668Spatrick static const char *getRegisterName(int num);
jumpto()291a0747c9fSpatrick void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }
lastDwarfRegNum()292*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
293*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64;
294*202cdb0eSrobert }
getArch()295f6c50668Spatrick static int getArch() { return REGISTERS_X86_64; }
296f6c50668Spatrick
getSP() const297f6c50668Spatrick uint64_t getSP() const { return _registers.__rsp; }
setSP(uint64_t value)298f6c50668Spatrick void setSP(uint64_t value) { _registers.__rsp = value; }
getIP() const299f6c50668Spatrick uint64_t getIP() const { return _registers.__rip; }
setIP(uint64_t value)300f6c50668Spatrick void setIP(uint64_t value) { _registers.__rip = value; }
getRBP() const301f6c50668Spatrick uint64_t getRBP() const { return _registers.__rbp; }
setRBP(uint64_t value)302f6c50668Spatrick void setRBP(uint64_t value) { _registers.__rbp = value; }
getRBX() const303f6c50668Spatrick uint64_t getRBX() const { return _registers.__rbx; }
setRBX(uint64_t value)304f6c50668Spatrick void setRBX(uint64_t value) { _registers.__rbx = value; }
getR12() const305f6c50668Spatrick uint64_t getR12() const { return _registers.__r12; }
setR12(uint64_t value)306f6c50668Spatrick void setR12(uint64_t value) { _registers.__r12 = value; }
getR13() const307f6c50668Spatrick uint64_t getR13() const { return _registers.__r13; }
setR13(uint64_t value)308f6c50668Spatrick void setR13(uint64_t value) { _registers.__r13 = value; }
getR14() const309f6c50668Spatrick uint64_t getR14() const { return _registers.__r14; }
setR14(uint64_t value)310f6c50668Spatrick void setR14(uint64_t value) { _registers.__r14 = value; }
getR15() const311f6c50668Spatrick uint64_t getR15() const { return _registers.__r15; }
setR15(uint64_t value)312f6c50668Spatrick void setR15(uint64_t value) { _registers.__r15 = value; }
313f6c50668Spatrick
314f6c50668Spatrick private:
315f6c50668Spatrick struct GPRs {
316f6c50668Spatrick uint64_t __rax;
317f6c50668Spatrick uint64_t __rbx;
318f6c50668Spatrick uint64_t __rcx;
319f6c50668Spatrick uint64_t __rdx;
320f6c50668Spatrick uint64_t __rdi;
321f6c50668Spatrick uint64_t __rsi;
322f6c50668Spatrick uint64_t __rbp;
323f6c50668Spatrick uint64_t __rsp;
324f6c50668Spatrick uint64_t __r8;
325f6c50668Spatrick uint64_t __r9;
326f6c50668Spatrick uint64_t __r10;
327f6c50668Spatrick uint64_t __r11;
328f6c50668Spatrick uint64_t __r12;
329f6c50668Spatrick uint64_t __r13;
330f6c50668Spatrick uint64_t __r14;
331f6c50668Spatrick uint64_t __r15;
332f6c50668Spatrick uint64_t __rip;
333f6c50668Spatrick uint64_t __rflags;
334f6c50668Spatrick uint64_t __cs;
335f6c50668Spatrick uint64_t __fs;
336f6c50668Spatrick uint64_t __gs;
337f6c50668Spatrick #if defined(_WIN64)
338f6c50668Spatrick uint64_t __padding; // 16-byte align
339f6c50668Spatrick #endif
340f6c50668Spatrick };
341f6c50668Spatrick GPRs _registers;
342f6c50668Spatrick #if defined(_WIN64)
343f6c50668Spatrick v128 _xmm[16];
344f6c50668Spatrick #endif
345f6c50668Spatrick };
346f6c50668Spatrick
Registers_x86_64(const void * registers)347f6c50668Spatrick inline Registers_x86_64::Registers_x86_64(const void *registers) {
348f6c50668Spatrick static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
349f6c50668Spatrick "x86_64 registers do not fit into unw_context_t");
350f6c50668Spatrick memcpy(&_registers, registers, sizeof(_registers));
351f6c50668Spatrick }
352f6c50668Spatrick
Registers_x86_64()353f6c50668Spatrick inline Registers_x86_64::Registers_x86_64() {
354f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
355f6c50668Spatrick }
356f6c50668Spatrick
validRegister(int regNum) const357f6c50668Spatrick inline bool Registers_x86_64::validRegister(int regNum) const {
358f6c50668Spatrick if (regNum == UNW_REG_IP)
359f6c50668Spatrick return true;
360f6c50668Spatrick if (regNum == UNW_REG_SP)
361f6c50668Spatrick return true;
362f6c50668Spatrick if (regNum < 0)
363f6c50668Spatrick return false;
364*202cdb0eSrobert if (regNum > 16)
365f6c50668Spatrick return false;
366f6c50668Spatrick return true;
367f6c50668Spatrick }
368f6c50668Spatrick
getRegister(int regNum) const369f6c50668Spatrick inline uint64_t Registers_x86_64::getRegister(int regNum) const {
370f6c50668Spatrick switch (regNum) {
371f6c50668Spatrick case UNW_REG_IP:
372*202cdb0eSrobert case UNW_X86_64_RIP:
373f6c50668Spatrick return _registers.__rip;
374f6c50668Spatrick case UNW_REG_SP:
375f6c50668Spatrick return _registers.__rsp;
376f6c50668Spatrick case UNW_X86_64_RAX:
377f6c50668Spatrick return _registers.__rax;
378f6c50668Spatrick case UNW_X86_64_RDX:
379f6c50668Spatrick return _registers.__rdx;
380f6c50668Spatrick case UNW_X86_64_RCX:
381f6c50668Spatrick return _registers.__rcx;
382f6c50668Spatrick case UNW_X86_64_RBX:
383f6c50668Spatrick return _registers.__rbx;
384f6c50668Spatrick case UNW_X86_64_RSI:
385f6c50668Spatrick return _registers.__rsi;
386f6c50668Spatrick case UNW_X86_64_RDI:
387f6c50668Spatrick return _registers.__rdi;
388f6c50668Spatrick case UNW_X86_64_RBP:
389f6c50668Spatrick return _registers.__rbp;
390f6c50668Spatrick case UNW_X86_64_RSP:
391f6c50668Spatrick return _registers.__rsp;
392f6c50668Spatrick case UNW_X86_64_R8:
393f6c50668Spatrick return _registers.__r8;
394f6c50668Spatrick case UNW_X86_64_R9:
395f6c50668Spatrick return _registers.__r9;
396f6c50668Spatrick case UNW_X86_64_R10:
397f6c50668Spatrick return _registers.__r10;
398f6c50668Spatrick case UNW_X86_64_R11:
399f6c50668Spatrick return _registers.__r11;
400f6c50668Spatrick case UNW_X86_64_R12:
401f6c50668Spatrick return _registers.__r12;
402f6c50668Spatrick case UNW_X86_64_R13:
403f6c50668Spatrick return _registers.__r13;
404f6c50668Spatrick case UNW_X86_64_R14:
405f6c50668Spatrick return _registers.__r14;
406f6c50668Spatrick case UNW_X86_64_R15:
407f6c50668Spatrick return _registers.__r15;
408f6c50668Spatrick }
409f6c50668Spatrick _LIBUNWIND_ABORT("unsupported x86_64 register");
410f6c50668Spatrick }
411f6c50668Spatrick
setRegister(int regNum,uint64_t value)412f6c50668Spatrick inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
413f6c50668Spatrick switch (regNum) {
414f6c50668Spatrick case UNW_REG_IP:
415*202cdb0eSrobert case UNW_X86_64_RIP:
416f6c50668Spatrick _registers.__rip = value;
417f6c50668Spatrick return;
418f6c50668Spatrick case UNW_REG_SP:
419f6c50668Spatrick _registers.__rsp = value;
420f6c50668Spatrick return;
421f6c50668Spatrick case UNW_X86_64_RAX:
422f6c50668Spatrick _registers.__rax = value;
423f6c50668Spatrick return;
424f6c50668Spatrick case UNW_X86_64_RDX:
425f6c50668Spatrick _registers.__rdx = value;
426f6c50668Spatrick return;
427f6c50668Spatrick case UNW_X86_64_RCX:
428f6c50668Spatrick _registers.__rcx = value;
429f6c50668Spatrick return;
430f6c50668Spatrick case UNW_X86_64_RBX:
431f6c50668Spatrick _registers.__rbx = value;
432f6c50668Spatrick return;
433f6c50668Spatrick case UNW_X86_64_RSI:
434f6c50668Spatrick _registers.__rsi = value;
435f6c50668Spatrick return;
436f6c50668Spatrick case UNW_X86_64_RDI:
437f6c50668Spatrick _registers.__rdi = value;
438f6c50668Spatrick return;
439f6c50668Spatrick case UNW_X86_64_RBP:
440f6c50668Spatrick _registers.__rbp = value;
441f6c50668Spatrick return;
442f6c50668Spatrick case UNW_X86_64_RSP:
443f6c50668Spatrick _registers.__rsp = value;
444f6c50668Spatrick return;
445f6c50668Spatrick case UNW_X86_64_R8:
446f6c50668Spatrick _registers.__r8 = value;
447f6c50668Spatrick return;
448f6c50668Spatrick case UNW_X86_64_R9:
449f6c50668Spatrick _registers.__r9 = value;
450f6c50668Spatrick return;
451f6c50668Spatrick case UNW_X86_64_R10:
452f6c50668Spatrick _registers.__r10 = value;
453f6c50668Spatrick return;
454f6c50668Spatrick case UNW_X86_64_R11:
455f6c50668Spatrick _registers.__r11 = value;
456f6c50668Spatrick return;
457f6c50668Spatrick case UNW_X86_64_R12:
458f6c50668Spatrick _registers.__r12 = value;
459f6c50668Spatrick return;
460f6c50668Spatrick case UNW_X86_64_R13:
461f6c50668Spatrick _registers.__r13 = value;
462f6c50668Spatrick return;
463f6c50668Spatrick case UNW_X86_64_R14:
464f6c50668Spatrick _registers.__r14 = value;
465f6c50668Spatrick return;
466f6c50668Spatrick case UNW_X86_64_R15:
467f6c50668Spatrick _registers.__r15 = value;
468f6c50668Spatrick return;
469f6c50668Spatrick }
470f6c50668Spatrick _LIBUNWIND_ABORT("unsupported x86_64 register");
471f6c50668Spatrick }
472f6c50668Spatrick
getRegisterName(int regNum)473f6c50668Spatrick inline const char *Registers_x86_64::getRegisterName(int regNum) {
474f6c50668Spatrick switch (regNum) {
475f6c50668Spatrick case UNW_REG_IP:
476*202cdb0eSrobert case UNW_X86_64_RIP:
477f6c50668Spatrick return "rip";
478f6c50668Spatrick case UNW_REG_SP:
479f6c50668Spatrick return "rsp";
480f6c50668Spatrick case UNW_X86_64_RAX:
481f6c50668Spatrick return "rax";
482f6c50668Spatrick case UNW_X86_64_RDX:
483f6c50668Spatrick return "rdx";
484f6c50668Spatrick case UNW_X86_64_RCX:
485f6c50668Spatrick return "rcx";
486f6c50668Spatrick case UNW_X86_64_RBX:
487f6c50668Spatrick return "rbx";
488f6c50668Spatrick case UNW_X86_64_RSI:
489f6c50668Spatrick return "rsi";
490f6c50668Spatrick case UNW_X86_64_RDI:
491f6c50668Spatrick return "rdi";
492f6c50668Spatrick case UNW_X86_64_RBP:
493f6c50668Spatrick return "rbp";
494f6c50668Spatrick case UNW_X86_64_RSP:
495f6c50668Spatrick return "rsp";
496f6c50668Spatrick case UNW_X86_64_R8:
497f6c50668Spatrick return "r8";
498f6c50668Spatrick case UNW_X86_64_R9:
499f6c50668Spatrick return "r9";
500f6c50668Spatrick case UNW_X86_64_R10:
501f6c50668Spatrick return "r10";
502f6c50668Spatrick case UNW_X86_64_R11:
503f6c50668Spatrick return "r11";
504f6c50668Spatrick case UNW_X86_64_R12:
505f6c50668Spatrick return "r12";
506f6c50668Spatrick case UNW_X86_64_R13:
507f6c50668Spatrick return "r13";
508f6c50668Spatrick case UNW_X86_64_R14:
509f6c50668Spatrick return "r14";
510f6c50668Spatrick case UNW_X86_64_R15:
511f6c50668Spatrick return "r15";
512f6c50668Spatrick case UNW_X86_64_XMM0:
513f6c50668Spatrick return "xmm0";
514f6c50668Spatrick case UNW_X86_64_XMM1:
515f6c50668Spatrick return "xmm1";
516f6c50668Spatrick case UNW_X86_64_XMM2:
517f6c50668Spatrick return "xmm2";
518f6c50668Spatrick case UNW_X86_64_XMM3:
519f6c50668Spatrick return "xmm3";
520f6c50668Spatrick case UNW_X86_64_XMM4:
521f6c50668Spatrick return "xmm4";
522f6c50668Spatrick case UNW_X86_64_XMM5:
523f6c50668Spatrick return "xmm5";
524f6c50668Spatrick case UNW_X86_64_XMM6:
525f6c50668Spatrick return "xmm6";
526f6c50668Spatrick case UNW_X86_64_XMM7:
527f6c50668Spatrick return "xmm7";
528f6c50668Spatrick case UNW_X86_64_XMM8:
529f6c50668Spatrick return "xmm8";
530f6c50668Spatrick case UNW_X86_64_XMM9:
531f6c50668Spatrick return "xmm9";
532f6c50668Spatrick case UNW_X86_64_XMM10:
533f6c50668Spatrick return "xmm10";
534f6c50668Spatrick case UNW_X86_64_XMM11:
535f6c50668Spatrick return "xmm11";
536f6c50668Spatrick case UNW_X86_64_XMM12:
537f6c50668Spatrick return "xmm12";
538f6c50668Spatrick case UNW_X86_64_XMM13:
539f6c50668Spatrick return "xmm13";
540f6c50668Spatrick case UNW_X86_64_XMM14:
541f6c50668Spatrick return "xmm14";
542f6c50668Spatrick case UNW_X86_64_XMM15:
543f6c50668Spatrick return "xmm15";
544f6c50668Spatrick default:
545f6c50668Spatrick return "unknown register";
546f6c50668Spatrick }
547f6c50668Spatrick }
548f6c50668Spatrick
getFloatRegister(int) const549f6c50668Spatrick inline double Registers_x86_64::getFloatRegister(int) const {
550f6c50668Spatrick _LIBUNWIND_ABORT("no x86_64 float registers");
551f6c50668Spatrick }
552f6c50668Spatrick
setFloatRegister(int,double)553f6c50668Spatrick inline void Registers_x86_64::setFloatRegister(int, double) {
554f6c50668Spatrick _LIBUNWIND_ABORT("no x86_64 float registers");
555f6c50668Spatrick }
556f6c50668Spatrick
validVectorRegister(int regNum) const557f6c50668Spatrick inline bool Registers_x86_64::validVectorRegister(int regNum) const {
558f6c50668Spatrick #if defined(_WIN64)
559f6c50668Spatrick if (regNum < UNW_X86_64_XMM0)
560f6c50668Spatrick return false;
561f6c50668Spatrick if (regNum > UNW_X86_64_XMM15)
562f6c50668Spatrick return false;
563f6c50668Spatrick return true;
564f6c50668Spatrick #else
565f6c50668Spatrick (void)regNum; // suppress unused parameter warning
566f6c50668Spatrick return false;
567f6c50668Spatrick #endif
568f6c50668Spatrick }
569f6c50668Spatrick
getVectorRegister(int regNum) const570f6c50668Spatrick inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
571f6c50668Spatrick #if defined(_WIN64)
572f6c50668Spatrick assert(validVectorRegister(regNum));
573f6c50668Spatrick return _xmm[regNum - UNW_X86_64_XMM0];
574f6c50668Spatrick #else
575f6c50668Spatrick (void)regNum; // suppress unused parameter warning
576f6c50668Spatrick _LIBUNWIND_ABORT("no x86_64 vector registers");
577f6c50668Spatrick #endif
578f6c50668Spatrick }
579f6c50668Spatrick
setVectorRegister(int regNum,v128 value)580f6c50668Spatrick inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
581f6c50668Spatrick #if defined(_WIN64)
582f6c50668Spatrick assert(validVectorRegister(regNum));
583f6c50668Spatrick _xmm[regNum - UNW_X86_64_XMM0] = value;
584f6c50668Spatrick #else
585f6c50668Spatrick (void)regNum; (void)value; // suppress unused parameter warnings
586f6c50668Spatrick _LIBUNWIND_ABORT("no x86_64 vector registers");
587f6c50668Spatrick #endif
588f6c50668Spatrick }
589f6c50668Spatrick #endif // _LIBUNWIND_TARGET_X86_64
590f6c50668Spatrick
591f6c50668Spatrick
592f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_PPC)
593f6c50668Spatrick /// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
594f6c50668Spatrick /// process.
595f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_ppc {
596f6c50668Spatrick public:
597f6c50668Spatrick Registers_ppc();
598f6c50668Spatrick Registers_ppc(const void *registers);
599f6c50668Spatrick
600f6c50668Spatrick bool validRegister(int num) const;
601f6c50668Spatrick uint32_t getRegister(int num) const;
602f6c50668Spatrick void setRegister(int num, uint32_t value);
603f6c50668Spatrick bool validFloatRegister(int num) const;
604f6c50668Spatrick double getFloatRegister(int num) const;
605f6c50668Spatrick void setFloatRegister(int num, double value);
606f6c50668Spatrick bool validVectorRegister(int num) const;
607f6c50668Spatrick v128 getVectorRegister(int num) const;
608f6c50668Spatrick void setVectorRegister(int num, v128 value);
609f6c50668Spatrick static const char *getRegisterName(int num);
610f6c50668Spatrick void jumpto();
lastDwarfRegNum()611*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
612*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC;
613*202cdb0eSrobert }
getArch()614f6c50668Spatrick static int getArch() { return REGISTERS_PPC; }
615f6c50668Spatrick
getSP() const616f6c50668Spatrick uint64_t getSP() const { return _registers.__r1; }
setSP(uint32_t value)617f6c50668Spatrick void setSP(uint32_t value) { _registers.__r1 = value; }
getIP() const618f6c50668Spatrick uint64_t getIP() const { return _registers.__srr0; }
setIP(uint32_t value)619f6c50668Spatrick void setIP(uint32_t value) { _registers.__srr0 = value; }
getCR() const620*202cdb0eSrobert uint64_t getCR() const { return _registers.__cr; }
setCR(uint32_t value)621*202cdb0eSrobert void setCR(uint32_t value) { _registers.__cr = value; }
622f6c50668Spatrick
623f6c50668Spatrick private:
624f6c50668Spatrick struct ppc_thread_state_t {
625f6c50668Spatrick unsigned int __srr0; /* Instruction address register (PC) */
626f6c50668Spatrick unsigned int __srr1; /* Machine state register (supervisor) */
627f6c50668Spatrick unsigned int __r0;
628f6c50668Spatrick unsigned int __r1;
629f6c50668Spatrick unsigned int __r2;
630f6c50668Spatrick unsigned int __r3;
631f6c50668Spatrick unsigned int __r4;
632f6c50668Spatrick unsigned int __r5;
633f6c50668Spatrick unsigned int __r6;
634f6c50668Spatrick unsigned int __r7;
635f6c50668Spatrick unsigned int __r8;
636f6c50668Spatrick unsigned int __r9;
637f6c50668Spatrick unsigned int __r10;
638f6c50668Spatrick unsigned int __r11;
639f6c50668Spatrick unsigned int __r12;
640f6c50668Spatrick unsigned int __r13;
641f6c50668Spatrick unsigned int __r14;
642f6c50668Spatrick unsigned int __r15;
643f6c50668Spatrick unsigned int __r16;
644f6c50668Spatrick unsigned int __r17;
645f6c50668Spatrick unsigned int __r18;
646f6c50668Spatrick unsigned int __r19;
647f6c50668Spatrick unsigned int __r20;
648f6c50668Spatrick unsigned int __r21;
649f6c50668Spatrick unsigned int __r22;
650f6c50668Spatrick unsigned int __r23;
651f6c50668Spatrick unsigned int __r24;
652f6c50668Spatrick unsigned int __r25;
653f6c50668Spatrick unsigned int __r26;
654f6c50668Spatrick unsigned int __r27;
655f6c50668Spatrick unsigned int __r28;
656f6c50668Spatrick unsigned int __r29;
657f6c50668Spatrick unsigned int __r30;
658f6c50668Spatrick unsigned int __r31;
659f6c50668Spatrick unsigned int __cr; /* Condition register */
660f6c50668Spatrick unsigned int __xer; /* User's integer exception register */
661f6c50668Spatrick unsigned int __lr; /* Link register */
662f6c50668Spatrick unsigned int __ctr; /* Count register */
663f6c50668Spatrick unsigned int __mq; /* MQ register (601 only) */
664a0747c9fSpatrick unsigned int __vrsave; /* Vector Save Register */
665f6c50668Spatrick };
666f6c50668Spatrick
667f6c50668Spatrick struct ppc_float_state_t {
668f6c50668Spatrick double __fpregs[32];
669f6c50668Spatrick
670f6c50668Spatrick unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
671f6c50668Spatrick unsigned int __fpscr; /* floating point status register */
672f6c50668Spatrick };
673f6c50668Spatrick
674f6c50668Spatrick ppc_thread_state_t _registers;
675f6c50668Spatrick ppc_float_state_t _floatRegisters;
676a0747c9fSpatrick v128 _vectorRegisters[32]; // offset 424
677f6c50668Spatrick };
678f6c50668Spatrick
Registers_ppc(const void * registers)679f6c50668Spatrick inline Registers_ppc::Registers_ppc(const void *registers) {
680f6c50668Spatrick static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
681f6c50668Spatrick "ppc registers do not fit into unw_context_t");
682f6c50668Spatrick memcpy(&_registers, static_cast<const uint8_t *>(registers),
683f6c50668Spatrick sizeof(_registers));
684f6c50668Spatrick static_assert(sizeof(ppc_thread_state_t) == 160,
685f6c50668Spatrick "expected float register offset to be 160");
686f6c50668Spatrick memcpy(&_floatRegisters,
687f6c50668Spatrick static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
688f6c50668Spatrick sizeof(_floatRegisters));
689f6c50668Spatrick static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
690f6c50668Spatrick "expected vector register offset to be 424 bytes");
691a0747c9fSpatrick memcpy(_vectorRegisters,
692a0747c9fSpatrick static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
693a0747c9fSpatrick sizeof(ppc_float_state_t),
694a0747c9fSpatrick sizeof(_vectorRegisters));
695f6c50668Spatrick }
696f6c50668Spatrick
Registers_ppc()697f6c50668Spatrick inline Registers_ppc::Registers_ppc() {
698f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
699f6c50668Spatrick memset(&_floatRegisters, 0, sizeof(_floatRegisters));
700f6c50668Spatrick memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
701f6c50668Spatrick }
702f6c50668Spatrick
validRegister(int regNum) const703f6c50668Spatrick inline bool Registers_ppc::validRegister(int regNum) const {
704f6c50668Spatrick if (regNum == UNW_REG_IP)
705f6c50668Spatrick return true;
706f6c50668Spatrick if (regNum == UNW_REG_SP)
707f6c50668Spatrick return true;
708f6c50668Spatrick if (regNum == UNW_PPC_VRSAVE)
709f6c50668Spatrick return true;
710f6c50668Spatrick if (regNum < 0)
711f6c50668Spatrick return false;
712f6c50668Spatrick if (regNum <= UNW_PPC_R31)
713f6c50668Spatrick return true;
714f6c50668Spatrick if (regNum == UNW_PPC_MQ)
715f6c50668Spatrick return true;
716f6c50668Spatrick if (regNum == UNW_PPC_LR)
717f6c50668Spatrick return true;
718f6c50668Spatrick if (regNum == UNW_PPC_CTR)
719f6c50668Spatrick return true;
720f6c50668Spatrick if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
721f6c50668Spatrick return true;
722f6c50668Spatrick return false;
723f6c50668Spatrick }
724f6c50668Spatrick
getRegister(int regNum) const725f6c50668Spatrick inline uint32_t Registers_ppc::getRegister(int regNum) const {
726f6c50668Spatrick switch (regNum) {
727f6c50668Spatrick case UNW_REG_IP:
728f6c50668Spatrick return _registers.__srr0;
729f6c50668Spatrick case UNW_REG_SP:
730f6c50668Spatrick return _registers.__r1;
731f6c50668Spatrick case UNW_PPC_R0:
732f6c50668Spatrick return _registers.__r0;
733f6c50668Spatrick case UNW_PPC_R1:
734f6c50668Spatrick return _registers.__r1;
735f6c50668Spatrick case UNW_PPC_R2:
736f6c50668Spatrick return _registers.__r2;
737f6c50668Spatrick case UNW_PPC_R3:
738f6c50668Spatrick return _registers.__r3;
739f6c50668Spatrick case UNW_PPC_R4:
740f6c50668Spatrick return _registers.__r4;
741f6c50668Spatrick case UNW_PPC_R5:
742f6c50668Spatrick return _registers.__r5;
743f6c50668Spatrick case UNW_PPC_R6:
744f6c50668Spatrick return _registers.__r6;
745f6c50668Spatrick case UNW_PPC_R7:
746f6c50668Spatrick return _registers.__r7;
747f6c50668Spatrick case UNW_PPC_R8:
748f6c50668Spatrick return _registers.__r8;
749f6c50668Spatrick case UNW_PPC_R9:
750f6c50668Spatrick return _registers.__r9;
751f6c50668Spatrick case UNW_PPC_R10:
752f6c50668Spatrick return _registers.__r10;
753f6c50668Spatrick case UNW_PPC_R11:
754f6c50668Spatrick return _registers.__r11;
755f6c50668Spatrick case UNW_PPC_R12:
756f6c50668Spatrick return _registers.__r12;
757f6c50668Spatrick case UNW_PPC_R13:
758f6c50668Spatrick return _registers.__r13;
759f6c50668Spatrick case UNW_PPC_R14:
760f6c50668Spatrick return _registers.__r14;
761f6c50668Spatrick case UNW_PPC_R15:
762f6c50668Spatrick return _registers.__r15;
763f6c50668Spatrick case UNW_PPC_R16:
764f6c50668Spatrick return _registers.__r16;
765f6c50668Spatrick case UNW_PPC_R17:
766f6c50668Spatrick return _registers.__r17;
767f6c50668Spatrick case UNW_PPC_R18:
768f6c50668Spatrick return _registers.__r18;
769f6c50668Spatrick case UNW_PPC_R19:
770f6c50668Spatrick return _registers.__r19;
771f6c50668Spatrick case UNW_PPC_R20:
772f6c50668Spatrick return _registers.__r20;
773f6c50668Spatrick case UNW_PPC_R21:
774f6c50668Spatrick return _registers.__r21;
775f6c50668Spatrick case UNW_PPC_R22:
776f6c50668Spatrick return _registers.__r22;
777f6c50668Spatrick case UNW_PPC_R23:
778f6c50668Spatrick return _registers.__r23;
779f6c50668Spatrick case UNW_PPC_R24:
780f6c50668Spatrick return _registers.__r24;
781f6c50668Spatrick case UNW_PPC_R25:
782f6c50668Spatrick return _registers.__r25;
783f6c50668Spatrick case UNW_PPC_R26:
784f6c50668Spatrick return _registers.__r26;
785f6c50668Spatrick case UNW_PPC_R27:
786f6c50668Spatrick return _registers.__r27;
787f6c50668Spatrick case UNW_PPC_R28:
788f6c50668Spatrick return _registers.__r28;
789f6c50668Spatrick case UNW_PPC_R29:
790f6c50668Spatrick return _registers.__r29;
791f6c50668Spatrick case UNW_PPC_R30:
792f6c50668Spatrick return _registers.__r30;
793f6c50668Spatrick case UNW_PPC_R31:
794f6c50668Spatrick return _registers.__r31;
795f6c50668Spatrick case UNW_PPC_LR:
796f6c50668Spatrick return _registers.__lr;
797f6c50668Spatrick case UNW_PPC_CR0:
798f6c50668Spatrick return (_registers.__cr & 0xF0000000);
799f6c50668Spatrick case UNW_PPC_CR1:
800f6c50668Spatrick return (_registers.__cr & 0x0F000000);
801f6c50668Spatrick case UNW_PPC_CR2:
802f6c50668Spatrick return (_registers.__cr & 0x00F00000);
803f6c50668Spatrick case UNW_PPC_CR3:
804f6c50668Spatrick return (_registers.__cr & 0x000F0000);
805f6c50668Spatrick case UNW_PPC_CR4:
806f6c50668Spatrick return (_registers.__cr & 0x0000F000);
807f6c50668Spatrick case UNW_PPC_CR5:
808f6c50668Spatrick return (_registers.__cr & 0x00000F00);
809f6c50668Spatrick case UNW_PPC_CR6:
810f6c50668Spatrick return (_registers.__cr & 0x000000F0);
811f6c50668Spatrick case UNW_PPC_CR7:
812f6c50668Spatrick return (_registers.__cr & 0x0000000F);
813f6c50668Spatrick case UNW_PPC_VRSAVE:
814f6c50668Spatrick return _registers.__vrsave;
815f6c50668Spatrick }
816f6c50668Spatrick _LIBUNWIND_ABORT("unsupported ppc register");
817f6c50668Spatrick }
818f6c50668Spatrick
setRegister(int regNum,uint32_t value)819f6c50668Spatrick inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
820f6c50668Spatrick //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
821f6c50668Spatrick switch (regNum) {
822f6c50668Spatrick case UNW_REG_IP:
823f6c50668Spatrick _registers.__srr0 = value;
824f6c50668Spatrick return;
825f6c50668Spatrick case UNW_REG_SP:
826f6c50668Spatrick _registers.__r1 = value;
827f6c50668Spatrick return;
828f6c50668Spatrick case UNW_PPC_R0:
829f6c50668Spatrick _registers.__r0 = value;
830f6c50668Spatrick return;
831f6c50668Spatrick case UNW_PPC_R1:
832f6c50668Spatrick _registers.__r1 = value;
833f6c50668Spatrick return;
834f6c50668Spatrick case UNW_PPC_R2:
835f6c50668Spatrick _registers.__r2 = value;
836f6c50668Spatrick return;
837f6c50668Spatrick case UNW_PPC_R3:
838f6c50668Spatrick _registers.__r3 = value;
839f6c50668Spatrick return;
840f6c50668Spatrick case UNW_PPC_R4:
841f6c50668Spatrick _registers.__r4 = value;
842f6c50668Spatrick return;
843f6c50668Spatrick case UNW_PPC_R5:
844f6c50668Spatrick _registers.__r5 = value;
845f6c50668Spatrick return;
846f6c50668Spatrick case UNW_PPC_R6:
847f6c50668Spatrick _registers.__r6 = value;
848f6c50668Spatrick return;
849f6c50668Spatrick case UNW_PPC_R7:
850f6c50668Spatrick _registers.__r7 = value;
851f6c50668Spatrick return;
852f6c50668Spatrick case UNW_PPC_R8:
853f6c50668Spatrick _registers.__r8 = value;
854f6c50668Spatrick return;
855f6c50668Spatrick case UNW_PPC_R9:
856f6c50668Spatrick _registers.__r9 = value;
857f6c50668Spatrick return;
858f6c50668Spatrick case UNW_PPC_R10:
859f6c50668Spatrick _registers.__r10 = value;
860f6c50668Spatrick return;
861f6c50668Spatrick case UNW_PPC_R11:
862f6c50668Spatrick _registers.__r11 = value;
863f6c50668Spatrick return;
864f6c50668Spatrick case UNW_PPC_R12:
865f6c50668Spatrick _registers.__r12 = value;
866f6c50668Spatrick return;
867f6c50668Spatrick case UNW_PPC_R13:
868f6c50668Spatrick _registers.__r13 = value;
869f6c50668Spatrick return;
870f6c50668Spatrick case UNW_PPC_R14:
871f6c50668Spatrick _registers.__r14 = value;
872f6c50668Spatrick return;
873f6c50668Spatrick case UNW_PPC_R15:
874f6c50668Spatrick _registers.__r15 = value;
875f6c50668Spatrick return;
876f6c50668Spatrick case UNW_PPC_R16:
877f6c50668Spatrick _registers.__r16 = value;
878f6c50668Spatrick return;
879f6c50668Spatrick case UNW_PPC_R17:
880f6c50668Spatrick _registers.__r17 = value;
881f6c50668Spatrick return;
882f6c50668Spatrick case UNW_PPC_R18:
883f6c50668Spatrick _registers.__r18 = value;
884f6c50668Spatrick return;
885f6c50668Spatrick case UNW_PPC_R19:
886f6c50668Spatrick _registers.__r19 = value;
887f6c50668Spatrick return;
888f6c50668Spatrick case UNW_PPC_R20:
889f6c50668Spatrick _registers.__r20 = value;
890f6c50668Spatrick return;
891f6c50668Spatrick case UNW_PPC_R21:
892f6c50668Spatrick _registers.__r21 = value;
893f6c50668Spatrick return;
894f6c50668Spatrick case UNW_PPC_R22:
895f6c50668Spatrick _registers.__r22 = value;
896f6c50668Spatrick return;
897f6c50668Spatrick case UNW_PPC_R23:
898f6c50668Spatrick _registers.__r23 = value;
899f6c50668Spatrick return;
900f6c50668Spatrick case UNW_PPC_R24:
901f6c50668Spatrick _registers.__r24 = value;
902f6c50668Spatrick return;
903f6c50668Spatrick case UNW_PPC_R25:
904f6c50668Spatrick _registers.__r25 = value;
905f6c50668Spatrick return;
906f6c50668Spatrick case UNW_PPC_R26:
907f6c50668Spatrick _registers.__r26 = value;
908f6c50668Spatrick return;
909f6c50668Spatrick case UNW_PPC_R27:
910f6c50668Spatrick _registers.__r27 = value;
911f6c50668Spatrick return;
912f6c50668Spatrick case UNW_PPC_R28:
913f6c50668Spatrick _registers.__r28 = value;
914f6c50668Spatrick return;
915f6c50668Spatrick case UNW_PPC_R29:
916f6c50668Spatrick _registers.__r29 = value;
917f6c50668Spatrick return;
918f6c50668Spatrick case UNW_PPC_R30:
919f6c50668Spatrick _registers.__r30 = value;
920f6c50668Spatrick return;
921f6c50668Spatrick case UNW_PPC_R31:
922f6c50668Spatrick _registers.__r31 = value;
923f6c50668Spatrick return;
924f6c50668Spatrick case UNW_PPC_MQ:
925f6c50668Spatrick _registers.__mq = value;
926f6c50668Spatrick return;
927f6c50668Spatrick case UNW_PPC_LR:
928f6c50668Spatrick _registers.__lr = value;
929f6c50668Spatrick return;
930f6c50668Spatrick case UNW_PPC_CTR:
931f6c50668Spatrick _registers.__ctr = value;
932f6c50668Spatrick return;
933f6c50668Spatrick case UNW_PPC_CR0:
934f6c50668Spatrick _registers.__cr &= 0x0FFFFFFF;
935f6c50668Spatrick _registers.__cr |= (value & 0xF0000000);
936f6c50668Spatrick return;
937f6c50668Spatrick case UNW_PPC_CR1:
938f6c50668Spatrick _registers.__cr &= 0xF0FFFFFF;
939f6c50668Spatrick _registers.__cr |= (value & 0x0F000000);
940f6c50668Spatrick return;
941f6c50668Spatrick case UNW_PPC_CR2:
942f6c50668Spatrick _registers.__cr &= 0xFF0FFFFF;
943f6c50668Spatrick _registers.__cr |= (value & 0x00F00000);
944f6c50668Spatrick return;
945f6c50668Spatrick case UNW_PPC_CR3:
946f6c50668Spatrick _registers.__cr &= 0xFFF0FFFF;
947f6c50668Spatrick _registers.__cr |= (value & 0x000F0000);
948f6c50668Spatrick return;
949f6c50668Spatrick case UNW_PPC_CR4:
950f6c50668Spatrick _registers.__cr &= 0xFFFF0FFF;
951f6c50668Spatrick _registers.__cr |= (value & 0x0000F000);
952f6c50668Spatrick return;
953f6c50668Spatrick case UNW_PPC_CR5:
954f6c50668Spatrick _registers.__cr &= 0xFFFFF0FF;
955f6c50668Spatrick _registers.__cr |= (value & 0x00000F00);
956f6c50668Spatrick return;
957f6c50668Spatrick case UNW_PPC_CR6:
958f6c50668Spatrick _registers.__cr &= 0xFFFFFF0F;
959f6c50668Spatrick _registers.__cr |= (value & 0x000000F0);
960f6c50668Spatrick return;
961f6c50668Spatrick case UNW_PPC_CR7:
962f6c50668Spatrick _registers.__cr &= 0xFFFFFFF0;
963f6c50668Spatrick _registers.__cr |= (value & 0x0000000F);
964f6c50668Spatrick return;
965f6c50668Spatrick case UNW_PPC_VRSAVE:
966f6c50668Spatrick _registers.__vrsave = value;
967f6c50668Spatrick return;
968f6c50668Spatrick // not saved
969f6c50668Spatrick return;
970f6c50668Spatrick case UNW_PPC_XER:
971f6c50668Spatrick _registers.__xer = value;
972f6c50668Spatrick return;
973f6c50668Spatrick case UNW_PPC_AP:
974f6c50668Spatrick case UNW_PPC_VSCR:
975f6c50668Spatrick case UNW_PPC_SPEFSCR:
976f6c50668Spatrick // not saved
977f6c50668Spatrick return;
978f6c50668Spatrick }
979f6c50668Spatrick _LIBUNWIND_ABORT("unsupported ppc register");
980f6c50668Spatrick }
981f6c50668Spatrick
validFloatRegister(int regNum) const982f6c50668Spatrick inline bool Registers_ppc::validFloatRegister(int regNum) const {
983f6c50668Spatrick if (regNum < UNW_PPC_F0)
984f6c50668Spatrick return false;
985f6c50668Spatrick if (regNum > UNW_PPC_F31)
986f6c50668Spatrick return false;
987f6c50668Spatrick return true;
988f6c50668Spatrick }
989f6c50668Spatrick
getFloatRegister(int regNum) const990f6c50668Spatrick inline double Registers_ppc::getFloatRegister(int regNum) const {
991f6c50668Spatrick assert(validFloatRegister(regNum));
992f6c50668Spatrick return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
993f6c50668Spatrick }
994f6c50668Spatrick
setFloatRegister(int regNum,double value)995f6c50668Spatrick inline void Registers_ppc::setFloatRegister(int regNum, double value) {
996f6c50668Spatrick assert(validFloatRegister(regNum));
997f6c50668Spatrick _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
998f6c50668Spatrick }
999f6c50668Spatrick
validVectorRegister(int regNum) const1000f6c50668Spatrick inline bool Registers_ppc::validVectorRegister(int regNum) const {
1001f6c50668Spatrick if (regNum < UNW_PPC_V0)
1002f6c50668Spatrick return false;
1003f6c50668Spatrick if (regNum > UNW_PPC_V31)
1004f6c50668Spatrick return false;
1005f6c50668Spatrick return true;
1006f6c50668Spatrick }
1007f6c50668Spatrick
getVectorRegister(int regNum) const1008f6c50668Spatrick inline v128 Registers_ppc::getVectorRegister(int regNum) const {
1009f6c50668Spatrick assert(validVectorRegister(regNum));
1010f6c50668Spatrick v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
1011f6c50668Spatrick return result;
1012f6c50668Spatrick }
1013f6c50668Spatrick
setVectorRegister(int regNum,v128 value)1014f6c50668Spatrick inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
1015f6c50668Spatrick assert(validVectorRegister(regNum));
1016f6c50668Spatrick _vectorRegisters[regNum - UNW_PPC_V0] = value;
1017f6c50668Spatrick }
1018f6c50668Spatrick
getRegisterName(int regNum)1019f6c50668Spatrick inline const char *Registers_ppc::getRegisterName(int regNum) {
1020f6c50668Spatrick switch (regNum) {
1021f6c50668Spatrick case UNW_REG_IP:
1022f6c50668Spatrick return "ip";
1023f6c50668Spatrick case UNW_REG_SP:
1024f6c50668Spatrick return "sp";
1025f6c50668Spatrick case UNW_PPC_R0:
1026f6c50668Spatrick return "r0";
1027f6c50668Spatrick case UNW_PPC_R1:
1028f6c50668Spatrick return "r1";
1029f6c50668Spatrick case UNW_PPC_R2:
1030f6c50668Spatrick return "r2";
1031f6c50668Spatrick case UNW_PPC_R3:
1032f6c50668Spatrick return "r3";
1033f6c50668Spatrick case UNW_PPC_R4:
1034f6c50668Spatrick return "r4";
1035f6c50668Spatrick case UNW_PPC_R5:
1036f6c50668Spatrick return "r5";
1037f6c50668Spatrick case UNW_PPC_R6:
1038f6c50668Spatrick return "r6";
1039f6c50668Spatrick case UNW_PPC_R7:
1040f6c50668Spatrick return "r7";
1041f6c50668Spatrick case UNW_PPC_R8:
1042f6c50668Spatrick return "r8";
1043f6c50668Spatrick case UNW_PPC_R9:
1044f6c50668Spatrick return "r9";
1045f6c50668Spatrick case UNW_PPC_R10:
1046f6c50668Spatrick return "r10";
1047f6c50668Spatrick case UNW_PPC_R11:
1048f6c50668Spatrick return "r11";
1049f6c50668Spatrick case UNW_PPC_R12:
1050f6c50668Spatrick return "r12";
1051f6c50668Spatrick case UNW_PPC_R13:
1052f6c50668Spatrick return "r13";
1053f6c50668Spatrick case UNW_PPC_R14:
1054f6c50668Spatrick return "r14";
1055f6c50668Spatrick case UNW_PPC_R15:
1056f6c50668Spatrick return "r15";
1057f6c50668Spatrick case UNW_PPC_R16:
1058f6c50668Spatrick return "r16";
1059f6c50668Spatrick case UNW_PPC_R17:
1060f6c50668Spatrick return "r17";
1061f6c50668Spatrick case UNW_PPC_R18:
1062f6c50668Spatrick return "r18";
1063f6c50668Spatrick case UNW_PPC_R19:
1064f6c50668Spatrick return "r19";
1065f6c50668Spatrick case UNW_PPC_R20:
1066f6c50668Spatrick return "r20";
1067f6c50668Spatrick case UNW_PPC_R21:
1068f6c50668Spatrick return "r21";
1069f6c50668Spatrick case UNW_PPC_R22:
1070f6c50668Spatrick return "r22";
1071f6c50668Spatrick case UNW_PPC_R23:
1072f6c50668Spatrick return "r23";
1073f6c50668Spatrick case UNW_PPC_R24:
1074f6c50668Spatrick return "r24";
1075f6c50668Spatrick case UNW_PPC_R25:
1076f6c50668Spatrick return "r25";
1077f6c50668Spatrick case UNW_PPC_R26:
1078f6c50668Spatrick return "r26";
1079f6c50668Spatrick case UNW_PPC_R27:
1080f6c50668Spatrick return "r27";
1081f6c50668Spatrick case UNW_PPC_R28:
1082f6c50668Spatrick return "r28";
1083f6c50668Spatrick case UNW_PPC_R29:
1084f6c50668Spatrick return "r29";
1085f6c50668Spatrick case UNW_PPC_R30:
1086f6c50668Spatrick return "r30";
1087f6c50668Spatrick case UNW_PPC_R31:
1088f6c50668Spatrick return "r31";
1089f6c50668Spatrick case UNW_PPC_F0:
1090f6c50668Spatrick return "fp0";
1091f6c50668Spatrick case UNW_PPC_F1:
1092f6c50668Spatrick return "fp1";
1093f6c50668Spatrick case UNW_PPC_F2:
1094f6c50668Spatrick return "fp2";
1095f6c50668Spatrick case UNW_PPC_F3:
1096f6c50668Spatrick return "fp3";
1097f6c50668Spatrick case UNW_PPC_F4:
1098f6c50668Spatrick return "fp4";
1099f6c50668Spatrick case UNW_PPC_F5:
1100f6c50668Spatrick return "fp5";
1101f6c50668Spatrick case UNW_PPC_F6:
1102f6c50668Spatrick return "fp6";
1103f6c50668Spatrick case UNW_PPC_F7:
1104f6c50668Spatrick return "fp7";
1105f6c50668Spatrick case UNW_PPC_F8:
1106f6c50668Spatrick return "fp8";
1107f6c50668Spatrick case UNW_PPC_F9:
1108f6c50668Spatrick return "fp9";
1109f6c50668Spatrick case UNW_PPC_F10:
1110f6c50668Spatrick return "fp10";
1111f6c50668Spatrick case UNW_PPC_F11:
1112f6c50668Spatrick return "fp11";
1113f6c50668Spatrick case UNW_PPC_F12:
1114f6c50668Spatrick return "fp12";
1115f6c50668Spatrick case UNW_PPC_F13:
1116f6c50668Spatrick return "fp13";
1117f6c50668Spatrick case UNW_PPC_F14:
1118f6c50668Spatrick return "fp14";
1119f6c50668Spatrick case UNW_PPC_F15:
1120f6c50668Spatrick return "fp15";
1121f6c50668Spatrick case UNW_PPC_F16:
1122f6c50668Spatrick return "fp16";
1123f6c50668Spatrick case UNW_PPC_F17:
1124f6c50668Spatrick return "fp17";
1125f6c50668Spatrick case UNW_PPC_F18:
1126f6c50668Spatrick return "fp18";
1127f6c50668Spatrick case UNW_PPC_F19:
1128f6c50668Spatrick return "fp19";
1129f6c50668Spatrick case UNW_PPC_F20:
1130f6c50668Spatrick return "fp20";
1131f6c50668Spatrick case UNW_PPC_F21:
1132f6c50668Spatrick return "fp21";
1133f6c50668Spatrick case UNW_PPC_F22:
1134f6c50668Spatrick return "fp22";
1135f6c50668Spatrick case UNW_PPC_F23:
1136f6c50668Spatrick return "fp23";
1137f6c50668Spatrick case UNW_PPC_F24:
1138f6c50668Spatrick return "fp24";
1139f6c50668Spatrick case UNW_PPC_F25:
1140f6c50668Spatrick return "fp25";
1141f6c50668Spatrick case UNW_PPC_F26:
1142f6c50668Spatrick return "fp26";
1143f6c50668Spatrick case UNW_PPC_F27:
1144f6c50668Spatrick return "fp27";
1145f6c50668Spatrick case UNW_PPC_F28:
1146f6c50668Spatrick return "fp28";
1147f6c50668Spatrick case UNW_PPC_F29:
1148f6c50668Spatrick return "fp29";
1149f6c50668Spatrick case UNW_PPC_F30:
1150f6c50668Spatrick return "fp30";
1151f6c50668Spatrick case UNW_PPC_F31:
1152f6c50668Spatrick return "fp31";
1153f6c50668Spatrick case UNW_PPC_LR:
1154f6c50668Spatrick return "lr";
1155f6c50668Spatrick default:
1156f6c50668Spatrick return "unknown register";
1157f6c50668Spatrick }
1158f6c50668Spatrick
1159f6c50668Spatrick }
1160f6c50668Spatrick #endif // _LIBUNWIND_TARGET_PPC
1161f6c50668Spatrick
1162f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_PPC64)
1163f6c50668Spatrick /// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
1164f6c50668Spatrick /// process.
1165f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_ppc64 {
1166f6c50668Spatrick public:
1167f6c50668Spatrick Registers_ppc64();
1168f6c50668Spatrick Registers_ppc64(const void *registers);
1169f6c50668Spatrick
1170f6c50668Spatrick bool validRegister(int num) const;
1171f6c50668Spatrick uint64_t getRegister(int num) const;
1172f6c50668Spatrick void setRegister(int num, uint64_t value);
1173f6c50668Spatrick bool validFloatRegister(int num) const;
1174f6c50668Spatrick double getFloatRegister(int num) const;
1175f6c50668Spatrick void setFloatRegister(int num, double value);
1176f6c50668Spatrick bool validVectorRegister(int num) const;
1177f6c50668Spatrick v128 getVectorRegister(int num) const;
1178f6c50668Spatrick void setVectorRegister(int num, v128 value);
1179f6c50668Spatrick static const char *getRegisterName(int num);
1180f6c50668Spatrick void jumpto();
lastDwarfRegNum()1181*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
1182*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64;
1183*202cdb0eSrobert }
getArch()1184f6c50668Spatrick static int getArch() { return REGISTERS_PPC64; }
1185f6c50668Spatrick
getSP() const1186f6c50668Spatrick uint64_t getSP() const { return _registers.__r1; }
setSP(uint64_t value)1187f6c50668Spatrick void setSP(uint64_t value) { _registers.__r1 = value; }
getIP() const1188f6c50668Spatrick uint64_t getIP() const { return _registers.__srr0; }
setIP(uint64_t value)1189f6c50668Spatrick void setIP(uint64_t value) { _registers.__srr0 = value; }
getCR() const1190*202cdb0eSrobert uint64_t getCR() const { return _registers.__cr; }
setCR(uint64_t value)1191*202cdb0eSrobert void setCR(uint64_t value) { _registers.__cr = value; }
1192f6c50668Spatrick
1193f6c50668Spatrick private:
1194f6c50668Spatrick struct ppc64_thread_state_t {
1195f6c50668Spatrick uint64_t __srr0; // Instruction address register (PC)
1196f6c50668Spatrick uint64_t __srr1; // Machine state register (supervisor)
1197f6c50668Spatrick uint64_t __r0;
1198f6c50668Spatrick uint64_t __r1;
1199f6c50668Spatrick uint64_t __r2;
1200f6c50668Spatrick uint64_t __r3;
1201f6c50668Spatrick uint64_t __r4;
1202f6c50668Spatrick uint64_t __r5;
1203f6c50668Spatrick uint64_t __r6;
1204f6c50668Spatrick uint64_t __r7;
1205f6c50668Spatrick uint64_t __r8;
1206f6c50668Spatrick uint64_t __r9;
1207f6c50668Spatrick uint64_t __r10;
1208f6c50668Spatrick uint64_t __r11;
1209f6c50668Spatrick uint64_t __r12;
1210f6c50668Spatrick uint64_t __r13;
1211f6c50668Spatrick uint64_t __r14;
1212f6c50668Spatrick uint64_t __r15;
1213f6c50668Spatrick uint64_t __r16;
1214f6c50668Spatrick uint64_t __r17;
1215f6c50668Spatrick uint64_t __r18;
1216f6c50668Spatrick uint64_t __r19;
1217f6c50668Spatrick uint64_t __r20;
1218f6c50668Spatrick uint64_t __r21;
1219f6c50668Spatrick uint64_t __r22;
1220f6c50668Spatrick uint64_t __r23;
1221f6c50668Spatrick uint64_t __r24;
1222f6c50668Spatrick uint64_t __r25;
1223f6c50668Spatrick uint64_t __r26;
1224f6c50668Spatrick uint64_t __r27;
1225f6c50668Spatrick uint64_t __r28;
1226f6c50668Spatrick uint64_t __r29;
1227f6c50668Spatrick uint64_t __r30;
1228f6c50668Spatrick uint64_t __r31;
1229f6c50668Spatrick uint64_t __cr; // Condition register
1230f6c50668Spatrick uint64_t __xer; // User's integer exception register
1231f6c50668Spatrick uint64_t __lr; // Link register
1232f6c50668Spatrick uint64_t __ctr; // Count register
1233f6c50668Spatrick uint64_t __vrsave; // Vector Save Register
1234f6c50668Spatrick };
1235f6c50668Spatrick
1236f6c50668Spatrick union ppc64_vsr_t {
1237f6c50668Spatrick struct asfloat_s {
1238f6c50668Spatrick double f;
1239f6c50668Spatrick uint64_t v2;
1240f6c50668Spatrick } asfloat;
1241f6c50668Spatrick v128 v;
1242f6c50668Spatrick };
1243f6c50668Spatrick
1244f6c50668Spatrick ppc64_thread_state_t _registers;
1245f6c50668Spatrick ppc64_vsr_t _vectorScalarRegisters[64];
1246f6c50668Spatrick
1247f6c50668Spatrick static int getVectorRegNum(int num);
1248f6c50668Spatrick };
1249f6c50668Spatrick
Registers_ppc64(const void * registers)1250f6c50668Spatrick inline Registers_ppc64::Registers_ppc64(const void *registers) {
1251f6c50668Spatrick static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),
1252f6c50668Spatrick "ppc64 registers do not fit into unw_context_t");
1253f6c50668Spatrick memcpy(&_registers, static_cast<const uint8_t *>(registers),
1254f6c50668Spatrick sizeof(_registers));
1255f6c50668Spatrick static_assert(sizeof(_registers) == 312,
1256f6c50668Spatrick "expected vector scalar register offset to be 312");
1257f6c50668Spatrick memcpy(&_vectorScalarRegisters,
1258f6c50668Spatrick static_cast<const uint8_t *>(registers) + sizeof(_registers),
1259f6c50668Spatrick sizeof(_vectorScalarRegisters));
1260f6c50668Spatrick static_assert(sizeof(_registers) +
1261f6c50668Spatrick sizeof(_vectorScalarRegisters) == 1336,
1262f6c50668Spatrick "expected vector register offset to be 1336 bytes");
1263f6c50668Spatrick }
1264f6c50668Spatrick
Registers_ppc64()1265f6c50668Spatrick inline Registers_ppc64::Registers_ppc64() {
1266f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
1267f6c50668Spatrick memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
1268f6c50668Spatrick }
1269f6c50668Spatrick
validRegister(int regNum) const1270f6c50668Spatrick inline bool Registers_ppc64::validRegister(int regNum) const {
1271f6c50668Spatrick switch (regNum) {
1272f6c50668Spatrick case UNW_REG_IP:
1273f6c50668Spatrick case UNW_REG_SP:
1274f6c50668Spatrick case UNW_PPC64_XER:
1275f6c50668Spatrick case UNW_PPC64_LR:
1276f6c50668Spatrick case UNW_PPC64_CTR:
1277f6c50668Spatrick case UNW_PPC64_VRSAVE:
1278f6c50668Spatrick return true;
1279f6c50668Spatrick }
1280f6c50668Spatrick
1281f6c50668Spatrick if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
1282f6c50668Spatrick return true;
1283f6c50668Spatrick if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
1284f6c50668Spatrick return true;
1285f6c50668Spatrick
1286f6c50668Spatrick return false;
1287f6c50668Spatrick }
1288f6c50668Spatrick
getRegister(int regNum) const1289f6c50668Spatrick inline uint64_t Registers_ppc64::getRegister(int regNum) const {
1290f6c50668Spatrick switch (regNum) {
1291f6c50668Spatrick case UNW_REG_IP:
1292f6c50668Spatrick return _registers.__srr0;
1293f6c50668Spatrick case UNW_PPC64_R0:
1294f6c50668Spatrick return _registers.__r0;
1295f6c50668Spatrick case UNW_PPC64_R1:
1296f6c50668Spatrick case UNW_REG_SP:
1297f6c50668Spatrick return _registers.__r1;
1298f6c50668Spatrick case UNW_PPC64_R2:
1299f6c50668Spatrick return _registers.__r2;
1300f6c50668Spatrick case UNW_PPC64_R3:
1301f6c50668Spatrick return _registers.__r3;
1302f6c50668Spatrick case UNW_PPC64_R4:
1303f6c50668Spatrick return _registers.__r4;
1304f6c50668Spatrick case UNW_PPC64_R5:
1305f6c50668Spatrick return _registers.__r5;
1306f6c50668Spatrick case UNW_PPC64_R6:
1307f6c50668Spatrick return _registers.__r6;
1308f6c50668Spatrick case UNW_PPC64_R7:
1309f6c50668Spatrick return _registers.__r7;
1310f6c50668Spatrick case UNW_PPC64_R8:
1311f6c50668Spatrick return _registers.__r8;
1312f6c50668Spatrick case UNW_PPC64_R9:
1313f6c50668Spatrick return _registers.__r9;
1314f6c50668Spatrick case UNW_PPC64_R10:
1315f6c50668Spatrick return _registers.__r10;
1316f6c50668Spatrick case UNW_PPC64_R11:
1317f6c50668Spatrick return _registers.__r11;
1318f6c50668Spatrick case UNW_PPC64_R12:
1319f6c50668Spatrick return _registers.__r12;
1320f6c50668Spatrick case UNW_PPC64_R13:
1321f6c50668Spatrick return _registers.__r13;
1322f6c50668Spatrick case UNW_PPC64_R14:
1323f6c50668Spatrick return _registers.__r14;
1324f6c50668Spatrick case UNW_PPC64_R15:
1325f6c50668Spatrick return _registers.__r15;
1326f6c50668Spatrick case UNW_PPC64_R16:
1327f6c50668Spatrick return _registers.__r16;
1328f6c50668Spatrick case UNW_PPC64_R17:
1329f6c50668Spatrick return _registers.__r17;
1330f6c50668Spatrick case UNW_PPC64_R18:
1331f6c50668Spatrick return _registers.__r18;
1332f6c50668Spatrick case UNW_PPC64_R19:
1333f6c50668Spatrick return _registers.__r19;
1334f6c50668Spatrick case UNW_PPC64_R20:
1335f6c50668Spatrick return _registers.__r20;
1336f6c50668Spatrick case UNW_PPC64_R21:
1337f6c50668Spatrick return _registers.__r21;
1338f6c50668Spatrick case UNW_PPC64_R22:
1339f6c50668Spatrick return _registers.__r22;
1340f6c50668Spatrick case UNW_PPC64_R23:
1341f6c50668Spatrick return _registers.__r23;
1342f6c50668Spatrick case UNW_PPC64_R24:
1343f6c50668Spatrick return _registers.__r24;
1344f6c50668Spatrick case UNW_PPC64_R25:
1345f6c50668Spatrick return _registers.__r25;
1346f6c50668Spatrick case UNW_PPC64_R26:
1347f6c50668Spatrick return _registers.__r26;
1348f6c50668Spatrick case UNW_PPC64_R27:
1349f6c50668Spatrick return _registers.__r27;
1350f6c50668Spatrick case UNW_PPC64_R28:
1351f6c50668Spatrick return _registers.__r28;
1352f6c50668Spatrick case UNW_PPC64_R29:
1353f6c50668Spatrick return _registers.__r29;
1354f6c50668Spatrick case UNW_PPC64_R30:
1355f6c50668Spatrick return _registers.__r30;
1356f6c50668Spatrick case UNW_PPC64_R31:
1357f6c50668Spatrick return _registers.__r31;
1358f6c50668Spatrick case UNW_PPC64_CR0:
1359f6c50668Spatrick return (_registers.__cr & 0xF0000000);
1360f6c50668Spatrick case UNW_PPC64_CR1:
1361f6c50668Spatrick return (_registers.__cr & 0x0F000000);
1362f6c50668Spatrick case UNW_PPC64_CR2:
1363f6c50668Spatrick return (_registers.__cr & 0x00F00000);
1364f6c50668Spatrick case UNW_PPC64_CR3:
1365f6c50668Spatrick return (_registers.__cr & 0x000F0000);
1366f6c50668Spatrick case UNW_PPC64_CR4:
1367f6c50668Spatrick return (_registers.__cr & 0x0000F000);
1368f6c50668Spatrick case UNW_PPC64_CR5:
1369f6c50668Spatrick return (_registers.__cr & 0x00000F00);
1370f6c50668Spatrick case UNW_PPC64_CR6:
1371f6c50668Spatrick return (_registers.__cr & 0x000000F0);
1372f6c50668Spatrick case UNW_PPC64_CR7:
1373f6c50668Spatrick return (_registers.__cr & 0x0000000F);
1374f6c50668Spatrick case UNW_PPC64_XER:
1375f6c50668Spatrick return _registers.__xer;
1376f6c50668Spatrick case UNW_PPC64_LR:
1377f6c50668Spatrick return _registers.__lr;
1378f6c50668Spatrick case UNW_PPC64_CTR:
1379f6c50668Spatrick return _registers.__ctr;
1380f6c50668Spatrick case UNW_PPC64_VRSAVE:
1381f6c50668Spatrick return _registers.__vrsave;
1382f6c50668Spatrick }
1383f6c50668Spatrick _LIBUNWIND_ABORT("unsupported ppc64 register");
1384f6c50668Spatrick }
1385f6c50668Spatrick
setRegister(int regNum,uint64_t value)1386f6c50668Spatrick inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
1387f6c50668Spatrick switch (regNum) {
1388f6c50668Spatrick case UNW_REG_IP:
1389f6c50668Spatrick _registers.__srr0 = value;
1390f6c50668Spatrick return;
1391f6c50668Spatrick case UNW_PPC64_R0:
1392f6c50668Spatrick _registers.__r0 = value;
1393f6c50668Spatrick return;
1394f6c50668Spatrick case UNW_PPC64_R1:
1395f6c50668Spatrick case UNW_REG_SP:
1396f6c50668Spatrick _registers.__r1 = value;
1397f6c50668Spatrick return;
1398f6c50668Spatrick case UNW_PPC64_R2:
1399f6c50668Spatrick _registers.__r2 = value;
1400f6c50668Spatrick return;
1401f6c50668Spatrick case UNW_PPC64_R3:
1402f6c50668Spatrick _registers.__r3 = value;
1403f6c50668Spatrick return;
1404f6c50668Spatrick case UNW_PPC64_R4:
1405f6c50668Spatrick _registers.__r4 = value;
1406f6c50668Spatrick return;
1407f6c50668Spatrick case UNW_PPC64_R5:
1408f6c50668Spatrick _registers.__r5 = value;
1409f6c50668Spatrick return;
1410f6c50668Spatrick case UNW_PPC64_R6:
1411f6c50668Spatrick _registers.__r6 = value;
1412f6c50668Spatrick return;
1413f6c50668Spatrick case UNW_PPC64_R7:
1414f6c50668Spatrick _registers.__r7 = value;
1415f6c50668Spatrick return;
1416f6c50668Spatrick case UNW_PPC64_R8:
1417f6c50668Spatrick _registers.__r8 = value;
1418f6c50668Spatrick return;
1419f6c50668Spatrick case UNW_PPC64_R9:
1420f6c50668Spatrick _registers.__r9 = value;
1421f6c50668Spatrick return;
1422f6c50668Spatrick case UNW_PPC64_R10:
1423f6c50668Spatrick _registers.__r10 = value;
1424f6c50668Spatrick return;
1425f6c50668Spatrick case UNW_PPC64_R11:
1426f6c50668Spatrick _registers.__r11 = value;
1427f6c50668Spatrick return;
1428f6c50668Spatrick case UNW_PPC64_R12:
1429f6c50668Spatrick _registers.__r12 = value;
1430f6c50668Spatrick return;
1431f6c50668Spatrick case UNW_PPC64_R13:
1432f6c50668Spatrick _registers.__r13 = value;
1433f6c50668Spatrick return;
1434f6c50668Spatrick case UNW_PPC64_R14:
1435f6c50668Spatrick _registers.__r14 = value;
1436f6c50668Spatrick return;
1437f6c50668Spatrick case UNW_PPC64_R15:
1438f6c50668Spatrick _registers.__r15 = value;
1439f6c50668Spatrick return;
1440f6c50668Spatrick case UNW_PPC64_R16:
1441f6c50668Spatrick _registers.__r16 = value;
1442f6c50668Spatrick return;
1443f6c50668Spatrick case UNW_PPC64_R17:
1444f6c50668Spatrick _registers.__r17 = value;
1445f6c50668Spatrick return;
1446f6c50668Spatrick case UNW_PPC64_R18:
1447f6c50668Spatrick _registers.__r18 = value;
1448f6c50668Spatrick return;
1449f6c50668Spatrick case UNW_PPC64_R19:
1450f6c50668Spatrick _registers.__r19 = value;
1451f6c50668Spatrick return;
1452f6c50668Spatrick case UNW_PPC64_R20:
1453f6c50668Spatrick _registers.__r20 = value;
1454f6c50668Spatrick return;
1455f6c50668Spatrick case UNW_PPC64_R21:
1456f6c50668Spatrick _registers.__r21 = value;
1457f6c50668Spatrick return;
1458f6c50668Spatrick case UNW_PPC64_R22:
1459f6c50668Spatrick _registers.__r22 = value;
1460f6c50668Spatrick return;
1461f6c50668Spatrick case UNW_PPC64_R23:
1462f6c50668Spatrick _registers.__r23 = value;
1463f6c50668Spatrick return;
1464f6c50668Spatrick case UNW_PPC64_R24:
1465f6c50668Spatrick _registers.__r24 = value;
1466f6c50668Spatrick return;
1467f6c50668Spatrick case UNW_PPC64_R25:
1468f6c50668Spatrick _registers.__r25 = value;
1469f6c50668Spatrick return;
1470f6c50668Spatrick case UNW_PPC64_R26:
1471f6c50668Spatrick _registers.__r26 = value;
1472f6c50668Spatrick return;
1473f6c50668Spatrick case UNW_PPC64_R27:
1474f6c50668Spatrick _registers.__r27 = value;
1475f6c50668Spatrick return;
1476f6c50668Spatrick case UNW_PPC64_R28:
1477f6c50668Spatrick _registers.__r28 = value;
1478f6c50668Spatrick return;
1479f6c50668Spatrick case UNW_PPC64_R29:
1480f6c50668Spatrick _registers.__r29 = value;
1481f6c50668Spatrick return;
1482f6c50668Spatrick case UNW_PPC64_R30:
1483f6c50668Spatrick _registers.__r30 = value;
1484f6c50668Spatrick return;
1485f6c50668Spatrick case UNW_PPC64_R31:
1486f6c50668Spatrick _registers.__r31 = value;
1487f6c50668Spatrick return;
1488f6c50668Spatrick case UNW_PPC64_CR0:
1489f6c50668Spatrick _registers.__cr &= 0x0FFFFFFF;
1490f6c50668Spatrick _registers.__cr |= (value & 0xF0000000);
1491f6c50668Spatrick return;
1492f6c50668Spatrick case UNW_PPC64_CR1:
1493f6c50668Spatrick _registers.__cr &= 0xF0FFFFFF;
1494f6c50668Spatrick _registers.__cr |= (value & 0x0F000000);
1495f6c50668Spatrick return;
1496f6c50668Spatrick case UNW_PPC64_CR2:
1497f6c50668Spatrick _registers.__cr &= 0xFF0FFFFF;
1498f6c50668Spatrick _registers.__cr |= (value & 0x00F00000);
1499f6c50668Spatrick return;
1500f6c50668Spatrick case UNW_PPC64_CR3:
1501f6c50668Spatrick _registers.__cr &= 0xFFF0FFFF;
1502f6c50668Spatrick _registers.__cr |= (value & 0x000F0000);
1503f6c50668Spatrick return;
1504f6c50668Spatrick case UNW_PPC64_CR4:
1505f6c50668Spatrick _registers.__cr &= 0xFFFF0FFF;
1506f6c50668Spatrick _registers.__cr |= (value & 0x0000F000);
1507f6c50668Spatrick return;
1508f6c50668Spatrick case UNW_PPC64_CR5:
1509f6c50668Spatrick _registers.__cr &= 0xFFFFF0FF;
1510f6c50668Spatrick _registers.__cr |= (value & 0x00000F00);
1511f6c50668Spatrick return;
1512f6c50668Spatrick case UNW_PPC64_CR6:
1513f6c50668Spatrick _registers.__cr &= 0xFFFFFF0F;
1514f6c50668Spatrick _registers.__cr |= (value & 0x000000F0);
1515f6c50668Spatrick return;
1516f6c50668Spatrick case UNW_PPC64_CR7:
1517f6c50668Spatrick _registers.__cr &= 0xFFFFFFF0;
1518f6c50668Spatrick _registers.__cr |= (value & 0x0000000F);
1519f6c50668Spatrick return;
1520f6c50668Spatrick case UNW_PPC64_XER:
1521f6c50668Spatrick _registers.__xer = value;
1522f6c50668Spatrick return;
1523f6c50668Spatrick case UNW_PPC64_LR:
1524f6c50668Spatrick _registers.__lr = value;
1525f6c50668Spatrick return;
1526f6c50668Spatrick case UNW_PPC64_CTR:
1527f6c50668Spatrick _registers.__ctr = value;
1528f6c50668Spatrick return;
1529f6c50668Spatrick case UNW_PPC64_VRSAVE:
1530f6c50668Spatrick _registers.__vrsave = value;
1531f6c50668Spatrick return;
1532f6c50668Spatrick }
1533f6c50668Spatrick _LIBUNWIND_ABORT("unsupported ppc64 register");
1534f6c50668Spatrick }
1535f6c50668Spatrick
validFloatRegister(int regNum) const1536f6c50668Spatrick inline bool Registers_ppc64::validFloatRegister(int regNum) const {
1537f6c50668Spatrick return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
1538f6c50668Spatrick }
1539f6c50668Spatrick
getFloatRegister(int regNum) const1540f6c50668Spatrick inline double Registers_ppc64::getFloatRegister(int regNum) const {
1541f6c50668Spatrick assert(validFloatRegister(regNum));
1542f6c50668Spatrick return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
1543f6c50668Spatrick }
1544f6c50668Spatrick
setFloatRegister(int regNum,double value)1545f6c50668Spatrick inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
1546f6c50668Spatrick assert(validFloatRegister(regNum));
1547f6c50668Spatrick _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
1548f6c50668Spatrick }
1549f6c50668Spatrick
validVectorRegister(int regNum) const1550f6c50668Spatrick inline bool Registers_ppc64::validVectorRegister(int regNum) const {
1551a0747c9fSpatrick #if defined(__VSX__)
1552f6c50668Spatrick if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
1553f6c50668Spatrick return true;
1554f6c50668Spatrick if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
1555f6c50668Spatrick return true;
1556a0747c9fSpatrick #elif defined(__ALTIVEC__)
1557f6c50668Spatrick if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
1558f6c50668Spatrick return true;
1559f6c50668Spatrick #endif
1560f6c50668Spatrick return false;
1561f6c50668Spatrick }
1562f6c50668Spatrick
getVectorRegNum(int num)1563f6c50668Spatrick inline int Registers_ppc64::getVectorRegNum(int num)
1564f6c50668Spatrick {
1565f6c50668Spatrick if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
1566f6c50668Spatrick return num - UNW_PPC64_VS0;
1567f6c50668Spatrick else
1568f6c50668Spatrick return num - UNW_PPC64_VS32 + 32;
1569f6c50668Spatrick }
1570f6c50668Spatrick
getVectorRegister(int regNum) const1571f6c50668Spatrick inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
1572f6c50668Spatrick assert(validVectorRegister(regNum));
1573f6c50668Spatrick return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
1574f6c50668Spatrick }
1575f6c50668Spatrick
setVectorRegister(int regNum,v128 value)1576f6c50668Spatrick inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
1577f6c50668Spatrick assert(validVectorRegister(regNum));
1578f6c50668Spatrick _vectorScalarRegisters[getVectorRegNum(regNum)].v = value;
1579f6c50668Spatrick }
1580f6c50668Spatrick
getRegisterName(int regNum)1581f6c50668Spatrick inline const char *Registers_ppc64::getRegisterName(int regNum) {
1582f6c50668Spatrick switch (regNum) {
1583f6c50668Spatrick case UNW_REG_IP:
1584f6c50668Spatrick return "ip";
1585f6c50668Spatrick case UNW_REG_SP:
1586f6c50668Spatrick return "sp";
1587f6c50668Spatrick case UNW_PPC64_R0:
1588f6c50668Spatrick return "r0";
1589f6c50668Spatrick case UNW_PPC64_R1:
1590f6c50668Spatrick return "r1";
1591f6c50668Spatrick case UNW_PPC64_R2:
1592f6c50668Spatrick return "r2";
1593f6c50668Spatrick case UNW_PPC64_R3:
1594f6c50668Spatrick return "r3";
1595f6c50668Spatrick case UNW_PPC64_R4:
1596f6c50668Spatrick return "r4";
1597f6c50668Spatrick case UNW_PPC64_R5:
1598f6c50668Spatrick return "r5";
1599f6c50668Spatrick case UNW_PPC64_R6:
1600f6c50668Spatrick return "r6";
1601f6c50668Spatrick case UNW_PPC64_R7:
1602f6c50668Spatrick return "r7";
1603f6c50668Spatrick case UNW_PPC64_R8:
1604f6c50668Spatrick return "r8";
1605f6c50668Spatrick case UNW_PPC64_R9:
1606f6c50668Spatrick return "r9";
1607f6c50668Spatrick case UNW_PPC64_R10:
1608f6c50668Spatrick return "r10";
1609f6c50668Spatrick case UNW_PPC64_R11:
1610f6c50668Spatrick return "r11";
1611f6c50668Spatrick case UNW_PPC64_R12:
1612f6c50668Spatrick return "r12";
1613f6c50668Spatrick case UNW_PPC64_R13:
1614f6c50668Spatrick return "r13";
1615f6c50668Spatrick case UNW_PPC64_R14:
1616f6c50668Spatrick return "r14";
1617f6c50668Spatrick case UNW_PPC64_R15:
1618f6c50668Spatrick return "r15";
1619f6c50668Spatrick case UNW_PPC64_R16:
1620f6c50668Spatrick return "r16";
1621f6c50668Spatrick case UNW_PPC64_R17:
1622f6c50668Spatrick return "r17";
1623f6c50668Spatrick case UNW_PPC64_R18:
1624f6c50668Spatrick return "r18";
1625f6c50668Spatrick case UNW_PPC64_R19:
1626f6c50668Spatrick return "r19";
1627f6c50668Spatrick case UNW_PPC64_R20:
1628f6c50668Spatrick return "r20";
1629f6c50668Spatrick case UNW_PPC64_R21:
1630f6c50668Spatrick return "r21";
1631f6c50668Spatrick case UNW_PPC64_R22:
1632f6c50668Spatrick return "r22";
1633f6c50668Spatrick case UNW_PPC64_R23:
1634f6c50668Spatrick return "r23";
1635f6c50668Spatrick case UNW_PPC64_R24:
1636f6c50668Spatrick return "r24";
1637f6c50668Spatrick case UNW_PPC64_R25:
1638f6c50668Spatrick return "r25";
1639f6c50668Spatrick case UNW_PPC64_R26:
1640f6c50668Spatrick return "r26";
1641f6c50668Spatrick case UNW_PPC64_R27:
1642f6c50668Spatrick return "r27";
1643f6c50668Spatrick case UNW_PPC64_R28:
1644f6c50668Spatrick return "r28";
1645f6c50668Spatrick case UNW_PPC64_R29:
1646f6c50668Spatrick return "r29";
1647f6c50668Spatrick case UNW_PPC64_R30:
1648f6c50668Spatrick return "r30";
1649f6c50668Spatrick case UNW_PPC64_R31:
1650f6c50668Spatrick return "r31";
1651f6c50668Spatrick case UNW_PPC64_CR0:
1652f6c50668Spatrick return "cr0";
1653f6c50668Spatrick case UNW_PPC64_CR1:
1654f6c50668Spatrick return "cr1";
1655f6c50668Spatrick case UNW_PPC64_CR2:
1656f6c50668Spatrick return "cr2";
1657f6c50668Spatrick case UNW_PPC64_CR3:
1658f6c50668Spatrick return "cr3";
1659f6c50668Spatrick case UNW_PPC64_CR4:
1660f6c50668Spatrick return "cr4";
1661f6c50668Spatrick case UNW_PPC64_CR5:
1662f6c50668Spatrick return "cr5";
1663f6c50668Spatrick case UNW_PPC64_CR6:
1664f6c50668Spatrick return "cr6";
1665f6c50668Spatrick case UNW_PPC64_CR7:
1666f6c50668Spatrick return "cr7";
1667f6c50668Spatrick case UNW_PPC64_XER:
1668f6c50668Spatrick return "xer";
1669f6c50668Spatrick case UNW_PPC64_LR:
1670f6c50668Spatrick return "lr";
1671f6c50668Spatrick case UNW_PPC64_CTR:
1672f6c50668Spatrick return "ctr";
1673f6c50668Spatrick case UNW_PPC64_VRSAVE:
1674f6c50668Spatrick return "vrsave";
1675f6c50668Spatrick case UNW_PPC64_F0:
1676f6c50668Spatrick return "fp0";
1677f6c50668Spatrick case UNW_PPC64_F1:
1678f6c50668Spatrick return "fp1";
1679f6c50668Spatrick case UNW_PPC64_F2:
1680f6c50668Spatrick return "fp2";
1681f6c50668Spatrick case UNW_PPC64_F3:
1682f6c50668Spatrick return "fp3";
1683f6c50668Spatrick case UNW_PPC64_F4:
1684f6c50668Spatrick return "fp4";
1685f6c50668Spatrick case UNW_PPC64_F5:
1686f6c50668Spatrick return "fp5";
1687f6c50668Spatrick case UNW_PPC64_F6:
1688f6c50668Spatrick return "fp6";
1689f6c50668Spatrick case UNW_PPC64_F7:
1690f6c50668Spatrick return "fp7";
1691f6c50668Spatrick case UNW_PPC64_F8:
1692f6c50668Spatrick return "fp8";
1693f6c50668Spatrick case UNW_PPC64_F9:
1694f6c50668Spatrick return "fp9";
1695f6c50668Spatrick case UNW_PPC64_F10:
1696f6c50668Spatrick return "fp10";
1697f6c50668Spatrick case UNW_PPC64_F11:
1698f6c50668Spatrick return "fp11";
1699f6c50668Spatrick case UNW_PPC64_F12:
1700f6c50668Spatrick return "fp12";
1701f6c50668Spatrick case UNW_PPC64_F13:
1702f6c50668Spatrick return "fp13";
1703f6c50668Spatrick case UNW_PPC64_F14:
1704f6c50668Spatrick return "fp14";
1705f6c50668Spatrick case UNW_PPC64_F15:
1706f6c50668Spatrick return "fp15";
1707f6c50668Spatrick case UNW_PPC64_F16:
1708f6c50668Spatrick return "fp16";
1709f6c50668Spatrick case UNW_PPC64_F17:
1710f6c50668Spatrick return "fp17";
1711f6c50668Spatrick case UNW_PPC64_F18:
1712f6c50668Spatrick return "fp18";
1713f6c50668Spatrick case UNW_PPC64_F19:
1714f6c50668Spatrick return "fp19";
1715f6c50668Spatrick case UNW_PPC64_F20:
1716f6c50668Spatrick return "fp20";
1717f6c50668Spatrick case UNW_PPC64_F21:
1718f6c50668Spatrick return "fp21";
1719f6c50668Spatrick case UNW_PPC64_F22:
1720f6c50668Spatrick return "fp22";
1721f6c50668Spatrick case UNW_PPC64_F23:
1722f6c50668Spatrick return "fp23";
1723f6c50668Spatrick case UNW_PPC64_F24:
1724f6c50668Spatrick return "fp24";
1725f6c50668Spatrick case UNW_PPC64_F25:
1726f6c50668Spatrick return "fp25";
1727f6c50668Spatrick case UNW_PPC64_F26:
1728f6c50668Spatrick return "fp26";
1729f6c50668Spatrick case UNW_PPC64_F27:
1730f6c50668Spatrick return "fp27";
1731f6c50668Spatrick case UNW_PPC64_F28:
1732f6c50668Spatrick return "fp28";
1733f6c50668Spatrick case UNW_PPC64_F29:
1734f6c50668Spatrick return "fp29";
1735f6c50668Spatrick case UNW_PPC64_F30:
1736f6c50668Spatrick return "fp30";
1737f6c50668Spatrick case UNW_PPC64_F31:
1738f6c50668Spatrick return "fp31";
1739f6c50668Spatrick case UNW_PPC64_V0:
1740f6c50668Spatrick return "v0";
1741f6c50668Spatrick case UNW_PPC64_V1:
1742f6c50668Spatrick return "v1";
1743f6c50668Spatrick case UNW_PPC64_V2:
1744f6c50668Spatrick return "v2";
1745f6c50668Spatrick case UNW_PPC64_V3:
1746f6c50668Spatrick return "v3";
1747f6c50668Spatrick case UNW_PPC64_V4:
1748f6c50668Spatrick return "v4";
1749f6c50668Spatrick case UNW_PPC64_V5:
1750f6c50668Spatrick return "v5";
1751f6c50668Spatrick case UNW_PPC64_V6:
1752f6c50668Spatrick return "v6";
1753f6c50668Spatrick case UNW_PPC64_V7:
1754f6c50668Spatrick return "v7";
1755f6c50668Spatrick case UNW_PPC64_V8:
1756f6c50668Spatrick return "v8";
1757f6c50668Spatrick case UNW_PPC64_V9:
1758f6c50668Spatrick return "v9";
1759f6c50668Spatrick case UNW_PPC64_V10:
1760f6c50668Spatrick return "v10";
1761f6c50668Spatrick case UNW_PPC64_V11:
1762f6c50668Spatrick return "v11";
1763f6c50668Spatrick case UNW_PPC64_V12:
1764f6c50668Spatrick return "v12";
1765f6c50668Spatrick case UNW_PPC64_V13:
1766f6c50668Spatrick return "v13";
1767f6c50668Spatrick case UNW_PPC64_V14:
1768f6c50668Spatrick return "v14";
1769f6c50668Spatrick case UNW_PPC64_V15:
1770f6c50668Spatrick return "v15";
1771f6c50668Spatrick case UNW_PPC64_V16:
1772f6c50668Spatrick return "v16";
1773f6c50668Spatrick case UNW_PPC64_V17:
1774f6c50668Spatrick return "v17";
1775f6c50668Spatrick case UNW_PPC64_V18:
1776f6c50668Spatrick return "v18";
1777f6c50668Spatrick case UNW_PPC64_V19:
1778f6c50668Spatrick return "v19";
1779f6c50668Spatrick case UNW_PPC64_V20:
1780f6c50668Spatrick return "v20";
1781f6c50668Spatrick case UNW_PPC64_V21:
1782f6c50668Spatrick return "v21";
1783f6c50668Spatrick case UNW_PPC64_V22:
1784f6c50668Spatrick return "v22";
1785f6c50668Spatrick case UNW_PPC64_V23:
1786f6c50668Spatrick return "v23";
1787f6c50668Spatrick case UNW_PPC64_V24:
1788f6c50668Spatrick return "v24";
1789f6c50668Spatrick case UNW_PPC64_V25:
1790f6c50668Spatrick return "v25";
1791f6c50668Spatrick case UNW_PPC64_V26:
1792f6c50668Spatrick return "v26";
1793f6c50668Spatrick case UNW_PPC64_V27:
1794f6c50668Spatrick return "v27";
1795f6c50668Spatrick case UNW_PPC64_V28:
1796f6c50668Spatrick return "v28";
1797f6c50668Spatrick case UNW_PPC64_V29:
1798f6c50668Spatrick return "v29";
1799f6c50668Spatrick case UNW_PPC64_V30:
1800f6c50668Spatrick return "v30";
1801f6c50668Spatrick case UNW_PPC64_V31:
1802f6c50668Spatrick return "v31";
1803f6c50668Spatrick }
1804f6c50668Spatrick return "unknown register";
1805f6c50668Spatrick }
1806f6c50668Spatrick #endif // _LIBUNWIND_TARGET_PPC64
1807f6c50668Spatrick
1808f6c50668Spatrick
1809f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_AARCH64)
1810f6c50668Spatrick /// Registers_arm64 holds the register state of a thread in a 64-bit arm
1811f6c50668Spatrick /// process.
1812a0747c9fSpatrick class _LIBUNWIND_HIDDEN Registers_arm64;
1813a0747c9fSpatrick extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
1814f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_arm64 {
1815f6c50668Spatrick public:
1816f6c50668Spatrick Registers_arm64();
1817f6c50668Spatrick Registers_arm64(const void *registers);
1818f6c50668Spatrick
1819f6c50668Spatrick bool validRegister(int num) const;
1820f6c50668Spatrick uint64_t getRegister(int num) const;
1821f6c50668Spatrick void setRegister(int num, uint64_t value);
1822f6c50668Spatrick bool validFloatRegister(int num) const;
1823f6c50668Spatrick double getFloatRegister(int num) const;
1824f6c50668Spatrick void setFloatRegister(int num, double value);
1825f6c50668Spatrick bool validVectorRegister(int num) const;
1826f6c50668Spatrick v128 getVectorRegister(int num) const;
1827f6c50668Spatrick void setVectorRegister(int num, v128 value);
1828f6c50668Spatrick static const char *getRegisterName(int num);
jumpto()1829a0747c9fSpatrick void jumpto() { __libunwind_Registers_arm64_jumpto(this); }
lastDwarfRegNum()1830*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
1831*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
1832*202cdb0eSrobert }
getArch()1833f6c50668Spatrick static int getArch() { return REGISTERS_ARM64; }
1834f6c50668Spatrick
getSP() const1835f6c50668Spatrick uint64_t getSP() const { return _registers.__sp; }
setSP(uint64_t value)1836f6c50668Spatrick void setSP(uint64_t value) { _registers.__sp = value; }
getIP() const1837f6c50668Spatrick uint64_t getIP() const { return _registers.__pc; }
setIP(uint64_t value)1838f6c50668Spatrick void setIP(uint64_t value) { _registers.__pc = value; }
getFP() const1839f6c50668Spatrick uint64_t getFP() const { return _registers.__fp; }
setFP(uint64_t value)1840f6c50668Spatrick void setFP(uint64_t value) { _registers.__fp = value; }
1841f6c50668Spatrick
1842f6c50668Spatrick private:
1843f6c50668Spatrick struct GPRs {
1844f6c50668Spatrick uint64_t __x[29]; // x0-x28
1845f6c50668Spatrick uint64_t __fp; // Frame pointer x29
1846f6c50668Spatrick uint64_t __lr; // Link register x30
1847f6c50668Spatrick uint64_t __sp; // Stack pointer x31
1848f6c50668Spatrick uint64_t __pc; // Program counter
1849f6c50668Spatrick uint64_t __ra_sign_state; // RA sign state register
1850f6c50668Spatrick };
1851f6c50668Spatrick
1852f6c50668Spatrick GPRs _registers;
1853f6c50668Spatrick double _vectorHalfRegisters[32];
1854f6c50668Spatrick // Currently only the lower double in 128-bit vectore registers
1855f6c50668Spatrick // is perserved during unwinding. We could define new register
1856f6c50668Spatrick // numbers (> 96) which mean whole vector registers, then this
1857f6c50668Spatrick // struct would need to change to contain whole vector registers.
1858f6c50668Spatrick };
1859f6c50668Spatrick
Registers_arm64(const void * registers)1860f6c50668Spatrick inline Registers_arm64::Registers_arm64(const void *registers) {
1861f6c50668Spatrick static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
1862f6c50668Spatrick "arm64 registers do not fit into unw_context_t");
1863f6c50668Spatrick memcpy(&_registers, registers, sizeof(_registers));
1864f6c50668Spatrick static_assert(sizeof(GPRs) == 0x110,
1865f6c50668Spatrick "expected VFP registers to be at offset 272");
1866f6c50668Spatrick memcpy(_vectorHalfRegisters,
1867f6c50668Spatrick static_cast<const uint8_t *>(registers) + sizeof(GPRs),
1868f6c50668Spatrick sizeof(_vectorHalfRegisters));
1869f6c50668Spatrick }
1870f6c50668Spatrick
Registers_arm64()1871f6c50668Spatrick inline Registers_arm64::Registers_arm64() {
1872f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
1873f6c50668Spatrick memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
1874f6c50668Spatrick }
1875f6c50668Spatrick
validRegister(int regNum) const1876f6c50668Spatrick inline bool Registers_arm64::validRegister(int regNum) const {
1877f6c50668Spatrick if (regNum == UNW_REG_IP)
1878f6c50668Spatrick return true;
1879f6c50668Spatrick if (regNum == UNW_REG_SP)
1880f6c50668Spatrick return true;
1881f6c50668Spatrick if (regNum < 0)
1882f6c50668Spatrick return false;
1883f6c50668Spatrick if (regNum > 95)
1884f6c50668Spatrick return false;
1885*202cdb0eSrobert if (regNum == UNW_AARCH64_RA_SIGN_STATE)
1886f6c50668Spatrick return true;
1887a0747c9fSpatrick if ((regNum > 32) && (regNum < 64))
1888f6c50668Spatrick return false;
1889f6c50668Spatrick return true;
1890f6c50668Spatrick }
1891f6c50668Spatrick
getRegister(int regNum) const1892f6c50668Spatrick inline uint64_t Registers_arm64::getRegister(int regNum) const {
1893*202cdb0eSrobert if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
1894f6c50668Spatrick return _registers.__pc;
1895*202cdb0eSrobert if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
1896f6c50668Spatrick return _registers.__sp;
1897*202cdb0eSrobert if (regNum == UNW_AARCH64_RA_SIGN_STATE)
1898f6c50668Spatrick return _registers.__ra_sign_state;
1899*202cdb0eSrobert if (regNum == UNW_AARCH64_FP)
1900a0747c9fSpatrick return _registers.__fp;
1901*202cdb0eSrobert if (regNum == UNW_AARCH64_LR)
1902a0747c9fSpatrick return _registers.__lr;
1903a0747c9fSpatrick if ((regNum >= 0) && (regNum < 29))
1904f6c50668Spatrick return _registers.__x[regNum];
1905f6c50668Spatrick _LIBUNWIND_ABORT("unsupported arm64 register");
1906f6c50668Spatrick }
1907f6c50668Spatrick
setRegister(int regNum,uint64_t value)1908f6c50668Spatrick inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1909*202cdb0eSrobert if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
1910f6c50668Spatrick _registers.__pc = value;
1911*202cdb0eSrobert else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
1912f6c50668Spatrick _registers.__sp = value;
1913*202cdb0eSrobert else if (regNum == UNW_AARCH64_RA_SIGN_STATE)
1914f6c50668Spatrick _registers.__ra_sign_state = value;
1915*202cdb0eSrobert else if (regNum == UNW_AARCH64_FP)
1916a0747c9fSpatrick _registers.__fp = value;
1917*202cdb0eSrobert else if (regNum == UNW_AARCH64_LR)
1918a0747c9fSpatrick _registers.__lr = value;
1919a0747c9fSpatrick else if ((regNum >= 0) && (regNum < 29))
1920f6c50668Spatrick _registers.__x[regNum] = value;
1921f6c50668Spatrick else
1922f6c50668Spatrick _LIBUNWIND_ABORT("unsupported arm64 register");
1923f6c50668Spatrick }
1924f6c50668Spatrick
getRegisterName(int regNum)1925f6c50668Spatrick inline const char *Registers_arm64::getRegisterName(int regNum) {
1926f6c50668Spatrick switch (regNum) {
1927f6c50668Spatrick case UNW_REG_IP:
1928f6c50668Spatrick return "pc";
1929f6c50668Spatrick case UNW_REG_SP:
1930f6c50668Spatrick return "sp";
1931*202cdb0eSrobert case UNW_AARCH64_X0:
1932f6c50668Spatrick return "x0";
1933*202cdb0eSrobert case UNW_AARCH64_X1:
1934f6c50668Spatrick return "x1";
1935*202cdb0eSrobert case UNW_AARCH64_X2:
1936f6c50668Spatrick return "x2";
1937*202cdb0eSrobert case UNW_AARCH64_X3:
1938f6c50668Spatrick return "x3";
1939*202cdb0eSrobert case UNW_AARCH64_X4:
1940f6c50668Spatrick return "x4";
1941*202cdb0eSrobert case UNW_AARCH64_X5:
1942f6c50668Spatrick return "x5";
1943*202cdb0eSrobert case UNW_AARCH64_X6:
1944f6c50668Spatrick return "x6";
1945*202cdb0eSrobert case UNW_AARCH64_X7:
1946f6c50668Spatrick return "x7";
1947*202cdb0eSrobert case UNW_AARCH64_X8:
1948f6c50668Spatrick return "x8";
1949*202cdb0eSrobert case UNW_AARCH64_X9:
1950f6c50668Spatrick return "x9";
1951*202cdb0eSrobert case UNW_AARCH64_X10:
1952f6c50668Spatrick return "x10";
1953*202cdb0eSrobert case UNW_AARCH64_X11:
1954f6c50668Spatrick return "x11";
1955*202cdb0eSrobert case UNW_AARCH64_X12:
1956f6c50668Spatrick return "x12";
1957*202cdb0eSrobert case UNW_AARCH64_X13:
1958f6c50668Spatrick return "x13";
1959*202cdb0eSrobert case UNW_AARCH64_X14:
1960f6c50668Spatrick return "x14";
1961*202cdb0eSrobert case UNW_AARCH64_X15:
1962f6c50668Spatrick return "x15";
1963*202cdb0eSrobert case UNW_AARCH64_X16:
1964f6c50668Spatrick return "x16";
1965*202cdb0eSrobert case UNW_AARCH64_X17:
1966f6c50668Spatrick return "x17";
1967*202cdb0eSrobert case UNW_AARCH64_X18:
1968f6c50668Spatrick return "x18";
1969*202cdb0eSrobert case UNW_AARCH64_X19:
1970f6c50668Spatrick return "x19";
1971*202cdb0eSrobert case UNW_AARCH64_X20:
1972f6c50668Spatrick return "x20";
1973*202cdb0eSrobert case UNW_AARCH64_X21:
1974f6c50668Spatrick return "x21";
1975*202cdb0eSrobert case UNW_AARCH64_X22:
1976f6c50668Spatrick return "x22";
1977*202cdb0eSrobert case UNW_AARCH64_X23:
1978f6c50668Spatrick return "x23";
1979*202cdb0eSrobert case UNW_AARCH64_X24:
1980f6c50668Spatrick return "x24";
1981*202cdb0eSrobert case UNW_AARCH64_X25:
1982f6c50668Spatrick return "x25";
1983*202cdb0eSrobert case UNW_AARCH64_X26:
1984f6c50668Spatrick return "x26";
1985*202cdb0eSrobert case UNW_AARCH64_X27:
1986f6c50668Spatrick return "x27";
1987*202cdb0eSrobert case UNW_AARCH64_X28:
1988f6c50668Spatrick return "x28";
1989*202cdb0eSrobert case UNW_AARCH64_FP:
1990f6c50668Spatrick return "fp";
1991*202cdb0eSrobert case UNW_AARCH64_LR:
1992f6c50668Spatrick return "lr";
1993*202cdb0eSrobert case UNW_AARCH64_SP:
1994f6c50668Spatrick return "sp";
1995*202cdb0eSrobert case UNW_AARCH64_PC:
1996a0747c9fSpatrick return "pc";
1997*202cdb0eSrobert case UNW_AARCH64_V0:
1998f6c50668Spatrick return "d0";
1999*202cdb0eSrobert case UNW_AARCH64_V1:
2000f6c50668Spatrick return "d1";
2001*202cdb0eSrobert case UNW_AARCH64_V2:
2002f6c50668Spatrick return "d2";
2003*202cdb0eSrobert case UNW_AARCH64_V3:
2004f6c50668Spatrick return "d3";
2005*202cdb0eSrobert case UNW_AARCH64_V4:
2006f6c50668Spatrick return "d4";
2007*202cdb0eSrobert case UNW_AARCH64_V5:
2008f6c50668Spatrick return "d5";
2009*202cdb0eSrobert case UNW_AARCH64_V6:
2010f6c50668Spatrick return "d6";
2011*202cdb0eSrobert case UNW_AARCH64_V7:
2012f6c50668Spatrick return "d7";
2013*202cdb0eSrobert case UNW_AARCH64_V8:
2014f6c50668Spatrick return "d8";
2015*202cdb0eSrobert case UNW_AARCH64_V9:
2016f6c50668Spatrick return "d9";
2017*202cdb0eSrobert case UNW_AARCH64_V10:
2018f6c50668Spatrick return "d10";
2019*202cdb0eSrobert case UNW_AARCH64_V11:
2020f6c50668Spatrick return "d11";
2021*202cdb0eSrobert case UNW_AARCH64_V12:
2022f6c50668Spatrick return "d12";
2023*202cdb0eSrobert case UNW_AARCH64_V13:
2024f6c50668Spatrick return "d13";
2025*202cdb0eSrobert case UNW_AARCH64_V14:
2026f6c50668Spatrick return "d14";
2027*202cdb0eSrobert case UNW_AARCH64_V15:
2028f6c50668Spatrick return "d15";
2029*202cdb0eSrobert case UNW_AARCH64_V16:
2030f6c50668Spatrick return "d16";
2031*202cdb0eSrobert case UNW_AARCH64_V17:
2032f6c50668Spatrick return "d17";
2033*202cdb0eSrobert case UNW_AARCH64_V18:
2034f6c50668Spatrick return "d18";
2035*202cdb0eSrobert case UNW_AARCH64_V19:
2036f6c50668Spatrick return "d19";
2037*202cdb0eSrobert case UNW_AARCH64_V20:
2038f6c50668Spatrick return "d20";
2039*202cdb0eSrobert case UNW_AARCH64_V21:
2040f6c50668Spatrick return "d21";
2041*202cdb0eSrobert case UNW_AARCH64_V22:
2042f6c50668Spatrick return "d22";
2043*202cdb0eSrobert case UNW_AARCH64_V23:
2044f6c50668Spatrick return "d23";
2045*202cdb0eSrobert case UNW_AARCH64_V24:
2046f6c50668Spatrick return "d24";
2047*202cdb0eSrobert case UNW_AARCH64_V25:
2048f6c50668Spatrick return "d25";
2049*202cdb0eSrobert case UNW_AARCH64_V26:
2050f6c50668Spatrick return "d26";
2051*202cdb0eSrobert case UNW_AARCH64_V27:
2052f6c50668Spatrick return "d27";
2053*202cdb0eSrobert case UNW_AARCH64_V28:
2054f6c50668Spatrick return "d28";
2055*202cdb0eSrobert case UNW_AARCH64_V29:
2056f6c50668Spatrick return "d29";
2057*202cdb0eSrobert case UNW_AARCH64_V30:
2058f6c50668Spatrick return "d30";
2059*202cdb0eSrobert case UNW_AARCH64_V31:
2060f6c50668Spatrick return "d31";
2061f6c50668Spatrick default:
2062f6c50668Spatrick return "unknown register";
2063f6c50668Spatrick }
2064f6c50668Spatrick }
2065f6c50668Spatrick
validFloatRegister(int regNum) const2066f6c50668Spatrick inline bool Registers_arm64::validFloatRegister(int regNum) const {
2067*202cdb0eSrobert if (regNum < UNW_AARCH64_V0)
2068f6c50668Spatrick return false;
2069*202cdb0eSrobert if (regNum > UNW_AARCH64_V31)
2070f6c50668Spatrick return false;
2071f6c50668Spatrick return true;
2072f6c50668Spatrick }
2073f6c50668Spatrick
getFloatRegister(int regNum) const2074f6c50668Spatrick inline double Registers_arm64::getFloatRegister(int regNum) const {
2075f6c50668Spatrick assert(validFloatRegister(regNum));
2076*202cdb0eSrobert return _vectorHalfRegisters[regNum - UNW_AARCH64_V0];
2077f6c50668Spatrick }
2078f6c50668Spatrick
setFloatRegister(int regNum,double value)2079f6c50668Spatrick inline void Registers_arm64::setFloatRegister(int regNum, double value) {
2080f6c50668Spatrick assert(validFloatRegister(regNum));
2081*202cdb0eSrobert _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value;
2082f6c50668Spatrick }
2083f6c50668Spatrick
validVectorRegister(int) const2084f6c50668Spatrick inline bool Registers_arm64::validVectorRegister(int) const {
2085f6c50668Spatrick return false;
2086f6c50668Spatrick }
2087f6c50668Spatrick
getVectorRegister(int) const2088f6c50668Spatrick inline v128 Registers_arm64::getVectorRegister(int) const {
2089f6c50668Spatrick _LIBUNWIND_ABORT("no arm64 vector register support yet");
2090f6c50668Spatrick }
2091f6c50668Spatrick
setVectorRegister(int,v128)2092f6c50668Spatrick inline void Registers_arm64::setVectorRegister(int, v128) {
2093f6c50668Spatrick _LIBUNWIND_ABORT("no arm64 vector register support yet");
2094f6c50668Spatrick }
2095f6c50668Spatrick #endif // _LIBUNWIND_TARGET_AARCH64
2096f6c50668Spatrick
2097f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_ARM)
2098f6c50668Spatrick /// Registers_arm holds the register state of a thread in a 32-bit arm
2099f6c50668Spatrick /// process.
2100f6c50668Spatrick ///
2101f6c50668Spatrick /// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2102f6c50668Spatrick /// this uses more memory than required.
2103f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_arm {
2104f6c50668Spatrick public:
2105f6c50668Spatrick Registers_arm();
2106f6c50668Spatrick Registers_arm(const void *registers);
2107f6c50668Spatrick
2108f6c50668Spatrick bool validRegister(int num) const;
2109f6c50668Spatrick uint32_t getRegister(int num) const;
2110f6c50668Spatrick void setRegister(int num, uint32_t value);
2111f6c50668Spatrick bool validFloatRegister(int num) const;
2112f6c50668Spatrick unw_fpreg_t getFloatRegister(int num);
2113f6c50668Spatrick void setFloatRegister(int num, unw_fpreg_t value);
2114f6c50668Spatrick bool validVectorRegister(int num) const;
2115f6c50668Spatrick v128 getVectorRegister(int num) const;
2116f6c50668Spatrick void setVectorRegister(int num, v128 value);
2117f6c50668Spatrick static const char *getRegisterName(int num);
jumpto()2118f6c50668Spatrick void jumpto() {
2119f6c50668Spatrick restoreSavedFloatRegisters();
2120f6c50668Spatrick restoreCoreAndJumpTo();
2121f6c50668Spatrick }
lastDwarfRegNum()2122*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
2123*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM;
2124*202cdb0eSrobert }
getArch()2125f6c50668Spatrick static int getArch() { return REGISTERS_ARM; }
2126f6c50668Spatrick
getSP() const2127f6c50668Spatrick uint32_t getSP() const { return _registers.__sp; }
setSP(uint32_t value)2128f6c50668Spatrick void setSP(uint32_t value) { _registers.__sp = value; }
getIP() const2129f6c50668Spatrick uint32_t getIP() const { return _registers.__pc; }
setIP(uint32_t value)2130f6c50668Spatrick void setIP(uint32_t value) { _registers.__pc = value; }
2131f6c50668Spatrick
saveVFPAsX()2132f6c50668Spatrick void saveVFPAsX() {
2133f6c50668Spatrick assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
2134f6c50668Spatrick _use_X_for_vfp_save = true;
2135f6c50668Spatrick }
2136f6c50668Spatrick
restoreSavedFloatRegisters()2137f6c50668Spatrick void restoreSavedFloatRegisters() {
2138f6c50668Spatrick if (_saved_vfp_d0_d15) {
2139f6c50668Spatrick if (_use_X_for_vfp_save)
2140f6c50668Spatrick restoreVFPWithFLDMX(_vfp_d0_d15_pad);
2141f6c50668Spatrick else
2142f6c50668Spatrick restoreVFPWithFLDMD(_vfp_d0_d15_pad);
2143f6c50668Spatrick }
2144f6c50668Spatrick if (_saved_vfp_d16_d31)
2145f6c50668Spatrick restoreVFPv3(_vfp_d16_d31);
2146f6c50668Spatrick #if defined(__ARM_WMMX)
2147f6c50668Spatrick if (_saved_iwmmx)
2148f6c50668Spatrick restoreiWMMX(_iwmmx);
2149f6c50668Spatrick if (_saved_iwmmx_control)
2150f6c50668Spatrick restoreiWMMXControl(_iwmmx_control);
2151f6c50668Spatrick #endif
2152f6c50668Spatrick }
2153f6c50668Spatrick
2154f6c50668Spatrick private:
2155f6c50668Spatrick struct GPRs {
2156f6c50668Spatrick uint32_t __r[13]; // r0-r12
2157f6c50668Spatrick uint32_t __sp; // Stack pointer r13
2158f6c50668Spatrick uint32_t __lr; // Link register r14
2159f6c50668Spatrick uint32_t __pc; // Program counter r15
2160f6c50668Spatrick };
2161f6c50668Spatrick
2162*202cdb0eSrobert struct PseudoRegisters {
2163*202cdb0eSrobert uint32_t __pac; // Return Authentication Code (PAC)
2164*202cdb0eSrobert };
2165*202cdb0eSrobert
2166f6c50668Spatrick static void saveVFPWithFSTMD(void*);
2167f6c50668Spatrick static void saveVFPWithFSTMX(void*);
2168f6c50668Spatrick static void saveVFPv3(void*);
2169f6c50668Spatrick static void restoreVFPWithFLDMD(void*);
2170f6c50668Spatrick static void restoreVFPWithFLDMX(void*);
2171f6c50668Spatrick static void restoreVFPv3(void*);
2172f6c50668Spatrick #if defined(__ARM_WMMX)
2173f6c50668Spatrick static void saveiWMMX(void*);
2174f6c50668Spatrick static void saveiWMMXControl(uint32_t*);
2175f6c50668Spatrick static void restoreiWMMX(void*);
2176f6c50668Spatrick static void restoreiWMMXControl(uint32_t*);
2177f6c50668Spatrick #endif
2178f6c50668Spatrick void restoreCoreAndJumpTo();
2179f6c50668Spatrick
2180f6c50668Spatrick // ARM registers
2181f6c50668Spatrick GPRs _registers;
2182*202cdb0eSrobert PseudoRegisters _pseudo_registers;
2183f6c50668Spatrick
2184f6c50668Spatrick // We save floating point registers lazily because we can't know ahead of
2185f6c50668Spatrick // time which ones are used. See EHABI #4.7.
2186f6c50668Spatrick
2187f6c50668Spatrick // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2188f6c50668Spatrick //
2189f6c50668Spatrick // See EHABI #7.5 that explains how matching instruction sequences for load
2190f6c50668Spatrick // and store need to be used to correctly restore the exact register bits.
2191f6c50668Spatrick bool _use_X_for_vfp_save;
2192f6c50668Spatrick // Whether VFP D0-D15 are saved.
2193f6c50668Spatrick bool _saved_vfp_d0_d15;
2194f6c50668Spatrick // Whether VFPv3 D16-D31 are saved.
2195f6c50668Spatrick bool _saved_vfp_d16_d31;
2196f6c50668Spatrick // VFP registers D0-D15, + padding if saved using FSTMX
2197f6c50668Spatrick unw_fpreg_t _vfp_d0_d15_pad[17];
2198f6c50668Spatrick // VFPv3 registers D16-D31, always saved using FSTMD
2199f6c50668Spatrick unw_fpreg_t _vfp_d16_d31[16];
2200f6c50668Spatrick #if defined(__ARM_WMMX)
2201f6c50668Spatrick // Whether iWMMX data registers are saved.
2202f6c50668Spatrick bool _saved_iwmmx;
2203f6c50668Spatrick // Whether iWMMX control registers are saved.
2204f6c50668Spatrick mutable bool _saved_iwmmx_control;
2205f6c50668Spatrick // iWMMX registers
2206f6c50668Spatrick unw_fpreg_t _iwmmx[16];
2207f6c50668Spatrick // iWMMX control registers
2208f6c50668Spatrick mutable uint32_t _iwmmx_control[4];
2209f6c50668Spatrick #endif
2210f6c50668Spatrick };
2211f6c50668Spatrick
Registers_arm(const void * registers)2212f6c50668Spatrick inline Registers_arm::Registers_arm(const void *registers)
2213f6c50668Spatrick : _use_X_for_vfp_save(false),
2214f6c50668Spatrick _saved_vfp_d0_d15(false),
2215f6c50668Spatrick _saved_vfp_d16_d31(false) {
2216f6c50668Spatrick static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
2217f6c50668Spatrick "arm registers do not fit into unw_context_t");
2218f6c50668Spatrick // See __unw_getcontext() note about data.
2219f6c50668Spatrick memcpy(&_registers, registers, sizeof(_registers));
2220*202cdb0eSrobert memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));
2221f6c50668Spatrick memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2222f6c50668Spatrick memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2223f6c50668Spatrick #if defined(__ARM_WMMX)
2224f6c50668Spatrick _saved_iwmmx = false;
2225f6c50668Spatrick _saved_iwmmx_control = false;
2226f6c50668Spatrick memset(&_iwmmx, 0, sizeof(_iwmmx));
2227f6c50668Spatrick memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2228f6c50668Spatrick #endif
2229f6c50668Spatrick }
2230f6c50668Spatrick
Registers_arm()2231f6c50668Spatrick inline Registers_arm::Registers_arm()
2232f6c50668Spatrick : _use_X_for_vfp_save(false),
2233f6c50668Spatrick _saved_vfp_d0_d15(false),
2234f6c50668Spatrick _saved_vfp_d16_d31(false) {
2235f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
2236*202cdb0eSrobert memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));
2237f6c50668Spatrick memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2238f6c50668Spatrick memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2239f6c50668Spatrick #if defined(__ARM_WMMX)
2240f6c50668Spatrick _saved_iwmmx = false;
2241f6c50668Spatrick _saved_iwmmx_control = false;
2242f6c50668Spatrick memset(&_iwmmx, 0, sizeof(_iwmmx));
2243f6c50668Spatrick memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2244f6c50668Spatrick #endif
2245f6c50668Spatrick }
2246f6c50668Spatrick
validRegister(int regNum) const2247f6c50668Spatrick inline bool Registers_arm::validRegister(int regNum) const {
2248f6c50668Spatrick // Returns true for all non-VFP registers supported by the EHABI
2249f6c50668Spatrick // virtual register set (VRS).
2250f6c50668Spatrick if (regNum == UNW_REG_IP)
2251f6c50668Spatrick return true;
2252f6c50668Spatrick
2253f6c50668Spatrick if (regNum == UNW_REG_SP)
2254f6c50668Spatrick return true;
2255f6c50668Spatrick
2256f6c50668Spatrick if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
2257f6c50668Spatrick return true;
2258f6c50668Spatrick
2259f6c50668Spatrick #if defined(__ARM_WMMX)
2260f6c50668Spatrick if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
2261f6c50668Spatrick return true;
2262f6c50668Spatrick #endif
2263f6c50668Spatrick
2264*202cdb0eSrobert #ifdef __ARM_FEATURE_PAUTH
2265*202cdb0eSrobert if (regNum == UNW_ARM_RA_AUTH_CODE)
2266*202cdb0eSrobert return true;
2267*202cdb0eSrobert #endif
2268*202cdb0eSrobert
2269f6c50668Spatrick return false;
2270f6c50668Spatrick }
2271f6c50668Spatrick
getRegister(int regNum) const2272f6c50668Spatrick inline uint32_t Registers_arm::getRegister(int regNum) const {
2273f6c50668Spatrick if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
2274f6c50668Spatrick return _registers.__sp;
2275f6c50668Spatrick
2276f6c50668Spatrick if (regNum == UNW_ARM_LR)
2277f6c50668Spatrick return _registers.__lr;
2278f6c50668Spatrick
2279f6c50668Spatrick if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
2280f6c50668Spatrick return _registers.__pc;
2281f6c50668Spatrick
2282f6c50668Spatrick if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
2283f6c50668Spatrick return _registers.__r[regNum];
2284f6c50668Spatrick
2285f6c50668Spatrick #if defined(__ARM_WMMX)
2286f6c50668Spatrick if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2287f6c50668Spatrick if (!_saved_iwmmx_control) {
2288f6c50668Spatrick _saved_iwmmx_control = true;
2289f6c50668Spatrick saveiWMMXControl(_iwmmx_control);
2290f6c50668Spatrick }
2291f6c50668Spatrick return _iwmmx_control[regNum - UNW_ARM_WC0];
2292f6c50668Spatrick }
2293f6c50668Spatrick #endif
2294f6c50668Spatrick
2295*202cdb0eSrobert #ifdef __ARM_FEATURE_PAUTH
2296*202cdb0eSrobert if (regNum == UNW_ARM_RA_AUTH_CODE)
2297*202cdb0eSrobert return _pseudo_registers.__pac;
2298*202cdb0eSrobert #endif
2299*202cdb0eSrobert
2300f6c50668Spatrick _LIBUNWIND_ABORT("unsupported arm register");
2301f6c50668Spatrick }
2302f6c50668Spatrick
setRegister(int regNum,uint32_t value)2303f6c50668Spatrick inline void Registers_arm::setRegister(int regNum, uint32_t value) {
2304f6c50668Spatrick if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
2305f6c50668Spatrick _registers.__sp = value;
2306f6c50668Spatrick return;
2307f6c50668Spatrick }
2308f6c50668Spatrick
2309f6c50668Spatrick if (regNum == UNW_ARM_LR) {
2310f6c50668Spatrick _registers.__lr = value;
2311f6c50668Spatrick return;
2312f6c50668Spatrick }
2313f6c50668Spatrick
2314f6c50668Spatrick if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
2315f6c50668Spatrick _registers.__pc = value;
2316f6c50668Spatrick return;
2317f6c50668Spatrick }
2318f6c50668Spatrick
2319f6c50668Spatrick if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
2320f6c50668Spatrick _registers.__r[regNum] = value;
2321f6c50668Spatrick return;
2322f6c50668Spatrick }
2323f6c50668Spatrick
2324f6c50668Spatrick #if defined(__ARM_WMMX)
2325f6c50668Spatrick if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2326f6c50668Spatrick if (!_saved_iwmmx_control) {
2327f6c50668Spatrick _saved_iwmmx_control = true;
2328f6c50668Spatrick saveiWMMXControl(_iwmmx_control);
2329f6c50668Spatrick }
2330f6c50668Spatrick _iwmmx_control[regNum - UNW_ARM_WC0] = value;
2331f6c50668Spatrick return;
2332f6c50668Spatrick }
2333f6c50668Spatrick #endif
2334f6c50668Spatrick
2335*202cdb0eSrobert if (regNum == UNW_ARM_RA_AUTH_CODE) {
2336*202cdb0eSrobert _pseudo_registers.__pac = value;
2337*202cdb0eSrobert return;
2338*202cdb0eSrobert }
2339*202cdb0eSrobert
2340f6c50668Spatrick _LIBUNWIND_ABORT("unsupported arm register");
2341f6c50668Spatrick }
2342f6c50668Spatrick
getRegisterName(int regNum)2343f6c50668Spatrick inline const char *Registers_arm::getRegisterName(int regNum) {
2344f6c50668Spatrick switch (regNum) {
2345f6c50668Spatrick case UNW_REG_IP:
2346f6c50668Spatrick case UNW_ARM_IP: // UNW_ARM_R15 is alias
2347f6c50668Spatrick return "pc";
2348f6c50668Spatrick case UNW_ARM_LR: // UNW_ARM_R14 is alias
2349f6c50668Spatrick return "lr";
2350f6c50668Spatrick case UNW_REG_SP:
2351f6c50668Spatrick case UNW_ARM_SP: // UNW_ARM_R13 is alias
2352f6c50668Spatrick return "sp";
2353f6c50668Spatrick case UNW_ARM_R0:
2354f6c50668Spatrick return "r0";
2355f6c50668Spatrick case UNW_ARM_R1:
2356f6c50668Spatrick return "r1";
2357f6c50668Spatrick case UNW_ARM_R2:
2358f6c50668Spatrick return "r2";
2359f6c50668Spatrick case UNW_ARM_R3:
2360f6c50668Spatrick return "r3";
2361f6c50668Spatrick case UNW_ARM_R4:
2362f6c50668Spatrick return "r4";
2363f6c50668Spatrick case UNW_ARM_R5:
2364f6c50668Spatrick return "r5";
2365f6c50668Spatrick case UNW_ARM_R6:
2366f6c50668Spatrick return "r6";
2367f6c50668Spatrick case UNW_ARM_R7:
2368f6c50668Spatrick return "r7";
2369f6c50668Spatrick case UNW_ARM_R8:
2370f6c50668Spatrick return "r8";
2371f6c50668Spatrick case UNW_ARM_R9:
2372f6c50668Spatrick return "r9";
2373f6c50668Spatrick case UNW_ARM_R10:
2374f6c50668Spatrick return "r10";
2375f6c50668Spatrick case UNW_ARM_R11:
2376f6c50668Spatrick return "r11";
2377f6c50668Spatrick case UNW_ARM_R12:
2378f6c50668Spatrick return "r12";
2379f6c50668Spatrick case UNW_ARM_S0:
2380f6c50668Spatrick return "s0";
2381f6c50668Spatrick case UNW_ARM_S1:
2382f6c50668Spatrick return "s1";
2383f6c50668Spatrick case UNW_ARM_S2:
2384f6c50668Spatrick return "s2";
2385f6c50668Spatrick case UNW_ARM_S3:
2386f6c50668Spatrick return "s3";
2387f6c50668Spatrick case UNW_ARM_S4:
2388f6c50668Spatrick return "s4";
2389f6c50668Spatrick case UNW_ARM_S5:
2390f6c50668Spatrick return "s5";
2391f6c50668Spatrick case UNW_ARM_S6:
2392f6c50668Spatrick return "s6";
2393f6c50668Spatrick case UNW_ARM_S7:
2394f6c50668Spatrick return "s7";
2395f6c50668Spatrick case UNW_ARM_S8:
2396f6c50668Spatrick return "s8";
2397f6c50668Spatrick case UNW_ARM_S9:
2398f6c50668Spatrick return "s9";
2399f6c50668Spatrick case UNW_ARM_S10:
2400f6c50668Spatrick return "s10";
2401f6c50668Spatrick case UNW_ARM_S11:
2402f6c50668Spatrick return "s11";
2403f6c50668Spatrick case UNW_ARM_S12:
2404f6c50668Spatrick return "s12";
2405f6c50668Spatrick case UNW_ARM_S13:
2406f6c50668Spatrick return "s13";
2407f6c50668Spatrick case UNW_ARM_S14:
2408f6c50668Spatrick return "s14";
2409f6c50668Spatrick case UNW_ARM_S15:
2410f6c50668Spatrick return "s15";
2411f6c50668Spatrick case UNW_ARM_S16:
2412f6c50668Spatrick return "s16";
2413f6c50668Spatrick case UNW_ARM_S17:
2414f6c50668Spatrick return "s17";
2415f6c50668Spatrick case UNW_ARM_S18:
2416f6c50668Spatrick return "s18";
2417f6c50668Spatrick case UNW_ARM_S19:
2418f6c50668Spatrick return "s19";
2419f6c50668Spatrick case UNW_ARM_S20:
2420f6c50668Spatrick return "s20";
2421f6c50668Spatrick case UNW_ARM_S21:
2422f6c50668Spatrick return "s21";
2423f6c50668Spatrick case UNW_ARM_S22:
2424f6c50668Spatrick return "s22";
2425f6c50668Spatrick case UNW_ARM_S23:
2426f6c50668Spatrick return "s23";
2427f6c50668Spatrick case UNW_ARM_S24:
2428f6c50668Spatrick return "s24";
2429f6c50668Spatrick case UNW_ARM_S25:
2430f6c50668Spatrick return "s25";
2431f6c50668Spatrick case UNW_ARM_S26:
2432f6c50668Spatrick return "s26";
2433f6c50668Spatrick case UNW_ARM_S27:
2434f6c50668Spatrick return "s27";
2435f6c50668Spatrick case UNW_ARM_S28:
2436f6c50668Spatrick return "s28";
2437f6c50668Spatrick case UNW_ARM_S29:
2438f6c50668Spatrick return "s29";
2439f6c50668Spatrick case UNW_ARM_S30:
2440f6c50668Spatrick return "s30";
2441f6c50668Spatrick case UNW_ARM_S31:
2442f6c50668Spatrick return "s31";
2443f6c50668Spatrick case UNW_ARM_D0:
2444f6c50668Spatrick return "d0";
2445f6c50668Spatrick case UNW_ARM_D1:
2446f6c50668Spatrick return "d1";
2447f6c50668Spatrick case UNW_ARM_D2:
2448f6c50668Spatrick return "d2";
2449f6c50668Spatrick case UNW_ARM_D3:
2450f6c50668Spatrick return "d3";
2451f6c50668Spatrick case UNW_ARM_D4:
2452f6c50668Spatrick return "d4";
2453f6c50668Spatrick case UNW_ARM_D5:
2454f6c50668Spatrick return "d5";
2455f6c50668Spatrick case UNW_ARM_D6:
2456f6c50668Spatrick return "d6";
2457f6c50668Spatrick case UNW_ARM_D7:
2458f6c50668Spatrick return "d7";
2459f6c50668Spatrick case UNW_ARM_D8:
2460f6c50668Spatrick return "d8";
2461f6c50668Spatrick case UNW_ARM_D9:
2462f6c50668Spatrick return "d9";
2463f6c50668Spatrick case UNW_ARM_D10:
2464f6c50668Spatrick return "d10";
2465f6c50668Spatrick case UNW_ARM_D11:
2466f6c50668Spatrick return "d11";
2467f6c50668Spatrick case UNW_ARM_D12:
2468f6c50668Spatrick return "d12";
2469f6c50668Spatrick case UNW_ARM_D13:
2470f6c50668Spatrick return "d13";
2471f6c50668Spatrick case UNW_ARM_D14:
2472f6c50668Spatrick return "d14";
2473f6c50668Spatrick case UNW_ARM_D15:
2474f6c50668Spatrick return "d15";
2475f6c50668Spatrick case UNW_ARM_D16:
2476f6c50668Spatrick return "d16";
2477f6c50668Spatrick case UNW_ARM_D17:
2478f6c50668Spatrick return "d17";
2479f6c50668Spatrick case UNW_ARM_D18:
2480f6c50668Spatrick return "d18";
2481f6c50668Spatrick case UNW_ARM_D19:
2482f6c50668Spatrick return "d19";
2483f6c50668Spatrick case UNW_ARM_D20:
2484f6c50668Spatrick return "d20";
2485f6c50668Spatrick case UNW_ARM_D21:
2486f6c50668Spatrick return "d21";
2487f6c50668Spatrick case UNW_ARM_D22:
2488f6c50668Spatrick return "d22";
2489f6c50668Spatrick case UNW_ARM_D23:
2490f6c50668Spatrick return "d23";
2491f6c50668Spatrick case UNW_ARM_D24:
2492f6c50668Spatrick return "d24";
2493f6c50668Spatrick case UNW_ARM_D25:
2494f6c50668Spatrick return "d25";
2495f6c50668Spatrick case UNW_ARM_D26:
2496f6c50668Spatrick return "d26";
2497f6c50668Spatrick case UNW_ARM_D27:
2498f6c50668Spatrick return "d27";
2499f6c50668Spatrick case UNW_ARM_D28:
2500f6c50668Spatrick return "d28";
2501f6c50668Spatrick case UNW_ARM_D29:
2502f6c50668Spatrick return "d29";
2503f6c50668Spatrick case UNW_ARM_D30:
2504f6c50668Spatrick return "d30";
2505f6c50668Spatrick case UNW_ARM_D31:
2506f6c50668Spatrick return "d31";
2507f6c50668Spatrick default:
2508f6c50668Spatrick return "unknown register";
2509f6c50668Spatrick }
2510f6c50668Spatrick }
2511f6c50668Spatrick
validFloatRegister(int regNum) const2512f6c50668Spatrick inline bool Registers_arm::validFloatRegister(int regNum) const {
2513f6c50668Spatrick // NOTE: Consider the intel MMX registers floating points so the
2514f6c50668Spatrick // __unw_get_fpreg can be used to transmit the 64-bit data back.
2515f6c50668Spatrick return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
2516f6c50668Spatrick #if defined(__ARM_WMMX)
2517f6c50668Spatrick || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
2518f6c50668Spatrick #endif
2519f6c50668Spatrick ;
2520f6c50668Spatrick }
2521f6c50668Spatrick
getFloatRegister(int regNum)2522f6c50668Spatrick inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
2523f6c50668Spatrick if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2524f6c50668Spatrick if (!_saved_vfp_d0_d15) {
2525f6c50668Spatrick _saved_vfp_d0_d15 = true;
2526f6c50668Spatrick if (_use_X_for_vfp_save)
2527f6c50668Spatrick saveVFPWithFSTMX(_vfp_d0_d15_pad);
2528f6c50668Spatrick else
2529f6c50668Spatrick saveVFPWithFSTMD(_vfp_d0_d15_pad);
2530f6c50668Spatrick }
2531f6c50668Spatrick return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
2532f6c50668Spatrick }
2533f6c50668Spatrick
2534f6c50668Spatrick if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2535f6c50668Spatrick if (!_saved_vfp_d16_d31) {
2536f6c50668Spatrick _saved_vfp_d16_d31 = true;
2537f6c50668Spatrick saveVFPv3(_vfp_d16_d31);
2538f6c50668Spatrick }
2539f6c50668Spatrick return _vfp_d16_d31[regNum - UNW_ARM_D16];
2540f6c50668Spatrick }
2541f6c50668Spatrick
2542f6c50668Spatrick #if defined(__ARM_WMMX)
2543f6c50668Spatrick if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2544f6c50668Spatrick if (!_saved_iwmmx) {
2545f6c50668Spatrick _saved_iwmmx = true;
2546f6c50668Spatrick saveiWMMX(_iwmmx);
2547f6c50668Spatrick }
2548f6c50668Spatrick return _iwmmx[regNum - UNW_ARM_WR0];
2549f6c50668Spatrick }
2550f6c50668Spatrick #endif
2551f6c50668Spatrick
2552f6c50668Spatrick _LIBUNWIND_ABORT("Unknown ARM float register");
2553f6c50668Spatrick }
2554f6c50668Spatrick
setFloatRegister(int regNum,unw_fpreg_t value)2555f6c50668Spatrick inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
2556f6c50668Spatrick if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2557f6c50668Spatrick if (!_saved_vfp_d0_d15) {
2558f6c50668Spatrick _saved_vfp_d0_d15 = true;
2559f6c50668Spatrick if (_use_X_for_vfp_save)
2560f6c50668Spatrick saveVFPWithFSTMX(_vfp_d0_d15_pad);
2561f6c50668Spatrick else
2562f6c50668Spatrick saveVFPWithFSTMD(_vfp_d0_d15_pad);
2563f6c50668Spatrick }
2564f6c50668Spatrick _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
2565f6c50668Spatrick return;
2566f6c50668Spatrick }
2567f6c50668Spatrick
2568f6c50668Spatrick if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2569f6c50668Spatrick if (!_saved_vfp_d16_d31) {
2570f6c50668Spatrick _saved_vfp_d16_d31 = true;
2571f6c50668Spatrick saveVFPv3(_vfp_d16_d31);
2572f6c50668Spatrick }
2573f6c50668Spatrick _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
2574f6c50668Spatrick return;
2575f6c50668Spatrick }
2576f6c50668Spatrick
2577f6c50668Spatrick #if defined(__ARM_WMMX)
2578f6c50668Spatrick if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2579f6c50668Spatrick if (!_saved_iwmmx) {
2580f6c50668Spatrick _saved_iwmmx = true;
2581f6c50668Spatrick saveiWMMX(_iwmmx);
2582f6c50668Spatrick }
2583f6c50668Spatrick _iwmmx[regNum - UNW_ARM_WR0] = value;
2584f6c50668Spatrick return;
2585f6c50668Spatrick }
2586f6c50668Spatrick #endif
2587f6c50668Spatrick
2588f6c50668Spatrick _LIBUNWIND_ABORT("Unknown ARM float register");
2589f6c50668Spatrick }
2590f6c50668Spatrick
validVectorRegister(int) const2591f6c50668Spatrick inline bool Registers_arm::validVectorRegister(int) const {
2592f6c50668Spatrick return false;
2593f6c50668Spatrick }
2594f6c50668Spatrick
getVectorRegister(int) const2595f6c50668Spatrick inline v128 Registers_arm::getVectorRegister(int) const {
2596f6c50668Spatrick _LIBUNWIND_ABORT("ARM vector support not implemented");
2597f6c50668Spatrick }
2598f6c50668Spatrick
setVectorRegister(int,v128)2599f6c50668Spatrick inline void Registers_arm::setVectorRegister(int, v128) {
2600f6c50668Spatrick _LIBUNWIND_ABORT("ARM vector support not implemented");
2601f6c50668Spatrick }
2602f6c50668Spatrick #endif // _LIBUNWIND_TARGET_ARM
2603f6c50668Spatrick
2604f6c50668Spatrick
2605f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_OR1K)
2606f6c50668Spatrick /// Registers_or1k holds the register state of a thread in an OpenRISC1000
2607f6c50668Spatrick /// process.
2608f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_or1k {
2609f6c50668Spatrick public:
2610f6c50668Spatrick Registers_or1k();
2611f6c50668Spatrick Registers_or1k(const void *registers);
2612f6c50668Spatrick
2613f6c50668Spatrick bool validRegister(int num) const;
2614f6c50668Spatrick uint32_t getRegister(int num) const;
2615f6c50668Spatrick void setRegister(int num, uint32_t value);
2616f6c50668Spatrick bool validFloatRegister(int num) const;
2617f6c50668Spatrick double getFloatRegister(int num) const;
2618f6c50668Spatrick void setFloatRegister(int num, double value);
2619f6c50668Spatrick bool validVectorRegister(int num) const;
2620f6c50668Spatrick v128 getVectorRegister(int num) const;
2621f6c50668Spatrick void setVectorRegister(int num, v128 value);
2622f6c50668Spatrick static const char *getRegisterName(int num);
2623f6c50668Spatrick void jumpto();
lastDwarfRegNum()2624*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
2625*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K;
2626*202cdb0eSrobert }
getArch()2627f6c50668Spatrick static int getArch() { return REGISTERS_OR1K; }
2628f6c50668Spatrick
getSP() const2629f6c50668Spatrick uint64_t getSP() const { return _registers.__r[1]; }
setSP(uint32_t value)2630f6c50668Spatrick void setSP(uint32_t value) { _registers.__r[1] = value; }
getIP() const2631f6c50668Spatrick uint64_t getIP() const { return _registers.__pc; }
setIP(uint32_t value)2632f6c50668Spatrick void setIP(uint32_t value) { _registers.__pc = value; }
2633f6c50668Spatrick
2634f6c50668Spatrick private:
2635f6c50668Spatrick struct or1k_thread_state_t {
2636f6c50668Spatrick unsigned int __r[32]; // r0-r31
2637f6c50668Spatrick unsigned int __pc; // Program counter
2638f6c50668Spatrick unsigned int __epcr; // Program counter at exception
2639f6c50668Spatrick };
2640f6c50668Spatrick
2641f6c50668Spatrick or1k_thread_state_t _registers;
2642f6c50668Spatrick };
2643f6c50668Spatrick
Registers_or1k(const void * registers)2644f6c50668Spatrick inline Registers_or1k::Registers_or1k(const void *registers) {
2645f6c50668Spatrick static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
2646f6c50668Spatrick "or1k registers do not fit into unw_context_t");
2647f6c50668Spatrick memcpy(&_registers, static_cast<const uint8_t *>(registers),
2648f6c50668Spatrick sizeof(_registers));
2649f6c50668Spatrick }
2650f6c50668Spatrick
Registers_or1k()2651f6c50668Spatrick inline Registers_or1k::Registers_or1k() {
2652f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
2653f6c50668Spatrick }
2654f6c50668Spatrick
validRegister(int regNum) const2655f6c50668Spatrick inline bool Registers_or1k::validRegister(int regNum) const {
2656f6c50668Spatrick if (regNum == UNW_REG_IP)
2657f6c50668Spatrick return true;
2658f6c50668Spatrick if (regNum == UNW_REG_SP)
2659f6c50668Spatrick return true;
2660f6c50668Spatrick if (regNum < 0)
2661f6c50668Spatrick return false;
2662f6c50668Spatrick if (regNum <= UNW_OR1K_R31)
2663f6c50668Spatrick return true;
2664f6c50668Spatrick if (regNum == UNW_OR1K_EPCR)
2665f6c50668Spatrick return true;
2666f6c50668Spatrick return false;
2667f6c50668Spatrick }
2668f6c50668Spatrick
getRegister(int regNum) const2669f6c50668Spatrick inline uint32_t Registers_or1k::getRegister(int regNum) const {
2670f6c50668Spatrick if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
2671f6c50668Spatrick return _registers.__r[regNum - UNW_OR1K_R0];
2672f6c50668Spatrick
2673f6c50668Spatrick switch (regNum) {
2674f6c50668Spatrick case UNW_REG_IP:
2675f6c50668Spatrick return _registers.__pc;
2676f6c50668Spatrick case UNW_REG_SP:
2677f6c50668Spatrick return _registers.__r[1];
2678f6c50668Spatrick case UNW_OR1K_EPCR:
2679f6c50668Spatrick return _registers.__epcr;
2680f6c50668Spatrick }
2681f6c50668Spatrick _LIBUNWIND_ABORT("unsupported or1k register");
2682f6c50668Spatrick }
2683f6c50668Spatrick
setRegister(int regNum,uint32_t value)2684f6c50668Spatrick inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
2685f6c50668Spatrick if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
2686f6c50668Spatrick _registers.__r[regNum - UNW_OR1K_R0] = value;
2687f6c50668Spatrick return;
2688f6c50668Spatrick }
2689f6c50668Spatrick
2690f6c50668Spatrick switch (regNum) {
2691f6c50668Spatrick case UNW_REG_IP:
2692f6c50668Spatrick _registers.__pc = value;
2693f6c50668Spatrick return;
2694f6c50668Spatrick case UNW_REG_SP:
2695f6c50668Spatrick _registers.__r[1] = value;
2696f6c50668Spatrick return;
2697f6c50668Spatrick case UNW_OR1K_EPCR:
2698f6c50668Spatrick _registers.__epcr = value;
2699f6c50668Spatrick return;
2700f6c50668Spatrick }
2701f6c50668Spatrick _LIBUNWIND_ABORT("unsupported or1k register");
2702f6c50668Spatrick }
2703f6c50668Spatrick
validFloatRegister(int) const2704f6c50668Spatrick inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2705f6c50668Spatrick return false;
2706f6c50668Spatrick }
2707f6c50668Spatrick
getFloatRegister(int) const2708f6c50668Spatrick inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2709f6c50668Spatrick _LIBUNWIND_ABORT("or1k float support not implemented");
2710f6c50668Spatrick }
2711f6c50668Spatrick
setFloatRegister(int,double)2712f6c50668Spatrick inline void Registers_or1k::setFloatRegister(int /* regNum */,
2713f6c50668Spatrick double /* value */) {
2714f6c50668Spatrick _LIBUNWIND_ABORT("or1k float support not implemented");
2715f6c50668Spatrick }
2716f6c50668Spatrick
validVectorRegister(int) const2717f6c50668Spatrick inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2718f6c50668Spatrick return false;
2719f6c50668Spatrick }
2720f6c50668Spatrick
getVectorRegister(int) const2721f6c50668Spatrick inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
2722f6c50668Spatrick _LIBUNWIND_ABORT("or1k vector support not implemented");
2723f6c50668Spatrick }
2724f6c50668Spatrick
setVectorRegister(int,v128)2725f6c50668Spatrick inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
2726f6c50668Spatrick _LIBUNWIND_ABORT("or1k vector support not implemented");
2727f6c50668Spatrick }
2728f6c50668Spatrick
getRegisterName(int regNum)2729f6c50668Spatrick inline const char *Registers_or1k::getRegisterName(int regNum) {
2730f6c50668Spatrick switch (regNum) {
2731f6c50668Spatrick case UNW_OR1K_R0:
2732f6c50668Spatrick return "r0";
2733f6c50668Spatrick case UNW_OR1K_R1:
2734f6c50668Spatrick return "r1";
2735f6c50668Spatrick case UNW_OR1K_R2:
2736f6c50668Spatrick return "r2";
2737f6c50668Spatrick case UNW_OR1K_R3:
2738f6c50668Spatrick return "r3";
2739f6c50668Spatrick case UNW_OR1K_R4:
2740f6c50668Spatrick return "r4";
2741f6c50668Spatrick case UNW_OR1K_R5:
2742f6c50668Spatrick return "r5";
2743f6c50668Spatrick case UNW_OR1K_R6:
2744f6c50668Spatrick return "r6";
2745f6c50668Spatrick case UNW_OR1K_R7:
2746f6c50668Spatrick return "r7";
2747f6c50668Spatrick case UNW_OR1K_R8:
2748f6c50668Spatrick return "r8";
2749f6c50668Spatrick case UNW_OR1K_R9:
2750f6c50668Spatrick return "r9";
2751f6c50668Spatrick case UNW_OR1K_R10:
2752f6c50668Spatrick return "r10";
2753f6c50668Spatrick case UNW_OR1K_R11:
2754f6c50668Spatrick return "r11";
2755f6c50668Spatrick case UNW_OR1K_R12:
2756f6c50668Spatrick return "r12";
2757f6c50668Spatrick case UNW_OR1K_R13:
2758f6c50668Spatrick return "r13";
2759f6c50668Spatrick case UNW_OR1K_R14:
2760f6c50668Spatrick return "r14";
2761f6c50668Spatrick case UNW_OR1K_R15:
2762f6c50668Spatrick return "r15";
2763f6c50668Spatrick case UNW_OR1K_R16:
2764f6c50668Spatrick return "r16";
2765f6c50668Spatrick case UNW_OR1K_R17:
2766f6c50668Spatrick return "r17";
2767f6c50668Spatrick case UNW_OR1K_R18:
2768f6c50668Spatrick return "r18";
2769f6c50668Spatrick case UNW_OR1K_R19:
2770f6c50668Spatrick return "r19";
2771f6c50668Spatrick case UNW_OR1K_R20:
2772f6c50668Spatrick return "r20";
2773f6c50668Spatrick case UNW_OR1K_R21:
2774f6c50668Spatrick return "r21";
2775f6c50668Spatrick case UNW_OR1K_R22:
2776f6c50668Spatrick return "r22";
2777f6c50668Spatrick case UNW_OR1K_R23:
2778f6c50668Spatrick return "r23";
2779f6c50668Spatrick case UNW_OR1K_R24:
2780f6c50668Spatrick return "r24";
2781f6c50668Spatrick case UNW_OR1K_R25:
2782f6c50668Spatrick return "r25";
2783f6c50668Spatrick case UNW_OR1K_R26:
2784f6c50668Spatrick return "r26";
2785f6c50668Spatrick case UNW_OR1K_R27:
2786f6c50668Spatrick return "r27";
2787f6c50668Spatrick case UNW_OR1K_R28:
2788f6c50668Spatrick return "r28";
2789f6c50668Spatrick case UNW_OR1K_R29:
2790f6c50668Spatrick return "r29";
2791f6c50668Spatrick case UNW_OR1K_R30:
2792f6c50668Spatrick return "r30";
2793f6c50668Spatrick case UNW_OR1K_R31:
2794f6c50668Spatrick return "r31";
2795f6c50668Spatrick case UNW_OR1K_EPCR:
2796f6c50668Spatrick return "EPCR";
2797f6c50668Spatrick default:
2798f6c50668Spatrick return "unknown register";
2799f6c50668Spatrick }
2800f6c50668Spatrick
2801f6c50668Spatrick }
2802f6c50668Spatrick #endif // _LIBUNWIND_TARGET_OR1K
2803f6c50668Spatrick
2804f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_MIPS_O32)
2805f6c50668Spatrick /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2806f6c50668Spatrick /// process.
2807f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_mips_o32 {
2808f6c50668Spatrick public:
2809f6c50668Spatrick Registers_mips_o32();
2810f6c50668Spatrick Registers_mips_o32(const void *registers);
2811f6c50668Spatrick
2812f6c50668Spatrick bool validRegister(int num) const;
2813f6c50668Spatrick uint32_t getRegister(int num) const;
2814f6c50668Spatrick void setRegister(int num, uint32_t value);
2815f6c50668Spatrick bool validFloatRegister(int num) const;
2816f6c50668Spatrick double getFloatRegister(int num) const;
2817f6c50668Spatrick void setFloatRegister(int num, double value);
2818f6c50668Spatrick bool validVectorRegister(int num) const;
2819f6c50668Spatrick v128 getVectorRegister(int num) const;
2820f6c50668Spatrick void setVectorRegister(int num, v128 value);
2821f6c50668Spatrick static const char *getRegisterName(int num);
2822f6c50668Spatrick void jumpto();
lastDwarfRegNum()2823*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
2824*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
2825*202cdb0eSrobert }
getArch()2826f6c50668Spatrick static int getArch() { return REGISTERS_MIPS_O32; }
2827f6c50668Spatrick
getSP() const2828f6c50668Spatrick uint32_t getSP() const { return _registers.__r[29]; }
setSP(uint32_t value)2829f6c50668Spatrick void setSP(uint32_t value) { _registers.__r[29] = value; }
getIP() const2830f6c50668Spatrick uint32_t getIP() const { return _registers.__pc; }
setIP(uint32_t value)2831f6c50668Spatrick void setIP(uint32_t value) { _registers.__pc = value; }
2832f6c50668Spatrick
2833f6c50668Spatrick private:
2834f6c50668Spatrick struct mips_o32_thread_state_t {
2835f6c50668Spatrick uint32_t __r[32];
2836f6c50668Spatrick uint32_t __pc;
2837f6c50668Spatrick uint32_t __hi;
2838f6c50668Spatrick uint32_t __lo;
2839f6c50668Spatrick };
2840f6c50668Spatrick
2841f6c50668Spatrick mips_o32_thread_state_t _registers;
2842f6c50668Spatrick #ifdef __mips_hard_float
2843f6c50668Spatrick /// O32 with 32-bit floating point registers only uses half of this
2844f6c50668Spatrick /// space. However, using the same layout for 32-bit vs 64-bit
2845f6c50668Spatrick /// floating point registers results in a single context size for
2846f6c50668Spatrick /// O32 with hard float.
2847f6c50668Spatrick uint32_t _padding;
2848f6c50668Spatrick double _floats[32];
2849f6c50668Spatrick #endif
2850f6c50668Spatrick };
2851f6c50668Spatrick
Registers_mips_o32(const void * registers)2852f6c50668Spatrick inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
2853f6c50668Spatrick static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
2854f6c50668Spatrick "mips_o32 registers do not fit into unw_context_t");
2855f6c50668Spatrick memcpy(&_registers, static_cast<const uint8_t *>(registers),
2856f6c50668Spatrick sizeof(_registers));
2857f6c50668Spatrick }
2858f6c50668Spatrick
Registers_mips_o32()2859f6c50668Spatrick inline Registers_mips_o32::Registers_mips_o32() {
2860f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
2861f6c50668Spatrick }
2862f6c50668Spatrick
validRegister(int regNum) const2863f6c50668Spatrick inline bool Registers_mips_o32::validRegister(int regNum) const {
2864f6c50668Spatrick if (regNum == UNW_REG_IP)
2865f6c50668Spatrick return true;
2866f6c50668Spatrick if (regNum == UNW_REG_SP)
2867f6c50668Spatrick return true;
2868f6c50668Spatrick if (regNum < 0)
2869f6c50668Spatrick return false;
2870f6c50668Spatrick if (regNum <= UNW_MIPS_R31)
2871f6c50668Spatrick return true;
2872f6c50668Spatrick #if __mips_isa_rev != 6
2873f6c50668Spatrick if (regNum == UNW_MIPS_HI)
2874f6c50668Spatrick return true;
2875f6c50668Spatrick if (regNum == UNW_MIPS_LO)
2876f6c50668Spatrick return true;
2877f6c50668Spatrick #endif
2878f6c50668Spatrick #if defined(__mips_hard_float) && __mips_fpr == 32
2879f6c50668Spatrick if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2880f6c50668Spatrick return true;
2881f6c50668Spatrick #endif
2882f6c50668Spatrick // FIXME: DSP accumulator registers, MSA registers
2883f6c50668Spatrick return false;
2884f6c50668Spatrick }
2885f6c50668Spatrick
getRegister(int regNum) const2886f6c50668Spatrick inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
2887f6c50668Spatrick if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
2888f6c50668Spatrick return _registers.__r[regNum - UNW_MIPS_R0];
2889f6c50668Spatrick #if defined(__mips_hard_float) && __mips_fpr == 32
2890f6c50668Spatrick if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2891f6c50668Spatrick uint32_t *p;
2892f6c50668Spatrick
2893f6c50668Spatrick if (regNum % 2 == 0)
2894f6c50668Spatrick p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2895f6c50668Spatrick else
2896f6c50668Spatrick p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2897f6c50668Spatrick return *p;
2898f6c50668Spatrick }
2899f6c50668Spatrick #endif
2900f6c50668Spatrick
2901f6c50668Spatrick switch (regNum) {
2902f6c50668Spatrick case UNW_REG_IP:
2903f6c50668Spatrick return _registers.__pc;
2904f6c50668Spatrick case UNW_REG_SP:
2905f6c50668Spatrick return _registers.__r[29];
2906f6c50668Spatrick case UNW_MIPS_HI:
2907f6c50668Spatrick return _registers.__hi;
2908f6c50668Spatrick case UNW_MIPS_LO:
2909f6c50668Spatrick return _registers.__lo;
2910f6c50668Spatrick }
2911f6c50668Spatrick _LIBUNWIND_ABORT("unsupported mips_o32 register");
2912f6c50668Spatrick }
2913f6c50668Spatrick
setRegister(int regNum,uint32_t value)2914f6c50668Spatrick inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
2915f6c50668Spatrick if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
2916f6c50668Spatrick _registers.__r[regNum - UNW_MIPS_R0] = value;
2917f6c50668Spatrick return;
2918f6c50668Spatrick }
2919f6c50668Spatrick #if defined(__mips_hard_float) && __mips_fpr == 32
2920f6c50668Spatrick if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2921f6c50668Spatrick uint32_t *p;
2922f6c50668Spatrick
2923f6c50668Spatrick if (regNum % 2 == 0)
2924f6c50668Spatrick p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2925f6c50668Spatrick else
2926f6c50668Spatrick p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2927f6c50668Spatrick *p = value;
2928f6c50668Spatrick return;
2929f6c50668Spatrick }
2930f6c50668Spatrick #endif
2931f6c50668Spatrick
2932f6c50668Spatrick switch (regNum) {
2933f6c50668Spatrick case UNW_REG_IP:
2934f6c50668Spatrick _registers.__pc = value;
2935f6c50668Spatrick return;
2936f6c50668Spatrick case UNW_REG_SP:
2937f6c50668Spatrick _registers.__r[29] = value;
2938f6c50668Spatrick return;
2939f6c50668Spatrick case UNW_MIPS_HI:
2940f6c50668Spatrick _registers.__hi = value;
2941f6c50668Spatrick return;
2942f6c50668Spatrick case UNW_MIPS_LO:
2943f6c50668Spatrick _registers.__lo = value;
2944f6c50668Spatrick return;
2945f6c50668Spatrick }
2946f6c50668Spatrick _LIBUNWIND_ABORT("unsupported mips_o32 register");
2947f6c50668Spatrick }
2948f6c50668Spatrick
validFloatRegister(int regNum) const2949f6c50668Spatrick inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
2950f6c50668Spatrick #if defined(__mips_hard_float) && __mips_fpr == 64
2951f6c50668Spatrick if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2952f6c50668Spatrick return true;
2953f6c50668Spatrick #else
2954f6c50668Spatrick (void)regNum;
2955f6c50668Spatrick #endif
2956f6c50668Spatrick return false;
2957f6c50668Spatrick }
2958f6c50668Spatrick
getFloatRegister(int regNum) const2959f6c50668Spatrick inline double Registers_mips_o32::getFloatRegister(int regNum) const {
2960f6c50668Spatrick #if defined(__mips_hard_float) && __mips_fpr == 64
2961f6c50668Spatrick assert(validFloatRegister(regNum));
2962f6c50668Spatrick return _floats[regNum - UNW_MIPS_F0];
2963f6c50668Spatrick #else
2964f6c50668Spatrick (void)regNum;
2965f6c50668Spatrick _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2966f6c50668Spatrick #endif
2967f6c50668Spatrick }
2968f6c50668Spatrick
setFloatRegister(int regNum,double value)2969f6c50668Spatrick inline void Registers_mips_o32::setFloatRegister(int regNum,
2970f6c50668Spatrick double value) {
2971f6c50668Spatrick #if defined(__mips_hard_float) && __mips_fpr == 64
2972f6c50668Spatrick assert(validFloatRegister(regNum));
2973f6c50668Spatrick _floats[regNum - UNW_MIPS_F0] = value;
2974f6c50668Spatrick #else
2975f6c50668Spatrick (void)regNum;
2976f6c50668Spatrick (void)value;
2977f6c50668Spatrick _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2978f6c50668Spatrick #endif
2979f6c50668Spatrick }
2980f6c50668Spatrick
validVectorRegister(int) const2981f6c50668Spatrick inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
2982f6c50668Spatrick return false;
2983f6c50668Spatrick }
2984f6c50668Spatrick
getVectorRegister(int) const2985f6c50668Spatrick inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
2986f6c50668Spatrick _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2987f6c50668Spatrick }
2988f6c50668Spatrick
setVectorRegister(int,v128)2989f6c50668Spatrick inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
2990f6c50668Spatrick _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2991f6c50668Spatrick }
2992f6c50668Spatrick
getRegisterName(int regNum)2993f6c50668Spatrick inline const char *Registers_mips_o32::getRegisterName(int regNum) {
2994f6c50668Spatrick switch (regNum) {
2995f6c50668Spatrick case UNW_MIPS_R0:
2996f6c50668Spatrick return "$0";
2997f6c50668Spatrick case UNW_MIPS_R1:
2998f6c50668Spatrick return "$1";
2999f6c50668Spatrick case UNW_MIPS_R2:
3000f6c50668Spatrick return "$2";
3001f6c50668Spatrick case UNW_MIPS_R3:
3002f6c50668Spatrick return "$3";
3003f6c50668Spatrick case UNW_MIPS_R4:
3004f6c50668Spatrick return "$4";
3005f6c50668Spatrick case UNW_MIPS_R5:
3006f6c50668Spatrick return "$5";
3007f6c50668Spatrick case UNW_MIPS_R6:
3008f6c50668Spatrick return "$6";
3009f6c50668Spatrick case UNW_MIPS_R7:
3010f6c50668Spatrick return "$7";
3011f6c50668Spatrick case UNW_MIPS_R8:
3012f6c50668Spatrick return "$8";
3013f6c50668Spatrick case UNW_MIPS_R9:
3014f6c50668Spatrick return "$9";
3015f6c50668Spatrick case UNW_MIPS_R10:
3016f6c50668Spatrick return "$10";
3017f6c50668Spatrick case UNW_MIPS_R11:
3018f6c50668Spatrick return "$11";
3019f6c50668Spatrick case UNW_MIPS_R12:
3020f6c50668Spatrick return "$12";
3021f6c50668Spatrick case UNW_MIPS_R13:
3022f6c50668Spatrick return "$13";
3023f6c50668Spatrick case UNW_MIPS_R14:
3024f6c50668Spatrick return "$14";
3025f6c50668Spatrick case UNW_MIPS_R15:
3026f6c50668Spatrick return "$15";
3027f6c50668Spatrick case UNW_MIPS_R16:
3028f6c50668Spatrick return "$16";
3029f6c50668Spatrick case UNW_MIPS_R17:
3030f6c50668Spatrick return "$17";
3031f6c50668Spatrick case UNW_MIPS_R18:
3032f6c50668Spatrick return "$18";
3033f6c50668Spatrick case UNW_MIPS_R19:
3034f6c50668Spatrick return "$19";
3035f6c50668Spatrick case UNW_MIPS_R20:
3036f6c50668Spatrick return "$20";
3037f6c50668Spatrick case UNW_MIPS_R21:
3038f6c50668Spatrick return "$21";
3039f6c50668Spatrick case UNW_MIPS_R22:
3040f6c50668Spatrick return "$22";
3041f6c50668Spatrick case UNW_MIPS_R23:
3042f6c50668Spatrick return "$23";
3043f6c50668Spatrick case UNW_MIPS_R24:
3044f6c50668Spatrick return "$24";
3045f6c50668Spatrick case UNW_MIPS_R25:
3046f6c50668Spatrick return "$25";
3047f6c50668Spatrick case UNW_MIPS_R26:
3048f6c50668Spatrick return "$26";
3049f6c50668Spatrick case UNW_MIPS_R27:
3050f6c50668Spatrick return "$27";
3051f6c50668Spatrick case UNW_MIPS_R28:
3052f6c50668Spatrick return "$28";
3053f6c50668Spatrick case UNW_MIPS_R29:
3054f6c50668Spatrick return "$29";
3055f6c50668Spatrick case UNW_MIPS_R30:
3056f6c50668Spatrick return "$30";
3057f6c50668Spatrick case UNW_MIPS_R31:
3058f6c50668Spatrick return "$31";
3059f6c50668Spatrick case UNW_MIPS_F0:
3060f6c50668Spatrick return "$f0";
3061f6c50668Spatrick case UNW_MIPS_F1:
3062f6c50668Spatrick return "$f1";
3063f6c50668Spatrick case UNW_MIPS_F2:
3064f6c50668Spatrick return "$f2";
3065f6c50668Spatrick case UNW_MIPS_F3:
3066f6c50668Spatrick return "$f3";
3067f6c50668Spatrick case UNW_MIPS_F4:
3068f6c50668Spatrick return "$f4";
3069f6c50668Spatrick case UNW_MIPS_F5:
3070f6c50668Spatrick return "$f5";
3071f6c50668Spatrick case UNW_MIPS_F6:
3072f6c50668Spatrick return "$f6";
3073f6c50668Spatrick case UNW_MIPS_F7:
3074f6c50668Spatrick return "$f7";
3075f6c50668Spatrick case UNW_MIPS_F8:
3076f6c50668Spatrick return "$f8";
3077f6c50668Spatrick case UNW_MIPS_F9:
3078f6c50668Spatrick return "$f9";
3079f6c50668Spatrick case UNW_MIPS_F10:
3080f6c50668Spatrick return "$f10";
3081f6c50668Spatrick case UNW_MIPS_F11:
3082f6c50668Spatrick return "$f11";
3083f6c50668Spatrick case UNW_MIPS_F12:
3084f6c50668Spatrick return "$f12";
3085f6c50668Spatrick case UNW_MIPS_F13:
3086f6c50668Spatrick return "$f13";
3087f6c50668Spatrick case UNW_MIPS_F14:
3088f6c50668Spatrick return "$f14";
3089f6c50668Spatrick case UNW_MIPS_F15:
3090f6c50668Spatrick return "$f15";
3091f6c50668Spatrick case UNW_MIPS_F16:
3092f6c50668Spatrick return "$f16";
3093f6c50668Spatrick case UNW_MIPS_F17:
3094f6c50668Spatrick return "$f17";
3095f6c50668Spatrick case UNW_MIPS_F18:
3096f6c50668Spatrick return "$f18";
3097f6c50668Spatrick case UNW_MIPS_F19:
3098f6c50668Spatrick return "$f19";
3099f6c50668Spatrick case UNW_MIPS_F20:
3100f6c50668Spatrick return "$f20";
3101f6c50668Spatrick case UNW_MIPS_F21:
3102f6c50668Spatrick return "$f21";
3103f6c50668Spatrick case UNW_MIPS_F22:
3104f6c50668Spatrick return "$f22";
3105f6c50668Spatrick case UNW_MIPS_F23:
3106f6c50668Spatrick return "$f23";
3107f6c50668Spatrick case UNW_MIPS_F24:
3108f6c50668Spatrick return "$f24";
3109f6c50668Spatrick case UNW_MIPS_F25:
3110f6c50668Spatrick return "$f25";
3111f6c50668Spatrick case UNW_MIPS_F26:
3112f6c50668Spatrick return "$f26";
3113f6c50668Spatrick case UNW_MIPS_F27:
3114f6c50668Spatrick return "$f27";
3115f6c50668Spatrick case UNW_MIPS_F28:
3116f6c50668Spatrick return "$f28";
3117f6c50668Spatrick case UNW_MIPS_F29:
3118f6c50668Spatrick return "$f29";
3119f6c50668Spatrick case UNW_MIPS_F30:
3120f6c50668Spatrick return "$f30";
3121f6c50668Spatrick case UNW_MIPS_F31:
3122f6c50668Spatrick return "$f31";
3123f6c50668Spatrick case UNW_MIPS_HI:
3124f6c50668Spatrick return "$hi";
3125f6c50668Spatrick case UNW_MIPS_LO:
3126f6c50668Spatrick return "$lo";
3127f6c50668Spatrick default:
3128f6c50668Spatrick return "unknown register";
3129f6c50668Spatrick }
3130f6c50668Spatrick }
3131f6c50668Spatrick #endif // _LIBUNWIND_TARGET_MIPS_O32
3132f6c50668Spatrick
3133f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3134f6c50668Spatrick /// Registers_mips_newabi holds the register state of a thread in a
3135f6c50668Spatrick /// MIPS process using NEWABI (the N32 or N64 ABIs).
3136f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_mips_newabi {
3137f6c50668Spatrick public:
3138f6c50668Spatrick Registers_mips_newabi();
3139f6c50668Spatrick Registers_mips_newabi(const void *registers);
3140f6c50668Spatrick
3141f6c50668Spatrick bool validRegister(int num) const;
3142f6c50668Spatrick uint64_t getRegister(int num) const;
3143f6c50668Spatrick void setRegister(int num, uint64_t value);
3144f6c50668Spatrick bool validFloatRegister(int num) const;
3145f6c50668Spatrick double getFloatRegister(int num) const;
3146f6c50668Spatrick void setFloatRegister(int num, double value);
3147f6c50668Spatrick bool validVectorRegister(int num) const;
3148f6c50668Spatrick v128 getVectorRegister(int num) const;
3149f6c50668Spatrick void setVectorRegister(int num, v128 value);
3150f6c50668Spatrick static const char *getRegisterName(int num);
3151f6c50668Spatrick void jumpto();
lastDwarfRegNum()3152*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
3153*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
3154*202cdb0eSrobert }
getArch()3155f6c50668Spatrick static int getArch() { return REGISTERS_MIPS_NEWABI; }
3156f6c50668Spatrick
getSP() const3157f6c50668Spatrick uint64_t getSP() const { return _registers.__r[29]; }
setSP(uint64_t value)3158f6c50668Spatrick void setSP(uint64_t value) { _registers.__r[29] = value; }
getIP() const3159f6c50668Spatrick uint64_t getIP() const { return _registers.__pc; }
setIP(uint64_t value)3160f6c50668Spatrick void setIP(uint64_t value) { _registers.__pc = value; }
3161f6c50668Spatrick
3162f6c50668Spatrick private:
3163f6c50668Spatrick struct mips_newabi_thread_state_t {
3164f6c50668Spatrick uint64_t __r[32];
3165f6c50668Spatrick uint64_t __pc;
3166f6c50668Spatrick uint64_t __hi;
3167f6c50668Spatrick uint64_t __lo;
3168f6c50668Spatrick };
3169f6c50668Spatrick
3170f6c50668Spatrick mips_newabi_thread_state_t _registers;
3171f6c50668Spatrick #ifdef __mips_hard_float
3172f6c50668Spatrick double _floats[32];
3173f6c50668Spatrick #endif
3174f6c50668Spatrick };
3175f6c50668Spatrick
Registers_mips_newabi(const void * registers)3176f6c50668Spatrick inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
3177f6c50668Spatrick static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
3178f6c50668Spatrick "mips_newabi registers do not fit into unw_context_t");
3179f6c50668Spatrick memcpy(&_registers, static_cast<const uint8_t *>(registers),
3180f6c50668Spatrick sizeof(_registers));
3181f6c50668Spatrick }
3182f6c50668Spatrick
Registers_mips_newabi()3183f6c50668Spatrick inline Registers_mips_newabi::Registers_mips_newabi() {
3184f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
3185f6c50668Spatrick }
3186f6c50668Spatrick
validRegister(int regNum) const3187f6c50668Spatrick inline bool Registers_mips_newabi::validRegister(int regNum) const {
3188f6c50668Spatrick if (regNum == UNW_REG_IP)
3189f6c50668Spatrick return true;
3190f6c50668Spatrick if (regNum == UNW_REG_SP)
3191f6c50668Spatrick return true;
3192f6c50668Spatrick if (regNum < 0)
3193f6c50668Spatrick return false;
3194f6c50668Spatrick if (regNum <= UNW_MIPS_R31)
3195f6c50668Spatrick return true;
3196f6c50668Spatrick #if __mips_isa_rev != 6
3197f6c50668Spatrick if (regNum == UNW_MIPS_HI)
3198f6c50668Spatrick return true;
3199f6c50668Spatrick if (regNum == UNW_MIPS_LO)
3200f6c50668Spatrick return true;
3201f6c50668Spatrick #endif
3202f6c50668Spatrick // FIXME: Hard float, DSP accumulator registers, MSA registers
3203f6c50668Spatrick return false;
3204f6c50668Spatrick }
3205f6c50668Spatrick
getRegister(int regNum) const3206f6c50668Spatrick inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
3207f6c50668Spatrick if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
3208f6c50668Spatrick return _registers.__r[regNum - UNW_MIPS_R0];
3209f6c50668Spatrick
3210f6c50668Spatrick switch (regNum) {
3211f6c50668Spatrick case UNW_REG_IP:
3212f6c50668Spatrick return _registers.__pc;
3213f6c50668Spatrick case UNW_REG_SP:
3214f6c50668Spatrick return _registers.__r[29];
3215f6c50668Spatrick case UNW_MIPS_HI:
3216f6c50668Spatrick return _registers.__hi;
3217f6c50668Spatrick case UNW_MIPS_LO:
3218f6c50668Spatrick return _registers.__lo;
3219f6c50668Spatrick }
3220f6c50668Spatrick _LIBUNWIND_ABORT("unsupported mips_newabi register");
3221f6c50668Spatrick }
3222f6c50668Spatrick
setRegister(int regNum,uint64_t value)3223f6c50668Spatrick inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
3224f6c50668Spatrick if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
3225f6c50668Spatrick _registers.__r[regNum - UNW_MIPS_R0] = value;
3226f6c50668Spatrick return;
3227f6c50668Spatrick }
3228f6c50668Spatrick
3229f6c50668Spatrick switch (regNum) {
3230f6c50668Spatrick case UNW_REG_IP:
3231f6c50668Spatrick _registers.__pc = value;
3232f6c50668Spatrick return;
3233f6c50668Spatrick case UNW_REG_SP:
3234f6c50668Spatrick _registers.__r[29] = value;
3235f6c50668Spatrick return;
3236f6c50668Spatrick case UNW_MIPS_HI:
3237f6c50668Spatrick _registers.__hi = value;
3238f6c50668Spatrick return;
3239f6c50668Spatrick case UNW_MIPS_LO:
3240f6c50668Spatrick _registers.__lo = value;
3241f6c50668Spatrick return;
3242f6c50668Spatrick }
3243f6c50668Spatrick _LIBUNWIND_ABORT("unsupported mips_newabi register");
3244f6c50668Spatrick }
3245f6c50668Spatrick
validFloatRegister(int regNum) const3246f6c50668Spatrick inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
3247f6c50668Spatrick #ifdef __mips_hard_float
3248f6c50668Spatrick if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3249f6c50668Spatrick return true;
3250f6c50668Spatrick #else
3251f6c50668Spatrick (void)regNum;
3252f6c50668Spatrick #endif
3253f6c50668Spatrick return false;
3254f6c50668Spatrick }
3255f6c50668Spatrick
getFloatRegister(int regNum) const3256f6c50668Spatrick inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
3257f6c50668Spatrick #ifdef __mips_hard_float
3258f6c50668Spatrick assert(validFloatRegister(regNum));
3259f6c50668Spatrick return _floats[regNum - UNW_MIPS_F0];
3260f6c50668Spatrick #else
3261f6c50668Spatrick (void)regNum;
3262f6c50668Spatrick _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3263f6c50668Spatrick #endif
3264f6c50668Spatrick }
3265f6c50668Spatrick
setFloatRegister(int regNum,double value)3266f6c50668Spatrick inline void Registers_mips_newabi::setFloatRegister(int regNum,
3267f6c50668Spatrick double value) {
3268f6c50668Spatrick #ifdef __mips_hard_float
3269f6c50668Spatrick assert(validFloatRegister(regNum));
3270f6c50668Spatrick _floats[regNum - UNW_MIPS_F0] = value;
3271f6c50668Spatrick #else
3272f6c50668Spatrick (void)regNum;
3273f6c50668Spatrick (void)value;
3274f6c50668Spatrick _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3275f6c50668Spatrick #endif
3276f6c50668Spatrick }
3277f6c50668Spatrick
validVectorRegister(int) const3278f6c50668Spatrick inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3279f6c50668Spatrick return false;
3280f6c50668Spatrick }
3281f6c50668Spatrick
getVectorRegister(int) const3282f6c50668Spatrick inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3283f6c50668Spatrick _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3284f6c50668Spatrick }
3285f6c50668Spatrick
setVectorRegister(int,v128)3286f6c50668Spatrick inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
3287f6c50668Spatrick _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3288f6c50668Spatrick }
3289f6c50668Spatrick
getRegisterName(int regNum)3290f6c50668Spatrick inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
3291f6c50668Spatrick switch (regNum) {
3292f6c50668Spatrick case UNW_MIPS_R0:
3293f6c50668Spatrick return "$0";
3294f6c50668Spatrick case UNW_MIPS_R1:
3295f6c50668Spatrick return "$1";
3296f6c50668Spatrick case UNW_MIPS_R2:
3297f6c50668Spatrick return "$2";
3298f6c50668Spatrick case UNW_MIPS_R3:
3299f6c50668Spatrick return "$3";
3300f6c50668Spatrick case UNW_MIPS_R4:
3301f6c50668Spatrick return "$4";
3302f6c50668Spatrick case UNW_MIPS_R5:
3303f6c50668Spatrick return "$5";
3304f6c50668Spatrick case UNW_MIPS_R6:
3305f6c50668Spatrick return "$6";
3306f6c50668Spatrick case UNW_MIPS_R7:
3307f6c50668Spatrick return "$7";
3308f6c50668Spatrick case UNW_MIPS_R8:
3309f6c50668Spatrick return "$8";
3310f6c50668Spatrick case UNW_MIPS_R9:
3311f6c50668Spatrick return "$9";
3312f6c50668Spatrick case UNW_MIPS_R10:
3313f6c50668Spatrick return "$10";
3314f6c50668Spatrick case UNW_MIPS_R11:
3315f6c50668Spatrick return "$11";
3316f6c50668Spatrick case UNW_MIPS_R12:
3317f6c50668Spatrick return "$12";
3318f6c50668Spatrick case UNW_MIPS_R13:
3319f6c50668Spatrick return "$13";
3320f6c50668Spatrick case UNW_MIPS_R14:
3321f6c50668Spatrick return "$14";
3322f6c50668Spatrick case UNW_MIPS_R15:
3323f6c50668Spatrick return "$15";
3324f6c50668Spatrick case UNW_MIPS_R16:
3325f6c50668Spatrick return "$16";
3326f6c50668Spatrick case UNW_MIPS_R17:
3327f6c50668Spatrick return "$17";
3328f6c50668Spatrick case UNW_MIPS_R18:
3329f6c50668Spatrick return "$18";
3330f6c50668Spatrick case UNW_MIPS_R19:
3331f6c50668Spatrick return "$19";
3332f6c50668Spatrick case UNW_MIPS_R20:
3333f6c50668Spatrick return "$20";
3334f6c50668Spatrick case UNW_MIPS_R21:
3335f6c50668Spatrick return "$21";
3336f6c50668Spatrick case UNW_MIPS_R22:
3337f6c50668Spatrick return "$22";
3338f6c50668Spatrick case UNW_MIPS_R23:
3339f6c50668Spatrick return "$23";
3340f6c50668Spatrick case UNW_MIPS_R24:
3341f6c50668Spatrick return "$24";
3342f6c50668Spatrick case UNW_MIPS_R25:
3343f6c50668Spatrick return "$25";
3344f6c50668Spatrick case UNW_MIPS_R26:
3345f6c50668Spatrick return "$26";
3346f6c50668Spatrick case UNW_MIPS_R27:
3347f6c50668Spatrick return "$27";
3348f6c50668Spatrick case UNW_MIPS_R28:
3349f6c50668Spatrick return "$28";
3350f6c50668Spatrick case UNW_MIPS_R29:
3351f6c50668Spatrick return "$29";
3352f6c50668Spatrick case UNW_MIPS_R30:
3353f6c50668Spatrick return "$30";
3354f6c50668Spatrick case UNW_MIPS_R31:
3355f6c50668Spatrick return "$31";
3356f6c50668Spatrick case UNW_MIPS_F0:
3357f6c50668Spatrick return "$f0";
3358f6c50668Spatrick case UNW_MIPS_F1:
3359f6c50668Spatrick return "$f1";
3360f6c50668Spatrick case UNW_MIPS_F2:
3361f6c50668Spatrick return "$f2";
3362f6c50668Spatrick case UNW_MIPS_F3:
3363f6c50668Spatrick return "$f3";
3364f6c50668Spatrick case UNW_MIPS_F4:
3365f6c50668Spatrick return "$f4";
3366f6c50668Spatrick case UNW_MIPS_F5:
3367f6c50668Spatrick return "$f5";
3368f6c50668Spatrick case UNW_MIPS_F6:
3369f6c50668Spatrick return "$f6";
3370f6c50668Spatrick case UNW_MIPS_F7:
3371f6c50668Spatrick return "$f7";
3372f6c50668Spatrick case UNW_MIPS_F8:
3373f6c50668Spatrick return "$f8";
3374f6c50668Spatrick case UNW_MIPS_F9:
3375f6c50668Spatrick return "$f9";
3376f6c50668Spatrick case UNW_MIPS_F10:
3377f6c50668Spatrick return "$f10";
3378f6c50668Spatrick case UNW_MIPS_F11:
3379f6c50668Spatrick return "$f11";
3380f6c50668Spatrick case UNW_MIPS_F12:
3381f6c50668Spatrick return "$f12";
3382f6c50668Spatrick case UNW_MIPS_F13:
3383f6c50668Spatrick return "$f13";
3384f6c50668Spatrick case UNW_MIPS_F14:
3385f6c50668Spatrick return "$f14";
3386f6c50668Spatrick case UNW_MIPS_F15:
3387f6c50668Spatrick return "$f15";
3388f6c50668Spatrick case UNW_MIPS_F16:
3389f6c50668Spatrick return "$f16";
3390f6c50668Spatrick case UNW_MIPS_F17:
3391f6c50668Spatrick return "$f17";
3392f6c50668Spatrick case UNW_MIPS_F18:
3393f6c50668Spatrick return "$f18";
3394f6c50668Spatrick case UNW_MIPS_F19:
3395f6c50668Spatrick return "$f19";
3396f6c50668Spatrick case UNW_MIPS_F20:
3397f6c50668Spatrick return "$f20";
3398f6c50668Spatrick case UNW_MIPS_F21:
3399f6c50668Spatrick return "$f21";
3400f6c50668Spatrick case UNW_MIPS_F22:
3401f6c50668Spatrick return "$f22";
3402f6c50668Spatrick case UNW_MIPS_F23:
3403f6c50668Spatrick return "$f23";
3404f6c50668Spatrick case UNW_MIPS_F24:
3405f6c50668Spatrick return "$f24";
3406f6c50668Spatrick case UNW_MIPS_F25:
3407f6c50668Spatrick return "$f25";
3408f6c50668Spatrick case UNW_MIPS_F26:
3409f6c50668Spatrick return "$f26";
3410f6c50668Spatrick case UNW_MIPS_F27:
3411f6c50668Spatrick return "$f27";
3412f6c50668Spatrick case UNW_MIPS_F28:
3413f6c50668Spatrick return "$f28";
3414f6c50668Spatrick case UNW_MIPS_F29:
3415f6c50668Spatrick return "$f29";
3416f6c50668Spatrick case UNW_MIPS_F30:
3417f6c50668Spatrick return "$f30";
3418f6c50668Spatrick case UNW_MIPS_F31:
3419f6c50668Spatrick return "$f31";
3420f6c50668Spatrick case UNW_MIPS_HI:
3421f6c50668Spatrick return "$hi";
3422f6c50668Spatrick case UNW_MIPS_LO:
3423f6c50668Spatrick return "$lo";
3424f6c50668Spatrick default:
3425f6c50668Spatrick return "unknown register";
3426f6c50668Spatrick }
3427f6c50668Spatrick }
3428f6c50668Spatrick #endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3429f6c50668Spatrick
3430f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_SPARC)
3431f6c50668Spatrick /// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3432f6c50668Spatrick /// process.
3433f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_sparc {
3434f6c50668Spatrick public:
3435f6c50668Spatrick Registers_sparc();
3436f6c50668Spatrick Registers_sparc(const void *registers);
3437f6c50668Spatrick
3438f6c50668Spatrick bool validRegister(int num) const;
3439f6c50668Spatrick uint32_t getRegister(int num) const;
3440f6c50668Spatrick void setRegister(int num, uint32_t value);
3441f6c50668Spatrick bool validFloatRegister(int num) const;
3442f6c50668Spatrick double getFloatRegister(int num) const;
3443f6c50668Spatrick void setFloatRegister(int num, double value);
3444f6c50668Spatrick bool validVectorRegister(int num) const;
3445f6c50668Spatrick v128 getVectorRegister(int num) const;
3446f6c50668Spatrick void setVectorRegister(int num, v128 value);
3447f6c50668Spatrick static const char *getRegisterName(int num);
3448f6c50668Spatrick void jumpto();
lastDwarfRegNum()3449*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
3450*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC;
3451*202cdb0eSrobert }
getArch()3452f6c50668Spatrick static int getArch() { return REGISTERS_SPARC; }
3453f6c50668Spatrick
getSP() const3454f6c50668Spatrick uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
setSP(uint32_t value)3455f6c50668Spatrick void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
getIP() const3456f6c50668Spatrick uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
setIP(uint32_t value)3457f6c50668Spatrick void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3458f6c50668Spatrick
3459f6c50668Spatrick private:
3460f6c50668Spatrick struct sparc_thread_state_t {
3461f6c50668Spatrick unsigned int __regs[32];
3462f6c50668Spatrick };
3463f6c50668Spatrick
3464f6c50668Spatrick sparc_thread_state_t _registers;
3465f6c50668Spatrick };
3466f6c50668Spatrick
Registers_sparc(const void * registers)3467f6c50668Spatrick inline Registers_sparc::Registers_sparc(const void *registers) {
3468f6c50668Spatrick static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
3469f6c50668Spatrick "sparc registers do not fit into unw_context_t");
3470f6c50668Spatrick memcpy(&_registers, static_cast<const uint8_t *>(registers),
3471f6c50668Spatrick sizeof(_registers));
3472f6c50668Spatrick }
3473f6c50668Spatrick
Registers_sparc()3474f6c50668Spatrick inline Registers_sparc::Registers_sparc() {
3475f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
3476f6c50668Spatrick }
3477f6c50668Spatrick
validRegister(int regNum) const3478f6c50668Spatrick inline bool Registers_sparc::validRegister(int regNum) const {
3479f6c50668Spatrick if (regNum == UNW_REG_IP)
3480f6c50668Spatrick return true;
3481f6c50668Spatrick if (regNum == UNW_REG_SP)
3482f6c50668Spatrick return true;
3483f6c50668Spatrick if (regNum < 0)
3484f6c50668Spatrick return false;
3485f6c50668Spatrick if (regNum <= UNW_SPARC_I7)
3486f6c50668Spatrick return true;
3487f6c50668Spatrick return false;
3488f6c50668Spatrick }
3489f6c50668Spatrick
getRegister(int regNum) const3490f6c50668Spatrick inline uint32_t Registers_sparc::getRegister(int regNum) const {
3491f6c50668Spatrick if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3492f6c50668Spatrick return _registers.__regs[regNum];
3493f6c50668Spatrick }
3494f6c50668Spatrick
3495f6c50668Spatrick switch (regNum) {
3496f6c50668Spatrick case UNW_REG_IP:
3497f6c50668Spatrick return _registers.__regs[UNW_SPARC_O7];
3498f6c50668Spatrick case UNW_REG_SP:
3499f6c50668Spatrick return _registers.__regs[UNW_SPARC_O6];
3500f6c50668Spatrick }
3501f6c50668Spatrick _LIBUNWIND_ABORT("unsupported sparc register");
3502f6c50668Spatrick }
3503f6c50668Spatrick
setRegister(int regNum,uint32_t value)3504f6c50668Spatrick inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
3505f6c50668Spatrick if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3506f6c50668Spatrick _registers.__regs[regNum] = value;
3507f6c50668Spatrick return;
3508f6c50668Spatrick }
3509f6c50668Spatrick
3510f6c50668Spatrick switch (regNum) {
3511f6c50668Spatrick case UNW_REG_IP:
3512f6c50668Spatrick _registers.__regs[UNW_SPARC_O7] = value;
3513f6c50668Spatrick return;
3514f6c50668Spatrick case UNW_REG_SP:
3515f6c50668Spatrick _registers.__regs[UNW_SPARC_O6] = value;
3516f6c50668Spatrick return;
3517f6c50668Spatrick }
3518f6c50668Spatrick _LIBUNWIND_ABORT("unsupported sparc register");
3519f6c50668Spatrick }
3520f6c50668Spatrick
validFloatRegister(int) const3521f6c50668Spatrick inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3522f6c50668Spatrick
getFloatRegister(int) const3523f6c50668Spatrick inline double Registers_sparc::getFloatRegister(int) const {
3524f6c50668Spatrick _LIBUNWIND_ABORT("no Sparc float registers");
3525f6c50668Spatrick }
3526f6c50668Spatrick
setFloatRegister(int,double)3527f6c50668Spatrick inline void Registers_sparc::setFloatRegister(int, double) {
3528f6c50668Spatrick _LIBUNWIND_ABORT("no Sparc float registers");
3529f6c50668Spatrick }
3530f6c50668Spatrick
validVectorRegister(int) const3531f6c50668Spatrick inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3532f6c50668Spatrick
getVectorRegister(int) const3533f6c50668Spatrick inline v128 Registers_sparc::getVectorRegister(int) const {
3534f6c50668Spatrick _LIBUNWIND_ABORT("no Sparc vector registers");
3535f6c50668Spatrick }
3536f6c50668Spatrick
setVectorRegister(int,v128)3537f6c50668Spatrick inline void Registers_sparc::setVectorRegister(int, v128) {
3538f6c50668Spatrick _LIBUNWIND_ABORT("no Sparc vector registers");
3539f6c50668Spatrick }
3540f6c50668Spatrick
getRegisterName(int regNum)3541f6c50668Spatrick inline const char *Registers_sparc::getRegisterName(int regNum) {
3542f6c50668Spatrick switch (regNum) {
3543f6c50668Spatrick case UNW_REG_IP:
3544f6c50668Spatrick return "pc";
3545f6c50668Spatrick case UNW_SPARC_G0:
3546f6c50668Spatrick return "g0";
3547f6c50668Spatrick case UNW_SPARC_G1:
3548f6c50668Spatrick return "g1";
3549f6c50668Spatrick case UNW_SPARC_G2:
3550f6c50668Spatrick return "g2";
3551f6c50668Spatrick case UNW_SPARC_G3:
3552f6c50668Spatrick return "g3";
3553f6c50668Spatrick case UNW_SPARC_G4:
3554f6c50668Spatrick return "g4";
3555f6c50668Spatrick case UNW_SPARC_G5:
3556f6c50668Spatrick return "g5";
3557f6c50668Spatrick case UNW_SPARC_G6:
3558f6c50668Spatrick return "g6";
3559f6c50668Spatrick case UNW_SPARC_G7:
3560f6c50668Spatrick return "g7";
3561f6c50668Spatrick case UNW_SPARC_O0:
3562f6c50668Spatrick return "o0";
3563f6c50668Spatrick case UNW_SPARC_O1:
3564f6c50668Spatrick return "o1";
3565f6c50668Spatrick case UNW_SPARC_O2:
3566f6c50668Spatrick return "o2";
3567f6c50668Spatrick case UNW_SPARC_O3:
3568f6c50668Spatrick return "o3";
3569f6c50668Spatrick case UNW_SPARC_O4:
3570f6c50668Spatrick return "o4";
3571f6c50668Spatrick case UNW_SPARC_O5:
3572f6c50668Spatrick return "o5";
3573f6c50668Spatrick case UNW_REG_SP:
3574f6c50668Spatrick case UNW_SPARC_O6:
3575f6c50668Spatrick return "sp";
3576f6c50668Spatrick case UNW_SPARC_O7:
3577f6c50668Spatrick return "o7";
3578f6c50668Spatrick case UNW_SPARC_L0:
3579f6c50668Spatrick return "l0";
3580f6c50668Spatrick case UNW_SPARC_L1:
3581f6c50668Spatrick return "l1";
3582f6c50668Spatrick case UNW_SPARC_L2:
3583f6c50668Spatrick return "l2";
3584f6c50668Spatrick case UNW_SPARC_L3:
3585f6c50668Spatrick return "l3";
3586f6c50668Spatrick case UNW_SPARC_L4:
3587f6c50668Spatrick return "l4";
3588f6c50668Spatrick case UNW_SPARC_L5:
3589f6c50668Spatrick return "l5";
3590f6c50668Spatrick case UNW_SPARC_L6:
3591f6c50668Spatrick return "l6";
3592f6c50668Spatrick case UNW_SPARC_L7:
3593f6c50668Spatrick return "l7";
3594f6c50668Spatrick case UNW_SPARC_I0:
3595f6c50668Spatrick return "i0";
3596f6c50668Spatrick case UNW_SPARC_I1:
3597f6c50668Spatrick return "i1";
3598f6c50668Spatrick case UNW_SPARC_I2:
3599f6c50668Spatrick return "i2";
3600f6c50668Spatrick case UNW_SPARC_I3:
3601f6c50668Spatrick return "i3";
3602f6c50668Spatrick case UNW_SPARC_I4:
3603f6c50668Spatrick return "i4";
3604f6c50668Spatrick case UNW_SPARC_I5:
3605f6c50668Spatrick return "i5";
3606f6c50668Spatrick case UNW_SPARC_I6:
3607f6c50668Spatrick return "fp";
3608f6c50668Spatrick case UNW_SPARC_I7:
3609f6c50668Spatrick return "i7";
3610f6c50668Spatrick default:
3611f6c50668Spatrick return "unknown register";
3612f6c50668Spatrick }
3613f6c50668Spatrick }
3614f6c50668Spatrick #endif // _LIBUNWIND_TARGET_SPARC
3615f6c50668Spatrick
3616*202cdb0eSrobert #if defined(_LIBUNWIND_TARGET_SPARC64)
3617*202cdb0eSrobert /// Registers_sparc64 holds the register state of a thread in a 64-bit
3618*202cdb0eSrobert /// sparc process.
3619*202cdb0eSrobert class _LIBUNWIND_HIDDEN Registers_sparc64 {
3620*202cdb0eSrobert public:
3621*202cdb0eSrobert Registers_sparc64() = default;
3622*202cdb0eSrobert Registers_sparc64(const void *registers);
3623*202cdb0eSrobert
3624*202cdb0eSrobert bool validRegister(int num) const;
3625*202cdb0eSrobert uint64_t getRegister(int num) const;
3626*202cdb0eSrobert void setRegister(int num, uint64_t value);
3627*202cdb0eSrobert bool validFloatRegister(int num) const;
3628*202cdb0eSrobert double getFloatRegister(int num) const;
3629*202cdb0eSrobert void setFloatRegister(int num, double value);
3630*202cdb0eSrobert bool validVectorRegister(int num) const;
3631*202cdb0eSrobert v128 getVectorRegister(int num) const;
3632*202cdb0eSrobert void setVectorRegister(int num, v128 value);
3633*202cdb0eSrobert const char *getRegisterName(int num);
3634*202cdb0eSrobert void jumpto();
lastDwarfRegNum()3635*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
3636*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;
3637*202cdb0eSrobert }
getArch()3638*202cdb0eSrobert static int getArch() { return REGISTERS_SPARC64; }
3639*202cdb0eSrobert
getSP() const3640*202cdb0eSrobert uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; }
setSP(uint64_t value)3641*202cdb0eSrobert void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; }
getIP() const3642*202cdb0eSrobert uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
setIP(uint64_t value)3643*202cdb0eSrobert void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
getWCookie() const3644*202cdb0eSrobert uint64_t getWCookie() const { return _wcookie; }
3645*202cdb0eSrobert
3646*202cdb0eSrobert private:
3647*202cdb0eSrobert struct sparc64_thread_state_t {
3648*202cdb0eSrobert uint64_t __regs[32];
3649*202cdb0eSrobert };
3650*202cdb0eSrobert
3651*202cdb0eSrobert sparc64_thread_state_t _registers{};
3652*202cdb0eSrobert uint64_t _wcookie = 0;
3653*202cdb0eSrobert };
3654*202cdb0eSrobert
Registers_sparc64(const void * registers)3655*202cdb0eSrobert inline Registers_sparc64::Registers_sparc64(const void *registers) {
3656*202cdb0eSrobert static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit),
3657*202cdb0eSrobert "sparc64 registers do not fit into unw_context_t");
3658*202cdb0eSrobert memcpy(&_registers, registers, sizeof(_registers));
3659*202cdb0eSrobert memcpy(&_wcookie,
3660*202cdb0eSrobert static_cast<const uint8_t *>(registers) + sizeof(_registers),
3661*202cdb0eSrobert sizeof(_wcookie));
3662*202cdb0eSrobert }
3663*202cdb0eSrobert
validRegister(int regNum) const3664*202cdb0eSrobert inline bool Registers_sparc64::validRegister(int regNum) const {
3665*202cdb0eSrobert if (regNum == UNW_REG_IP)
3666*202cdb0eSrobert return true;
3667*202cdb0eSrobert if (regNum == UNW_REG_SP)
3668*202cdb0eSrobert return true;
3669*202cdb0eSrobert if (regNum < 0)
3670*202cdb0eSrobert return false;
3671*202cdb0eSrobert if (regNum <= UNW_SPARC_I7)
3672*202cdb0eSrobert return true;
3673*202cdb0eSrobert return false;
3674*202cdb0eSrobert }
3675*202cdb0eSrobert
getRegister(int regNum) const3676*202cdb0eSrobert inline uint64_t Registers_sparc64::getRegister(int regNum) const {
3677*202cdb0eSrobert if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7)
3678*202cdb0eSrobert return _registers.__regs[regNum];
3679*202cdb0eSrobert
3680*202cdb0eSrobert switch (regNum) {
3681*202cdb0eSrobert case UNW_REG_IP:
3682*202cdb0eSrobert return _registers.__regs[UNW_SPARC_O7];
3683*202cdb0eSrobert case UNW_REG_SP:
3684*202cdb0eSrobert return _registers.__regs[UNW_SPARC_O6] + 2047;
3685*202cdb0eSrobert }
3686*202cdb0eSrobert _LIBUNWIND_ABORT("unsupported sparc64 register");
3687*202cdb0eSrobert }
3688*202cdb0eSrobert
setRegister(int regNum,uint64_t value)3689*202cdb0eSrobert inline void Registers_sparc64::setRegister(int regNum, uint64_t value) {
3690*202cdb0eSrobert if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) {
3691*202cdb0eSrobert _registers.__regs[regNum] = value;
3692*202cdb0eSrobert return;
3693*202cdb0eSrobert }
3694*202cdb0eSrobert
3695*202cdb0eSrobert switch (regNum) {
3696*202cdb0eSrobert case UNW_REG_IP:
3697*202cdb0eSrobert _registers.__regs[UNW_SPARC_O7] = value;
3698*202cdb0eSrobert return;
3699*202cdb0eSrobert case UNW_REG_SP:
3700*202cdb0eSrobert _registers.__regs[UNW_SPARC_O6] = value - 2047;
3701*202cdb0eSrobert return;
3702*202cdb0eSrobert }
3703*202cdb0eSrobert _LIBUNWIND_ABORT("unsupported sparc64 register");
3704*202cdb0eSrobert }
3705*202cdb0eSrobert
validFloatRegister(int) const3706*202cdb0eSrobert inline bool Registers_sparc64::validFloatRegister(int) const { return false; }
3707*202cdb0eSrobert
getFloatRegister(int) const3708*202cdb0eSrobert inline double Registers_sparc64::getFloatRegister(int) const {
3709*202cdb0eSrobert _LIBUNWIND_ABORT("no sparc64 float registers");
3710*202cdb0eSrobert }
3711*202cdb0eSrobert
setFloatRegister(int,double)3712*202cdb0eSrobert inline void Registers_sparc64::setFloatRegister(int, double) {
3713*202cdb0eSrobert _LIBUNWIND_ABORT("no sparc64 float registers");
3714*202cdb0eSrobert }
3715*202cdb0eSrobert
validVectorRegister(int) const3716*202cdb0eSrobert inline bool Registers_sparc64::validVectorRegister(int) const { return false; }
3717*202cdb0eSrobert
getVectorRegister(int) const3718*202cdb0eSrobert inline v128 Registers_sparc64::getVectorRegister(int) const {
3719*202cdb0eSrobert _LIBUNWIND_ABORT("no sparc64 vector registers");
3720*202cdb0eSrobert }
3721*202cdb0eSrobert
setVectorRegister(int,v128)3722*202cdb0eSrobert inline void Registers_sparc64::setVectorRegister(int, v128) {
3723*202cdb0eSrobert _LIBUNWIND_ABORT("no sparc64 vector registers");
3724*202cdb0eSrobert }
3725*202cdb0eSrobert
getRegisterName(int regNum)3726*202cdb0eSrobert inline const char *Registers_sparc64::getRegisterName(int regNum) {
3727*202cdb0eSrobert switch (regNum) {
3728*202cdb0eSrobert case UNW_REG_IP:
3729*202cdb0eSrobert return "pc";
3730*202cdb0eSrobert case UNW_SPARC_G0:
3731*202cdb0eSrobert return "g0";
3732*202cdb0eSrobert case UNW_SPARC_G1:
3733*202cdb0eSrobert return "g1";
3734*202cdb0eSrobert case UNW_SPARC_G2:
3735*202cdb0eSrobert return "g2";
3736*202cdb0eSrobert case UNW_SPARC_G3:
3737*202cdb0eSrobert return "g3";
3738*202cdb0eSrobert case UNW_SPARC_G4:
3739*202cdb0eSrobert return "g4";
3740*202cdb0eSrobert case UNW_SPARC_G5:
3741*202cdb0eSrobert return "g5";
3742*202cdb0eSrobert case UNW_SPARC_G6:
3743*202cdb0eSrobert return "g6";
3744*202cdb0eSrobert case UNW_SPARC_G7:
3745*202cdb0eSrobert return "g7";
3746*202cdb0eSrobert case UNW_SPARC_O0:
3747*202cdb0eSrobert return "o0";
3748*202cdb0eSrobert case UNW_SPARC_O1:
3749*202cdb0eSrobert return "o1";
3750*202cdb0eSrobert case UNW_SPARC_O2:
3751*202cdb0eSrobert return "o2";
3752*202cdb0eSrobert case UNW_SPARC_O3:
3753*202cdb0eSrobert return "o3";
3754*202cdb0eSrobert case UNW_SPARC_O4:
3755*202cdb0eSrobert return "o4";
3756*202cdb0eSrobert case UNW_SPARC_O5:
3757*202cdb0eSrobert return "o5";
3758*202cdb0eSrobert case UNW_REG_SP:
3759*202cdb0eSrobert case UNW_SPARC_O6:
3760*202cdb0eSrobert return "o6";
3761*202cdb0eSrobert case UNW_SPARC_O7:
3762*202cdb0eSrobert return "o7";
3763*202cdb0eSrobert case UNW_SPARC_L0:
3764*202cdb0eSrobert return "l0";
3765*202cdb0eSrobert case UNW_SPARC_L1:
3766*202cdb0eSrobert return "l1";
3767*202cdb0eSrobert case UNW_SPARC_L2:
3768*202cdb0eSrobert return "l2";
3769*202cdb0eSrobert case UNW_SPARC_L3:
3770*202cdb0eSrobert return "l3";
3771*202cdb0eSrobert case UNW_SPARC_L4:
3772*202cdb0eSrobert return "l4";
3773*202cdb0eSrobert case UNW_SPARC_L5:
3774*202cdb0eSrobert return "l5";
3775*202cdb0eSrobert case UNW_SPARC_L6:
3776*202cdb0eSrobert return "l6";
3777*202cdb0eSrobert case UNW_SPARC_L7:
3778*202cdb0eSrobert return "l7";
3779*202cdb0eSrobert case UNW_SPARC_I0:
3780*202cdb0eSrobert return "i0";
3781*202cdb0eSrobert case UNW_SPARC_I1:
3782*202cdb0eSrobert return "i1";
3783*202cdb0eSrobert case UNW_SPARC_I2:
3784*202cdb0eSrobert return "i2";
3785*202cdb0eSrobert case UNW_SPARC_I3:
3786*202cdb0eSrobert return "i3";
3787*202cdb0eSrobert case UNW_SPARC_I4:
3788*202cdb0eSrobert return "i4";
3789*202cdb0eSrobert case UNW_SPARC_I5:
3790*202cdb0eSrobert return "i5";
3791*202cdb0eSrobert case UNW_SPARC_I6:
3792*202cdb0eSrobert return "i6";
3793*202cdb0eSrobert case UNW_SPARC_I7:
3794*202cdb0eSrobert return "i7";
3795*202cdb0eSrobert default:
3796*202cdb0eSrobert return "unknown register";
3797*202cdb0eSrobert }
3798*202cdb0eSrobert }
3799*202cdb0eSrobert #endif // _LIBUNWIND_TARGET_SPARC64
3800*202cdb0eSrobert
3801f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_HEXAGON)
3802f6c50668Spatrick /// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
3803f6c50668Spatrick /// process.
3804f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_hexagon {
3805f6c50668Spatrick public:
3806f6c50668Spatrick Registers_hexagon();
3807f6c50668Spatrick Registers_hexagon(const void *registers);
3808f6c50668Spatrick
3809f6c50668Spatrick bool validRegister(int num) const;
3810f6c50668Spatrick uint32_t getRegister(int num) const;
3811f6c50668Spatrick void setRegister(int num, uint32_t value);
3812f6c50668Spatrick bool validFloatRegister(int num) const;
3813f6c50668Spatrick double getFloatRegister(int num) const;
3814f6c50668Spatrick void setFloatRegister(int num, double value);
3815f6c50668Spatrick bool validVectorRegister(int num) const;
3816f6c50668Spatrick v128 getVectorRegister(int num) const;
3817f6c50668Spatrick void setVectorRegister(int num, v128 value);
3818f6c50668Spatrick const char *getRegisterName(int num);
3819f6c50668Spatrick void jumpto();
lastDwarfRegNum()3820*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
3821*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON;
3822*202cdb0eSrobert }
getArch()3823f6c50668Spatrick static int getArch() { return REGISTERS_HEXAGON; }
3824f6c50668Spatrick
getSP() const3825f6c50668Spatrick uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }
setSP(uint32_t value)3826f6c50668Spatrick void setSP(uint32_t value) { _registers.__r[UNW_HEXAGON_R29] = value; }
getIP() const3827f6c50668Spatrick uint32_t getIP() const { return _registers.__r[UNW_HEXAGON_PC]; }
setIP(uint32_t value)3828f6c50668Spatrick void setIP(uint32_t value) { _registers.__r[UNW_HEXAGON_PC] = value; }
3829f6c50668Spatrick
3830f6c50668Spatrick private:
3831f6c50668Spatrick struct hexagon_thread_state_t {
3832f6c50668Spatrick unsigned int __r[35];
3833f6c50668Spatrick };
3834f6c50668Spatrick
3835f6c50668Spatrick hexagon_thread_state_t _registers;
3836f6c50668Spatrick };
3837f6c50668Spatrick
Registers_hexagon(const void * registers)3838f6c50668Spatrick inline Registers_hexagon::Registers_hexagon(const void *registers) {
3839f6c50668Spatrick static_assert((check_fit<Registers_hexagon, unw_context_t>::does_fit),
3840f6c50668Spatrick "hexagon registers do not fit into unw_context_t");
3841f6c50668Spatrick memcpy(&_registers, static_cast<const uint8_t *>(registers),
3842f6c50668Spatrick sizeof(_registers));
3843f6c50668Spatrick }
3844f6c50668Spatrick
Registers_hexagon()3845f6c50668Spatrick inline Registers_hexagon::Registers_hexagon() {
3846f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
3847f6c50668Spatrick }
3848f6c50668Spatrick
validRegister(int regNum) const3849f6c50668Spatrick inline bool Registers_hexagon::validRegister(int regNum) const {
3850f6c50668Spatrick if (regNum <= UNW_HEXAGON_R31)
3851f6c50668Spatrick return true;
3852f6c50668Spatrick return false;
3853f6c50668Spatrick }
3854f6c50668Spatrick
getRegister(int regNum) const3855f6c50668Spatrick inline uint32_t Registers_hexagon::getRegister(int regNum) const {
3856f6c50668Spatrick if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31)
3857f6c50668Spatrick return _registers.__r[regNum - UNW_HEXAGON_R0];
3858f6c50668Spatrick
3859f6c50668Spatrick switch (regNum) {
3860f6c50668Spatrick case UNW_REG_IP:
3861f6c50668Spatrick return _registers.__r[UNW_HEXAGON_PC];
3862f6c50668Spatrick case UNW_REG_SP:
3863f6c50668Spatrick return _registers.__r[UNW_HEXAGON_R29];
3864f6c50668Spatrick }
3865f6c50668Spatrick _LIBUNWIND_ABORT("unsupported hexagon register");
3866f6c50668Spatrick }
3867f6c50668Spatrick
setRegister(int regNum,uint32_t value)3868f6c50668Spatrick inline void Registers_hexagon::setRegister(int regNum, uint32_t value) {
3869f6c50668Spatrick if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) {
3870f6c50668Spatrick _registers.__r[regNum - UNW_HEXAGON_R0] = value;
3871f6c50668Spatrick return;
3872f6c50668Spatrick }
3873f6c50668Spatrick
3874f6c50668Spatrick switch (regNum) {
3875f6c50668Spatrick case UNW_REG_IP:
3876f6c50668Spatrick _registers.__r[UNW_HEXAGON_PC] = value;
3877f6c50668Spatrick return;
3878f6c50668Spatrick case UNW_REG_SP:
3879f6c50668Spatrick _registers.__r[UNW_HEXAGON_R29] = value;
3880f6c50668Spatrick return;
3881f6c50668Spatrick }
3882f6c50668Spatrick _LIBUNWIND_ABORT("unsupported hexagon register");
3883f6c50668Spatrick }
3884f6c50668Spatrick
validFloatRegister(int) const3885f6c50668Spatrick inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {
3886f6c50668Spatrick return false;
3887f6c50668Spatrick }
3888f6c50668Spatrick
getFloatRegister(int) const3889f6c50668Spatrick inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {
3890f6c50668Spatrick _LIBUNWIND_ABORT("hexagon float support not implemented");
3891f6c50668Spatrick }
3892f6c50668Spatrick
setFloatRegister(int,double)3893f6c50668Spatrick inline void Registers_hexagon::setFloatRegister(int /* regNum */,
3894f6c50668Spatrick double /* value */) {
3895f6c50668Spatrick _LIBUNWIND_ABORT("hexagon float support not implemented");
3896f6c50668Spatrick }
3897f6c50668Spatrick
validVectorRegister(int) const3898f6c50668Spatrick inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {
3899f6c50668Spatrick return false;
3900f6c50668Spatrick }
3901f6c50668Spatrick
getVectorRegister(int) const3902f6c50668Spatrick inline v128 Registers_hexagon::getVectorRegister(int /* regNum */) const {
3903f6c50668Spatrick _LIBUNWIND_ABORT("hexagon vector support not implemented");
3904f6c50668Spatrick }
3905f6c50668Spatrick
setVectorRegister(int,v128)3906f6c50668Spatrick inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128 /* value */) {
3907f6c50668Spatrick _LIBUNWIND_ABORT("hexagon vector support not implemented");
3908f6c50668Spatrick }
3909f6c50668Spatrick
getRegisterName(int regNum)3910f6c50668Spatrick inline const char *Registers_hexagon::getRegisterName(int regNum) {
3911f6c50668Spatrick switch (regNum) {
3912f6c50668Spatrick case UNW_HEXAGON_R0:
3913f6c50668Spatrick return "r0";
3914f6c50668Spatrick case UNW_HEXAGON_R1:
3915f6c50668Spatrick return "r1";
3916f6c50668Spatrick case UNW_HEXAGON_R2:
3917f6c50668Spatrick return "r2";
3918f6c50668Spatrick case UNW_HEXAGON_R3:
3919f6c50668Spatrick return "r3";
3920f6c50668Spatrick case UNW_HEXAGON_R4:
3921f6c50668Spatrick return "r4";
3922f6c50668Spatrick case UNW_HEXAGON_R5:
3923f6c50668Spatrick return "r5";
3924f6c50668Spatrick case UNW_HEXAGON_R6:
3925f6c50668Spatrick return "r6";
3926f6c50668Spatrick case UNW_HEXAGON_R7:
3927f6c50668Spatrick return "r7";
3928f6c50668Spatrick case UNW_HEXAGON_R8:
3929f6c50668Spatrick return "r8";
3930f6c50668Spatrick case UNW_HEXAGON_R9:
3931f6c50668Spatrick return "r9";
3932f6c50668Spatrick case UNW_HEXAGON_R10:
3933f6c50668Spatrick return "r10";
3934f6c50668Spatrick case UNW_HEXAGON_R11:
3935f6c50668Spatrick return "r11";
3936f6c50668Spatrick case UNW_HEXAGON_R12:
3937f6c50668Spatrick return "r12";
3938f6c50668Spatrick case UNW_HEXAGON_R13:
3939f6c50668Spatrick return "r13";
3940f6c50668Spatrick case UNW_HEXAGON_R14:
3941f6c50668Spatrick return "r14";
3942f6c50668Spatrick case UNW_HEXAGON_R15:
3943f6c50668Spatrick return "r15";
3944f6c50668Spatrick case UNW_HEXAGON_R16:
3945f6c50668Spatrick return "r16";
3946f6c50668Spatrick case UNW_HEXAGON_R17:
3947f6c50668Spatrick return "r17";
3948f6c50668Spatrick case UNW_HEXAGON_R18:
3949f6c50668Spatrick return "r18";
3950f6c50668Spatrick case UNW_HEXAGON_R19:
3951f6c50668Spatrick return "r19";
3952f6c50668Spatrick case UNW_HEXAGON_R20:
3953f6c50668Spatrick return "r20";
3954f6c50668Spatrick case UNW_HEXAGON_R21:
3955f6c50668Spatrick return "r21";
3956f6c50668Spatrick case UNW_HEXAGON_R22:
3957f6c50668Spatrick return "r22";
3958f6c50668Spatrick case UNW_HEXAGON_R23:
3959f6c50668Spatrick return "r23";
3960f6c50668Spatrick case UNW_HEXAGON_R24:
3961f6c50668Spatrick return "r24";
3962f6c50668Spatrick case UNW_HEXAGON_R25:
3963f6c50668Spatrick return "r25";
3964f6c50668Spatrick case UNW_HEXAGON_R26:
3965f6c50668Spatrick return "r26";
3966f6c50668Spatrick case UNW_HEXAGON_R27:
3967f6c50668Spatrick return "r27";
3968f6c50668Spatrick case UNW_HEXAGON_R28:
3969f6c50668Spatrick return "r28";
3970f6c50668Spatrick case UNW_HEXAGON_R29:
3971f6c50668Spatrick return "r29";
3972f6c50668Spatrick case UNW_HEXAGON_R30:
3973f6c50668Spatrick return "r30";
3974f6c50668Spatrick case UNW_HEXAGON_R31:
3975f6c50668Spatrick return "r31";
3976f6c50668Spatrick default:
3977f6c50668Spatrick return "unknown register";
3978f6c50668Spatrick }
3979f6c50668Spatrick
3980f6c50668Spatrick }
3981f6c50668Spatrick #endif // _LIBUNWIND_TARGET_HEXAGON
3982f6c50668Spatrick
3983f6c50668Spatrick
3984f6c50668Spatrick #if defined(_LIBUNWIND_TARGET_RISCV)
3985a0747c9fSpatrick /// Registers_riscv holds the register state of a thread in a RISC-V
3986f6c50668Spatrick /// process.
3987a0747c9fSpatrick
3988a0747c9fSpatrick // This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.
3989a0747c9fSpatrick # ifdef __riscv
3990a0747c9fSpatrick # if __riscv_xlen == 32
3991a0747c9fSpatrick typedef uint32_t reg_t;
3992a0747c9fSpatrick # elif __riscv_xlen == 64
3993a0747c9fSpatrick typedef uint64_t reg_t;
3994a0747c9fSpatrick # else
3995a0747c9fSpatrick # error "Unsupported __riscv_xlen"
3996a0747c9fSpatrick # endif
3997a0747c9fSpatrick
3998a0747c9fSpatrick # if defined(__riscv_flen)
3999a0747c9fSpatrick # if __riscv_flen == 64
4000a0747c9fSpatrick typedef double fp_t;
4001a0747c9fSpatrick # elif __riscv_flen == 32
4002a0747c9fSpatrick typedef float fp_t;
4003a0747c9fSpatrick # else
4004a0747c9fSpatrick # error "Unsupported __riscv_flen"
4005a0747c9fSpatrick # endif
4006a0747c9fSpatrick # else
4007*202cdb0eSrobert // This is just for suppressing undeclared error of fp_t.
4008a0747c9fSpatrick typedef double fp_t;
4009a0747c9fSpatrick # endif
4010a0747c9fSpatrick # else
4011a0747c9fSpatrick // Use Max possible width when cross unwinding
4012a0747c9fSpatrick typedef uint64_t reg_t;
4013a0747c9fSpatrick typedef double fp_t;
4014a0747c9fSpatrick # define __riscv_xlen 64
4015a0747c9fSpatrick # define __riscv_flen 64
4016a0747c9fSpatrick #endif
4017a0747c9fSpatrick
4018a0747c9fSpatrick /// Registers_riscv holds the register state of a thread.
4019f6c50668Spatrick class _LIBUNWIND_HIDDEN Registers_riscv {
4020f6c50668Spatrick public:
4021f6c50668Spatrick Registers_riscv();
4022f6c50668Spatrick Registers_riscv(const void *registers);
4023f6c50668Spatrick
4024f6c50668Spatrick bool validRegister(int num) const;
4025a0747c9fSpatrick reg_t getRegister(int num) const;
4026a0747c9fSpatrick void setRegister(int num, reg_t value);
4027f6c50668Spatrick bool validFloatRegister(int num) const;
4028a0747c9fSpatrick fp_t getFloatRegister(int num) const;
4029a0747c9fSpatrick void setFloatRegister(int num, fp_t value);
4030f6c50668Spatrick bool validVectorRegister(int num) const;
4031f6c50668Spatrick v128 getVectorRegister(int num) const;
4032f6c50668Spatrick void setVectorRegister(int num, v128 value);
4033f6c50668Spatrick static const char *getRegisterName(int num);
4034f6c50668Spatrick void jumpto();
lastDwarfRegNum()4035*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
4036*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV;
4037*202cdb0eSrobert }
getArch()4038f6c50668Spatrick static int getArch() { return REGISTERS_RISCV; }
4039f6c50668Spatrick
getSP() const4040a0747c9fSpatrick reg_t getSP() const { return _registers[2]; }
setSP(reg_t value)4041a0747c9fSpatrick void setSP(reg_t value) { _registers[2] = value; }
getIP() const4042a0747c9fSpatrick reg_t getIP() const { return _registers[0]; }
setIP(reg_t value)4043a0747c9fSpatrick void setIP(reg_t value) { _registers[0] = value; }
4044f6c50668Spatrick
4045f6c50668Spatrick private:
4046f6c50668Spatrick // _registers[0] holds the pc
4047a0747c9fSpatrick reg_t _registers[32];
4048a0747c9fSpatrick # if defined(__riscv_flen)
4049a0747c9fSpatrick fp_t _floats[32];
4050a0747c9fSpatrick # endif
4051f6c50668Spatrick };
4052f6c50668Spatrick
Registers_riscv(const void * registers)4053f6c50668Spatrick inline Registers_riscv::Registers_riscv(const void *registers) {
4054f6c50668Spatrick static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit),
4055f6c50668Spatrick "riscv registers do not fit into unw_context_t");
4056f6c50668Spatrick memcpy(&_registers, registers, sizeof(_registers));
4057a0747c9fSpatrick # if __riscv_xlen == 32
4058a0747c9fSpatrick static_assert(sizeof(_registers) == 0x80,
4059a0747c9fSpatrick "expected float registers to be at offset 128");
4060a0747c9fSpatrick # elif __riscv_xlen == 64
4061f6c50668Spatrick static_assert(sizeof(_registers) == 0x100,
4062f6c50668Spatrick "expected float registers to be at offset 256");
4063a0747c9fSpatrick # else
4064a0747c9fSpatrick # error "Unexpected float registers."
4065a0747c9fSpatrick # endif
4066a0747c9fSpatrick
4067a0747c9fSpatrick # if defined(__riscv_flen)
4068f6c50668Spatrick memcpy(_floats,
4069f6c50668Spatrick static_cast<const uint8_t *>(registers) + sizeof(_registers),
4070f6c50668Spatrick sizeof(_floats));
4071a0747c9fSpatrick # endif
4072f6c50668Spatrick }
4073f6c50668Spatrick
Registers_riscv()4074f6c50668Spatrick inline Registers_riscv::Registers_riscv() {
4075f6c50668Spatrick memset(&_registers, 0, sizeof(_registers));
4076a0747c9fSpatrick # if defined(__riscv_flen)
4077f6c50668Spatrick memset(&_floats, 0, sizeof(_floats));
4078a0747c9fSpatrick # endif
4079f6c50668Spatrick }
4080f6c50668Spatrick
validRegister(int regNum) const4081f6c50668Spatrick inline bool Registers_riscv::validRegister(int regNum) const {
4082f6c50668Spatrick if (regNum == UNW_REG_IP)
4083f6c50668Spatrick return true;
4084f6c50668Spatrick if (regNum == UNW_REG_SP)
4085f6c50668Spatrick return true;
4086f6c50668Spatrick if (regNum < 0)
4087f6c50668Spatrick return false;
4088*202cdb0eSrobert if (regNum == UNW_RISCV_VLENB)
4089*202cdb0eSrobert return true;
4090f6c50668Spatrick if (regNum > UNW_RISCV_F31)
4091f6c50668Spatrick return false;
4092f6c50668Spatrick return true;
4093f6c50668Spatrick }
4094f6c50668Spatrick
getRegister(int regNum) const4095a0747c9fSpatrick inline reg_t Registers_riscv::getRegister(int regNum) const {
4096f6c50668Spatrick if (regNum == UNW_REG_IP)
4097f6c50668Spatrick return _registers[0];
4098f6c50668Spatrick if (regNum == UNW_REG_SP)
4099f6c50668Spatrick return _registers[2];
4100f6c50668Spatrick if (regNum == UNW_RISCV_X0)
4101f6c50668Spatrick return 0;
4102f6c50668Spatrick if ((regNum > 0) && (regNum < 32))
4103f6c50668Spatrick return _registers[regNum];
4104*202cdb0eSrobert if (regNum == UNW_RISCV_VLENB) {
4105*202cdb0eSrobert reg_t vlenb;
4106*202cdb0eSrobert __asm__("csrr %0, 0xC22" : "=r"(vlenb));
4107*202cdb0eSrobert return vlenb;
4108*202cdb0eSrobert }
4109f6c50668Spatrick _LIBUNWIND_ABORT("unsupported riscv register");
4110f6c50668Spatrick }
4111f6c50668Spatrick
setRegister(int regNum,reg_t value)4112a0747c9fSpatrick inline void Registers_riscv::setRegister(int regNum, reg_t value) {
4113f6c50668Spatrick if (regNum == UNW_REG_IP)
4114f6c50668Spatrick _registers[0] = value;
4115f6c50668Spatrick else if (regNum == UNW_REG_SP)
4116f6c50668Spatrick _registers[2] = value;
4117f6c50668Spatrick else if (regNum == UNW_RISCV_X0)
4118f6c50668Spatrick /* x0 is hardwired to zero */
4119f6c50668Spatrick return;
4120f6c50668Spatrick else if ((regNum > 0) && (regNum < 32))
4121f6c50668Spatrick _registers[regNum] = value;
4122f6c50668Spatrick else
4123f6c50668Spatrick _LIBUNWIND_ABORT("unsupported riscv register");
4124f6c50668Spatrick }
4125f6c50668Spatrick
getRegisterName(int regNum)4126f6c50668Spatrick inline const char *Registers_riscv::getRegisterName(int regNum) {
4127f6c50668Spatrick switch (regNum) {
4128f6c50668Spatrick case UNW_REG_IP:
4129f6c50668Spatrick return "pc";
4130f6c50668Spatrick case UNW_REG_SP:
4131f6c50668Spatrick return "sp";
4132f6c50668Spatrick case UNW_RISCV_X0:
4133f6c50668Spatrick return "zero";
4134f6c50668Spatrick case UNW_RISCV_X1:
4135f6c50668Spatrick return "ra";
4136f6c50668Spatrick case UNW_RISCV_X2:
4137f6c50668Spatrick return "sp";
4138f6c50668Spatrick case UNW_RISCV_X3:
4139f6c50668Spatrick return "gp";
4140f6c50668Spatrick case UNW_RISCV_X4:
4141f6c50668Spatrick return "tp";
4142f6c50668Spatrick case UNW_RISCV_X5:
4143f6c50668Spatrick return "t0";
4144f6c50668Spatrick case UNW_RISCV_X6:
4145f6c50668Spatrick return "t1";
4146f6c50668Spatrick case UNW_RISCV_X7:
4147f6c50668Spatrick return "t2";
4148f6c50668Spatrick case UNW_RISCV_X8:
4149f6c50668Spatrick return "s0";
4150f6c50668Spatrick case UNW_RISCV_X9:
4151f6c50668Spatrick return "s1";
4152f6c50668Spatrick case UNW_RISCV_X10:
4153f6c50668Spatrick return "a0";
4154f6c50668Spatrick case UNW_RISCV_X11:
4155f6c50668Spatrick return "a1";
4156f6c50668Spatrick case UNW_RISCV_X12:
4157f6c50668Spatrick return "a2";
4158f6c50668Spatrick case UNW_RISCV_X13:
4159f6c50668Spatrick return "a3";
4160f6c50668Spatrick case UNW_RISCV_X14:
4161f6c50668Spatrick return "a4";
4162f6c50668Spatrick case UNW_RISCV_X15:
4163f6c50668Spatrick return "a5";
4164f6c50668Spatrick case UNW_RISCV_X16:
4165f6c50668Spatrick return "a6";
4166f6c50668Spatrick case UNW_RISCV_X17:
4167f6c50668Spatrick return "a7";
4168f6c50668Spatrick case UNW_RISCV_X18:
4169f6c50668Spatrick return "s2";
4170f6c50668Spatrick case UNW_RISCV_X19:
4171f6c50668Spatrick return "s3";
4172f6c50668Spatrick case UNW_RISCV_X20:
4173f6c50668Spatrick return "s4";
4174f6c50668Spatrick case UNW_RISCV_X21:
4175f6c50668Spatrick return "s5";
4176f6c50668Spatrick case UNW_RISCV_X22:
4177f6c50668Spatrick return "s6";
4178f6c50668Spatrick case UNW_RISCV_X23:
4179f6c50668Spatrick return "s7";
4180f6c50668Spatrick case UNW_RISCV_X24:
4181f6c50668Spatrick return "s8";
4182f6c50668Spatrick case UNW_RISCV_X25:
4183f6c50668Spatrick return "s9";
4184f6c50668Spatrick case UNW_RISCV_X26:
4185f6c50668Spatrick return "s10";
4186f6c50668Spatrick case UNW_RISCV_X27:
4187f6c50668Spatrick return "s11";
4188f6c50668Spatrick case UNW_RISCV_X28:
4189f6c50668Spatrick return "t3";
4190f6c50668Spatrick case UNW_RISCV_X29:
4191f6c50668Spatrick return "t4";
4192f6c50668Spatrick case UNW_RISCV_X30:
4193f6c50668Spatrick return "t5";
4194f6c50668Spatrick case UNW_RISCV_X31:
4195f6c50668Spatrick return "t6";
4196f6c50668Spatrick case UNW_RISCV_F0:
4197f6c50668Spatrick return "ft0";
4198f6c50668Spatrick case UNW_RISCV_F1:
4199f6c50668Spatrick return "ft1";
4200f6c50668Spatrick case UNW_RISCV_F2:
4201f6c50668Spatrick return "ft2";
4202f6c50668Spatrick case UNW_RISCV_F3:
4203f6c50668Spatrick return "ft3";
4204f6c50668Spatrick case UNW_RISCV_F4:
4205f6c50668Spatrick return "ft4";
4206f6c50668Spatrick case UNW_RISCV_F5:
4207f6c50668Spatrick return "ft5";
4208f6c50668Spatrick case UNW_RISCV_F6:
4209f6c50668Spatrick return "ft6";
4210f6c50668Spatrick case UNW_RISCV_F7:
4211f6c50668Spatrick return "ft7";
4212f6c50668Spatrick case UNW_RISCV_F8:
4213f6c50668Spatrick return "fs0";
4214f6c50668Spatrick case UNW_RISCV_F9:
4215f6c50668Spatrick return "fs1";
4216f6c50668Spatrick case UNW_RISCV_F10:
4217f6c50668Spatrick return "fa0";
4218f6c50668Spatrick case UNW_RISCV_F11:
4219f6c50668Spatrick return "fa1";
4220f6c50668Spatrick case UNW_RISCV_F12:
4221f6c50668Spatrick return "fa2";
4222f6c50668Spatrick case UNW_RISCV_F13:
4223f6c50668Spatrick return "fa3";
4224f6c50668Spatrick case UNW_RISCV_F14:
4225f6c50668Spatrick return "fa4";
4226f6c50668Spatrick case UNW_RISCV_F15:
4227f6c50668Spatrick return "fa5";
4228f6c50668Spatrick case UNW_RISCV_F16:
4229f6c50668Spatrick return "fa6";
4230f6c50668Spatrick case UNW_RISCV_F17:
4231f6c50668Spatrick return "fa7";
4232f6c50668Spatrick case UNW_RISCV_F18:
4233f6c50668Spatrick return "fs2";
4234f6c50668Spatrick case UNW_RISCV_F19:
4235f6c50668Spatrick return "fs3";
4236f6c50668Spatrick case UNW_RISCV_F20:
4237f6c50668Spatrick return "fs4";
4238f6c50668Spatrick case UNW_RISCV_F21:
4239f6c50668Spatrick return "fs5";
4240f6c50668Spatrick case UNW_RISCV_F22:
4241f6c50668Spatrick return "fs6";
4242f6c50668Spatrick case UNW_RISCV_F23:
4243f6c50668Spatrick return "fs7";
4244f6c50668Spatrick case UNW_RISCV_F24:
4245f6c50668Spatrick return "fs8";
4246f6c50668Spatrick case UNW_RISCV_F25:
4247f6c50668Spatrick return "fs9";
4248f6c50668Spatrick case UNW_RISCV_F26:
4249f6c50668Spatrick return "fs10";
4250f6c50668Spatrick case UNW_RISCV_F27:
4251f6c50668Spatrick return "fs11";
4252f6c50668Spatrick case UNW_RISCV_F28:
4253f6c50668Spatrick return "ft8";
4254f6c50668Spatrick case UNW_RISCV_F29:
4255f6c50668Spatrick return "ft9";
4256f6c50668Spatrick case UNW_RISCV_F30:
4257f6c50668Spatrick return "ft10";
4258f6c50668Spatrick case UNW_RISCV_F31:
4259f6c50668Spatrick return "ft11";
4260*202cdb0eSrobert case UNW_RISCV_VLENB:
4261*202cdb0eSrobert return "vlenb";
4262f6c50668Spatrick default:
4263f6c50668Spatrick return "unknown register";
4264f6c50668Spatrick }
4265f6c50668Spatrick }
4266f6c50668Spatrick
validFloatRegister(int regNum) const4267f6c50668Spatrick inline bool Registers_riscv::validFloatRegister(int regNum) const {
4268a0747c9fSpatrick # if defined(__riscv_flen)
4269f6c50668Spatrick if (regNum < UNW_RISCV_F0)
4270f6c50668Spatrick return false;
4271f6c50668Spatrick if (regNum > UNW_RISCV_F31)
4272f6c50668Spatrick return false;
4273f6c50668Spatrick return true;
4274a0747c9fSpatrick # else
4275a0747c9fSpatrick (void)regNum;
4276a0747c9fSpatrick return false;
4277a0747c9fSpatrick # endif
4278f6c50668Spatrick }
4279f6c50668Spatrick
getFloatRegister(int regNum) const4280a0747c9fSpatrick inline fp_t Registers_riscv::getFloatRegister(int regNum) const {
4281a0747c9fSpatrick # if defined(__riscv_flen)
4282f6c50668Spatrick assert(validFloatRegister(regNum));
4283f6c50668Spatrick return _floats[regNum - UNW_RISCV_F0];
4284f6c50668Spatrick # else
4285f6c50668Spatrick (void)regNum;
4286f6c50668Spatrick _LIBUNWIND_ABORT("libunwind not built with float support");
4287f6c50668Spatrick # endif
4288f6c50668Spatrick }
4289f6c50668Spatrick
setFloatRegister(int regNum,fp_t value)4290a0747c9fSpatrick inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) {
4291a0747c9fSpatrick # if defined(__riscv_flen)
4292f6c50668Spatrick assert(validFloatRegister(regNum));
4293f6c50668Spatrick _floats[regNum - UNW_RISCV_F0] = value;
4294f6c50668Spatrick # else
4295f6c50668Spatrick (void)regNum;
4296f6c50668Spatrick (void)value;
4297f6c50668Spatrick _LIBUNWIND_ABORT("libunwind not built with float support");
4298f6c50668Spatrick # endif
4299f6c50668Spatrick }
4300f6c50668Spatrick
validVectorRegister(int) const4301f6c50668Spatrick inline bool Registers_riscv::validVectorRegister(int) const {
4302f6c50668Spatrick return false;
4303f6c50668Spatrick }
4304f6c50668Spatrick
getVectorRegister(int) const4305f6c50668Spatrick inline v128 Registers_riscv::getVectorRegister(int) const {
4306f6c50668Spatrick _LIBUNWIND_ABORT("no riscv vector register support yet");
4307f6c50668Spatrick }
4308f6c50668Spatrick
setVectorRegister(int,v128)4309f6c50668Spatrick inline void Registers_riscv::setVectorRegister(int, v128) {
4310f6c50668Spatrick _LIBUNWIND_ABORT("no riscv vector register support yet");
4311f6c50668Spatrick }
4312f6c50668Spatrick #endif // _LIBUNWIND_TARGET_RISCV
4313a0747c9fSpatrick
4314a0747c9fSpatrick #if defined(_LIBUNWIND_TARGET_VE)
4315a0747c9fSpatrick /// Registers_ve holds the register state of a thread in a VE process.
4316a0747c9fSpatrick class _LIBUNWIND_HIDDEN Registers_ve {
4317a0747c9fSpatrick public:
4318a0747c9fSpatrick Registers_ve();
4319a0747c9fSpatrick Registers_ve(const void *registers);
4320a0747c9fSpatrick
4321a0747c9fSpatrick bool validRegister(int num) const;
4322a0747c9fSpatrick uint64_t getRegister(int num) const;
4323a0747c9fSpatrick void setRegister(int num, uint64_t value);
4324a0747c9fSpatrick bool validFloatRegister(int num) const;
4325a0747c9fSpatrick double getFloatRegister(int num) const;
4326a0747c9fSpatrick void setFloatRegister(int num, double value);
4327a0747c9fSpatrick bool validVectorRegister(int num) const;
4328a0747c9fSpatrick v128 getVectorRegister(int num) const;
4329a0747c9fSpatrick void setVectorRegister(int num, v128 value);
4330a0747c9fSpatrick static const char *getRegisterName(int num);
4331a0747c9fSpatrick void jumpto();
lastDwarfRegNum()4332*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
4333*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE;
4334*202cdb0eSrobert }
getArch()4335a0747c9fSpatrick static int getArch() { return REGISTERS_VE; }
4336a0747c9fSpatrick
getSP() const4337a0747c9fSpatrick uint64_t getSP() const { return _registers.__s[11]; }
setSP(uint64_t value)4338a0747c9fSpatrick void setSP(uint64_t value) { _registers.__s[11] = value; }
getIP() const4339a0747c9fSpatrick uint64_t getIP() const { return _registers.__ic; }
setIP(uint64_t value)4340a0747c9fSpatrick void setIP(uint64_t value) { _registers.__ic = value; }
4341a0747c9fSpatrick
4342a0747c9fSpatrick private:
4343a0747c9fSpatrick // FIXME: Need to store not only scalar registers but also vector and vector
4344a0747c9fSpatrick // mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes
4345a0747c9fSpatrick // 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for
4346a0747c9fSpatrick // SjLj exception support only, so Registers_ve is not implemented completely.
4347a0747c9fSpatrick struct ve_thread_state_t {
4348a0747c9fSpatrick uint64_t __s[64]; // s0-s64
4349a0747c9fSpatrick uint64_t __ic; // Instruction counter (IC)
4350a0747c9fSpatrick uint64_t __vixr; // Vector Index Register
4351a0747c9fSpatrick uint64_t __vl; // Vector Length Register
4352a0747c9fSpatrick };
4353a0747c9fSpatrick
4354a0747c9fSpatrick ve_thread_state_t _registers; // total 67 registers
4355a0747c9fSpatrick
4356a0747c9fSpatrick // Currently no vector register is preserved.
4357a0747c9fSpatrick };
4358a0747c9fSpatrick
Registers_ve(const void * registers)4359a0747c9fSpatrick inline Registers_ve::Registers_ve(const void *registers) {
4360a0747c9fSpatrick static_assert((check_fit<Registers_ve, unw_context_t>::does_fit),
4361a0747c9fSpatrick "ve registers do not fit into unw_context_t");
4362a0747c9fSpatrick memcpy(&_registers, static_cast<const uint8_t *>(registers),
4363a0747c9fSpatrick sizeof(_registers));
4364a0747c9fSpatrick static_assert(sizeof(_registers) == 536,
4365a0747c9fSpatrick "expected vector register offset to be 536");
4366a0747c9fSpatrick }
4367a0747c9fSpatrick
Registers_ve()4368a0747c9fSpatrick inline Registers_ve::Registers_ve() {
4369a0747c9fSpatrick memset(&_registers, 0, sizeof(_registers));
4370a0747c9fSpatrick }
4371a0747c9fSpatrick
validRegister(int regNum) const4372a0747c9fSpatrick inline bool Registers_ve::validRegister(int regNum) const {
4373a0747c9fSpatrick if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
4374a0747c9fSpatrick return true;
4375a0747c9fSpatrick
4376a0747c9fSpatrick switch (regNum) {
4377a0747c9fSpatrick case UNW_REG_IP:
4378a0747c9fSpatrick case UNW_REG_SP:
4379a0747c9fSpatrick case UNW_VE_VIXR:
4380a0747c9fSpatrick case UNW_VE_VL:
4381a0747c9fSpatrick return true;
4382a0747c9fSpatrick default:
4383a0747c9fSpatrick return false;
4384a0747c9fSpatrick }
4385a0747c9fSpatrick }
4386a0747c9fSpatrick
getRegister(int regNum) const4387a0747c9fSpatrick inline uint64_t Registers_ve::getRegister(int regNum) const {
4388a0747c9fSpatrick if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)
4389a0747c9fSpatrick return _registers.__s[regNum - UNW_VE_S0];
4390a0747c9fSpatrick
4391a0747c9fSpatrick switch (regNum) {
4392a0747c9fSpatrick case UNW_REG_IP:
4393a0747c9fSpatrick return _registers.__ic;
4394a0747c9fSpatrick case UNW_REG_SP:
4395a0747c9fSpatrick return _registers.__s[11];
4396a0747c9fSpatrick case UNW_VE_VIXR:
4397a0747c9fSpatrick return _registers.__vixr;
4398a0747c9fSpatrick case UNW_VE_VL:
4399a0747c9fSpatrick return _registers.__vl;
4400a0747c9fSpatrick }
4401a0747c9fSpatrick _LIBUNWIND_ABORT("unsupported ve register");
4402a0747c9fSpatrick }
4403a0747c9fSpatrick
setRegister(int regNum,uint64_t value)4404a0747c9fSpatrick inline void Registers_ve::setRegister(int regNum, uint64_t value) {
4405a0747c9fSpatrick if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) {
4406a0747c9fSpatrick _registers.__s[regNum - UNW_VE_S0] = value;
4407a0747c9fSpatrick return;
4408a0747c9fSpatrick }
4409a0747c9fSpatrick
4410a0747c9fSpatrick switch (regNum) {
4411a0747c9fSpatrick case UNW_REG_IP:
4412a0747c9fSpatrick _registers.__ic = value;
4413a0747c9fSpatrick return;
4414a0747c9fSpatrick case UNW_REG_SP:
4415a0747c9fSpatrick _registers.__s[11] = value;
4416a0747c9fSpatrick return;
4417a0747c9fSpatrick case UNW_VE_VIXR:
4418a0747c9fSpatrick _registers.__vixr = value;
4419a0747c9fSpatrick return;
4420a0747c9fSpatrick case UNW_VE_VL:
4421a0747c9fSpatrick _registers.__vl = value;
4422a0747c9fSpatrick return;
4423a0747c9fSpatrick }
4424a0747c9fSpatrick _LIBUNWIND_ABORT("unsupported ve register");
4425a0747c9fSpatrick }
4426a0747c9fSpatrick
validFloatRegister(int) const4427a0747c9fSpatrick inline bool Registers_ve::validFloatRegister(int /* regNum */) const {
4428a0747c9fSpatrick return false;
4429a0747c9fSpatrick }
4430a0747c9fSpatrick
getFloatRegister(int) const4431a0747c9fSpatrick inline double Registers_ve::getFloatRegister(int /* regNum */) const {
4432a0747c9fSpatrick _LIBUNWIND_ABORT("VE doesn't have float registers");
4433a0747c9fSpatrick }
4434a0747c9fSpatrick
setFloatRegister(int,double)4435a0747c9fSpatrick inline void Registers_ve::setFloatRegister(int /* regNum */,
4436a0747c9fSpatrick double /* value */) {
4437a0747c9fSpatrick _LIBUNWIND_ABORT("VE doesn't have float registers");
4438a0747c9fSpatrick }
4439a0747c9fSpatrick
validVectorRegister(int) const4440a0747c9fSpatrick inline bool Registers_ve::validVectorRegister(int /* regNum */) const {
4441a0747c9fSpatrick return false;
4442a0747c9fSpatrick }
4443a0747c9fSpatrick
getVectorRegister(int) const4444a0747c9fSpatrick inline v128 Registers_ve::getVectorRegister(int /* regNum */) const {
4445a0747c9fSpatrick _LIBUNWIND_ABORT("VE vector support not implemented");
4446a0747c9fSpatrick }
4447a0747c9fSpatrick
setVectorRegister(int,v128)4448a0747c9fSpatrick inline void Registers_ve::setVectorRegister(int /* regNum */,
4449a0747c9fSpatrick v128 /* value */) {
4450a0747c9fSpatrick _LIBUNWIND_ABORT("VE vector support not implemented");
4451a0747c9fSpatrick }
4452a0747c9fSpatrick
getRegisterName(int regNum)4453a0747c9fSpatrick inline const char *Registers_ve::getRegisterName(int regNum) {
4454a0747c9fSpatrick switch (regNum) {
4455a0747c9fSpatrick case UNW_REG_IP:
4456a0747c9fSpatrick return "ip";
4457a0747c9fSpatrick case UNW_REG_SP:
4458a0747c9fSpatrick return "sp";
4459a0747c9fSpatrick case UNW_VE_VIXR:
4460a0747c9fSpatrick return "vixr";
4461a0747c9fSpatrick case UNW_VE_VL:
4462a0747c9fSpatrick return "vl";
4463a0747c9fSpatrick case UNW_VE_S0:
4464a0747c9fSpatrick return "s0";
4465a0747c9fSpatrick case UNW_VE_S1:
4466a0747c9fSpatrick return "s1";
4467a0747c9fSpatrick case UNW_VE_S2:
4468a0747c9fSpatrick return "s2";
4469a0747c9fSpatrick case UNW_VE_S3:
4470a0747c9fSpatrick return "s3";
4471a0747c9fSpatrick case UNW_VE_S4:
4472a0747c9fSpatrick return "s4";
4473a0747c9fSpatrick case UNW_VE_S5:
4474a0747c9fSpatrick return "s5";
4475a0747c9fSpatrick case UNW_VE_S6:
4476a0747c9fSpatrick return "s6";
4477a0747c9fSpatrick case UNW_VE_S7:
4478a0747c9fSpatrick return "s7";
4479a0747c9fSpatrick case UNW_VE_S8:
4480a0747c9fSpatrick return "s8";
4481a0747c9fSpatrick case UNW_VE_S9:
4482a0747c9fSpatrick return "s9";
4483a0747c9fSpatrick case UNW_VE_S10:
4484a0747c9fSpatrick return "s10";
4485a0747c9fSpatrick case UNW_VE_S11:
4486a0747c9fSpatrick return "s11";
4487a0747c9fSpatrick case UNW_VE_S12:
4488a0747c9fSpatrick return "s12";
4489a0747c9fSpatrick case UNW_VE_S13:
4490a0747c9fSpatrick return "s13";
4491a0747c9fSpatrick case UNW_VE_S14:
4492a0747c9fSpatrick return "s14";
4493a0747c9fSpatrick case UNW_VE_S15:
4494a0747c9fSpatrick return "s15";
4495a0747c9fSpatrick case UNW_VE_S16:
4496a0747c9fSpatrick return "s16";
4497a0747c9fSpatrick case UNW_VE_S17:
4498a0747c9fSpatrick return "s17";
4499a0747c9fSpatrick case UNW_VE_S18:
4500a0747c9fSpatrick return "s18";
4501a0747c9fSpatrick case UNW_VE_S19:
4502a0747c9fSpatrick return "s19";
4503a0747c9fSpatrick case UNW_VE_S20:
4504a0747c9fSpatrick return "s20";
4505a0747c9fSpatrick case UNW_VE_S21:
4506a0747c9fSpatrick return "s21";
4507a0747c9fSpatrick case UNW_VE_S22:
4508a0747c9fSpatrick return "s22";
4509a0747c9fSpatrick case UNW_VE_S23:
4510a0747c9fSpatrick return "s23";
4511a0747c9fSpatrick case UNW_VE_S24:
4512a0747c9fSpatrick return "s24";
4513a0747c9fSpatrick case UNW_VE_S25:
4514a0747c9fSpatrick return "s25";
4515a0747c9fSpatrick case UNW_VE_S26:
4516a0747c9fSpatrick return "s26";
4517a0747c9fSpatrick case UNW_VE_S27:
4518a0747c9fSpatrick return "s27";
4519a0747c9fSpatrick case UNW_VE_S28:
4520a0747c9fSpatrick return "s28";
4521a0747c9fSpatrick case UNW_VE_S29:
4522a0747c9fSpatrick return "s29";
4523a0747c9fSpatrick case UNW_VE_S30:
4524a0747c9fSpatrick return "s30";
4525a0747c9fSpatrick case UNW_VE_S31:
4526a0747c9fSpatrick return "s31";
4527a0747c9fSpatrick case UNW_VE_S32:
4528a0747c9fSpatrick return "s32";
4529a0747c9fSpatrick case UNW_VE_S33:
4530a0747c9fSpatrick return "s33";
4531a0747c9fSpatrick case UNW_VE_S34:
4532a0747c9fSpatrick return "s34";
4533a0747c9fSpatrick case UNW_VE_S35:
4534a0747c9fSpatrick return "s35";
4535a0747c9fSpatrick case UNW_VE_S36:
4536a0747c9fSpatrick return "s36";
4537a0747c9fSpatrick case UNW_VE_S37:
4538a0747c9fSpatrick return "s37";
4539a0747c9fSpatrick case UNW_VE_S38:
4540a0747c9fSpatrick return "s38";
4541a0747c9fSpatrick case UNW_VE_S39:
4542a0747c9fSpatrick return "s39";
4543a0747c9fSpatrick case UNW_VE_S40:
4544a0747c9fSpatrick return "s40";
4545a0747c9fSpatrick case UNW_VE_S41:
4546a0747c9fSpatrick return "s41";
4547a0747c9fSpatrick case UNW_VE_S42:
4548a0747c9fSpatrick return "s42";
4549a0747c9fSpatrick case UNW_VE_S43:
4550a0747c9fSpatrick return "s43";
4551a0747c9fSpatrick case UNW_VE_S44:
4552a0747c9fSpatrick return "s44";
4553a0747c9fSpatrick case UNW_VE_S45:
4554a0747c9fSpatrick return "s45";
4555a0747c9fSpatrick case UNW_VE_S46:
4556a0747c9fSpatrick return "s46";
4557a0747c9fSpatrick case UNW_VE_S47:
4558a0747c9fSpatrick return "s47";
4559a0747c9fSpatrick case UNW_VE_S48:
4560a0747c9fSpatrick return "s48";
4561a0747c9fSpatrick case UNW_VE_S49:
4562a0747c9fSpatrick return "s49";
4563a0747c9fSpatrick case UNW_VE_S50:
4564a0747c9fSpatrick return "s50";
4565a0747c9fSpatrick case UNW_VE_S51:
4566a0747c9fSpatrick return "s51";
4567a0747c9fSpatrick case UNW_VE_S52:
4568a0747c9fSpatrick return "s52";
4569a0747c9fSpatrick case UNW_VE_S53:
4570a0747c9fSpatrick return "s53";
4571a0747c9fSpatrick case UNW_VE_S54:
4572a0747c9fSpatrick return "s54";
4573a0747c9fSpatrick case UNW_VE_S55:
4574a0747c9fSpatrick return "s55";
4575a0747c9fSpatrick case UNW_VE_S56:
4576a0747c9fSpatrick return "s56";
4577a0747c9fSpatrick case UNW_VE_S57:
4578a0747c9fSpatrick return "s57";
4579a0747c9fSpatrick case UNW_VE_S58:
4580a0747c9fSpatrick return "s58";
4581a0747c9fSpatrick case UNW_VE_S59:
4582a0747c9fSpatrick return "s59";
4583a0747c9fSpatrick case UNW_VE_S60:
4584a0747c9fSpatrick return "s60";
4585a0747c9fSpatrick case UNW_VE_S61:
4586a0747c9fSpatrick return "s61";
4587a0747c9fSpatrick case UNW_VE_S62:
4588a0747c9fSpatrick return "s62";
4589a0747c9fSpatrick case UNW_VE_S63:
4590a0747c9fSpatrick return "s63";
4591a0747c9fSpatrick case UNW_VE_V0:
4592a0747c9fSpatrick return "v0";
4593a0747c9fSpatrick case UNW_VE_V1:
4594a0747c9fSpatrick return "v1";
4595a0747c9fSpatrick case UNW_VE_V2:
4596a0747c9fSpatrick return "v2";
4597a0747c9fSpatrick case UNW_VE_V3:
4598a0747c9fSpatrick return "v3";
4599a0747c9fSpatrick case UNW_VE_V4:
4600a0747c9fSpatrick return "v4";
4601a0747c9fSpatrick case UNW_VE_V5:
4602a0747c9fSpatrick return "v5";
4603a0747c9fSpatrick case UNW_VE_V6:
4604a0747c9fSpatrick return "v6";
4605a0747c9fSpatrick case UNW_VE_V7:
4606a0747c9fSpatrick return "v7";
4607a0747c9fSpatrick case UNW_VE_V8:
4608a0747c9fSpatrick return "v8";
4609a0747c9fSpatrick case UNW_VE_V9:
4610a0747c9fSpatrick return "v9";
4611a0747c9fSpatrick case UNW_VE_V10:
4612a0747c9fSpatrick return "v10";
4613a0747c9fSpatrick case UNW_VE_V11:
4614a0747c9fSpatrick return "v11";
4615a0747c9fSpatrick case UNW_VE_V12:
4616a0747c9fSpatrick return "v12";
4617a0747c9fSpatrick case UNW_VE_V13:
4618a0747c9fSpatrick return "v13";
4619a0747c9fSpatrick case UNW_VE_V14:
4620a0747c9fSpatrick return "v14";
4621a0747c9fSpatrick case UNW_VE_V15:
4622a0747c9fSpatrick return "v15";
4623a0747c9fSpatrick case UNW_VE_V16:
4624a0747c9fSpatrick return "v16";
4625a0747c9fSpatrick case UNW_VE_V17:
4626a0747c9fSpatrick return "v17";
4627a0747c9fSpatrick case UNW_VE_V18:
4628a0747c9fSpatrick return "v18";
4629a0747c9fSpatrick case UNW_VE_V19:
4630a0747c9fSpatrick return "v19";
4631a0747c9fSpatrick case UNW_VE_V20:
4632a0747c9fSpatrick return "v20";
4633a0747c9fSpatrick case UNW_VE_V21:
4634a0747c9fSpatrick return "v21";
4635a0747c9fSpatrick case UNW_VE_V22:
4636a0747c9fSpatrick return "v22";
4637a0747c9fSpatrick case UNW_VE_V23:
4638a0747c9fSpatrick return "v23";
4639a0747c9fSpatrick case UNW_VE_V24:
4640a0747c9fSpatrick return "v24";
4641a0747c9fSpatrick case UNW_VE_V25:
4642a0747c9fSpatrick return "v25";
4643a0747c9fSpatrick case UNW_VE_V26:
4644a0747c9fSpatrick return "v26";
4645a0747c9fSpatrick case UNW_VE_V27:
4646a0747c9fSpatrick return "v27";
4647a0747c9fSpatrick case UNW_VE_V28:
4648a0747c9fSpatrick return "v28";
4649a0747c9fSpatrick case UNW_VE_V29:
4650a0747c9fSpatrick return "v29";
4651a0747c9fSpatrick case UNW_VE_V30:
4652a0747c9fSpatrick return "v30";
4653a0747c9fSpatrick case UNW_VE_V31:
4654a0747c9fSpatrick return "v31";
4655a0747c9fSpatrick case UNW_VE_V32:
4656a0747c9fSpatrick return "v32";
4657a0747c9fSpatrick case UNW_VE_V33:
4658a0747c9fSpatrick return "v33";
4659a0747c9fSpatrick case UNW_VE_V34:
4660a0747c9fSpatrick return "v34";
4661a0747c9fSpatrick case UNW_VE_V35:
4662a0747c9fSpatrick return "v35";
4663a0747c9fSpatrick case UNW_VE_V36:
4664a0747c9fSpatrick return "v36";
4665a0747c9fSpatrick case UNW_VE_V37:
4666a0747c9fSpatrick return "v37";
4667a0747c9fSpatrick case UNW_VE_V38:
4668a0747c9fSpatrick return "v38";
4669a0747c9fSpatrick case UNW_VE_V39:
4670a0747c9fSpatrick return "v39";
4671a0747c9fSpatrick case UNW_VE_V40:
4672a0747c9fSpatrick return "v40";
4673a0747c9fSpatrick case UNW_VE_V41:
4674a0747c9fSpatrick return "v41";
4675a0747c9fSpatrick case UNW_VE_V42:
4676a0747c9fSpatrick return "v42";
4677a0747c9fSpatrick case UNW_VE_V43:
4678a0747c9fSpatrick return "v43";
4679a0747c9fSpatrick case UNW_VE_V44:
4680a0747c9fSpatrick return "v44";
4681a0747c9fSpatrick case UNW_VE_V45:
4682a0747c9fSpatrick return "v45";
4683a0747c9fSpatrick case UNW_VE_V46:
4684a0747c9fSpatrick return "v46";
4685a0747c9fSpatrick case UNW_VE_V47:
4686a0747c9fSpatrick return "v47";
4687a0747c9fSpatrick case UNW_VE_V48:
4688a0747c9fSpatrick return "v48";
4689a0747c9fSpatrick case UNW_VE_V49:
4690a0747c9fSpatrick return "v49";
4691a0747c9fSpatrick case UNW_VE_V50:
4692a0747c9fSpatrick return "v50";
4693a0747c9fSpatrick case UNW_VE_V51:
4694a0747c9fSpatrick return "v51";
4695a0747c9fSpatrick case UNW_VE_V52:
4696a0747c9fSpatrick return "v52";
4697a0747c9fSpatrick case UNW_VE_V53:
4698a0747c9fSpatrick return "v53";
4699a0747c9fSpatrick case UNW_VE_V54:
4700a0747c9fSpatrick return "v54";
4701a0747c9fSpatrick case UNW_VE_V55:
4702a0747c9fSpatrick return "v55";
4703a0747c9fSpatrick case UNW_VE_V56:
4704a0747c9fSpatrick return "v56";
4705a0747c9fSpatrick case UNW_VE_V57:
4706a0747c9fSpatrick return "v57";
4707a0747c9fSpatrick case UNW_VE_V58:
4708a0747c9fSpatrick return "v58";
4709a0747c9fSpatrick case UNW_VE_V59:
4710a0747c9fSpatrick return "v59";
4711a0747c9fSpatrick case UNW_VE_V60:
4712a0747c9fSpatrick return "v60";
4713a0747c9fSpatrick case UNW_VE_V61:
4714a0747c9fSpatrick return "v61";
4715a0747c9fSpatrick case UNW_VE_V62:
4716a0747c9fSpatrick return "v62";
4717a0747c9fSpatrick case UNW_VE_V63:
4718a0747c9fSpatrick return "v63";
4719a0747c9fSpatrick case UNW_VE_VM0:
4720a0747c9fSpatrick return "vm0";
4721a0747c9fSpatrick case UNW_VE_VM1:
4722a0747c9fSpatrick return "vm1";
4723a0747c9fSpatrick case UNW_VE_VM2:
4724a0747c9fSpatrick return "vm2";
4725a0747c9fSpatrick case UNW_VE_VM3:
4726a0747c9fSpatrick return "vm3";
4727a0747c9fSpatrick case UNW_VE_VM4:
4728a0747c9fSpatrick return "vm4";
4729a0747c9fSpatrick case UNW_VE_VM5:
4730a0747c9fSpatrick return "vm5";
4731a0747c9fSpatrick case UNW_VE_VM6:
4732a0747c9fSpatrick return "vm6";
4733a0747c9fSpatrick case UNW_VE_VM7:
4734a0747c9fSpatrick return "vm7";
4735a0747c9fSpatrick case UNW_VE_VM8:
4736a0747c9fSpatrick return "vm8";
4737a0747c9fSpatrick case UNW_VE_VM9:
4738a0747c9fSpatrick return "vm9";
4739a0747c9fSpatrick case UNW_VE_VM10:
4740a0747c9fSpatrick return "vm10";
4741a0747c9fSpatrick case UNW_VE_VM11:
4742a0747c9fSpatrick return "vm11";
4743a0747c9fSpatrick case UNW_VE_VM12:
4744a0747c9fSpatrick return "vm12";
4745a0747c9fSpatrick case UNW_VE_VM13:
4746a0747c9fSpatrick return "vm13";
4747a0747c9fSpatrick case UNW_VE_VM14:
4748a0747c9fSpatrick return "vm14";
4749a0747c9fSpatrick case UNW_VE_VM15:
4750a0747c9fSpatrick return "vm15";
4751a0747c9fSpatrick }
4752a0747c9fSpatrick return "unknown register";
4753a0747c9fSpatrick }
4754a0747c9fSpatrick #endif // _LIBUNWIND_TARGET_VE
4755a0747c9fSpatrick
4756*202cdb0eSrobert #if defined(_LIBUNWIND_TARGET_S390X)
4757*202cdb0eSrobert /// Registers_s390x holds the register state of a thread in a
4758*202cdb0eSrobert /// 64-bit Linux on IBM zSystems process.
4759*202cdb0eSrobert class _LIBUNWIND_HIDDEN Registers_s390x {
4760*202cdb0eSrobert public:
4761*202cdb0eSrobert Registers_s390x();
4762*202cdb0eSrobert Registers_s390x(const void *registers);
4763*202cdb0eSrobert
4764*202cdb0eSrobert bool validRegister(int num) const;
4765*202cdb0eSrobert uint64_t getRegister(int num) const;
4766*202cdb0eSrobert void setRegister(int num, uint64_t value);
4767*202cdb0eSrobert bool validFloatRegister(int num) const;
4768*202cdb0eSrobert double getFloatRegister(int num) const;
4769*202cdb0eSrobert void setFloatRegister(int num, double value);
4770*202cdb0eSrobert bool validVectorRegister(int num) const;
4771*202cdb0eSrobert v128 getVectorRegister(int num) const;
4772*202cdb0eSrobert void setVectorRegister(int num, v128 value);
4773*202cdb0eSrobert static const char *getRegisterName(int num);
4774*202cdb0eSrobert void jumpto();
lastDwarfRegNum()4775*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
4776*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X;
4777*202cdb0eSrobert }
getArch()4778*202cdb0eSrobert static int getArch() { return REGISTERS_S390X; }
4779*202cdb0eSrobert
getSP() const4780*202cdb0eSrobert uint64_t getSP() const { return _registers.__gpr[15]; }
setSP(uint64_t value)4781*202cdb0eSrobert void setSP(uint64_t value) { _registers.__gpr[15] = value; }
getIP() const4782*202cdb0eSrobert uint64_t getIP() const { return _registers.__pswa; }
setIP(uint64_t value)4783*202cdb0eSrobert void setIP(uint64_t value) { _registers.__pswa = value; }
4784*202cdb0eSrobert
4785*202cdb0eSrobert private:
4786*202cdb0eSrobert struct s390x_thread_state_t {
4787*202cdb0eSrobert uint64_t __pswm; // Problem Status Word: Mask
4788*202cdb0eSrobert uint64_t __pswa; // Problem Status Word: Address (PC)
4789*202cdb0eSrobert uint64_t __gpr[16]; // General Purpose Registers
4790*202cdb0eSrobert double __fpr[16]; // Floating-Point Registers
4791*202cdb0eSrobert };
4792*202cdb0eSrobert
4793*202cdb0eSrobert s390x_thread_state_t _registers;
4794*202cdb0eSrobert };
4795*202cdb0eSrobert
Registers_s390x(const void * registers)4796*202cdb0eSrobert inline Registers_s390x::Registers_s390x(const void *registers) {
4797*202cdb0eSrobert static_assert((check_fit<Registers_s390x, unw_context_t>::does_fit),
4798*202cdb0eSrobert "s390x registers do not fit into unw_context_t");
4799*202cdb0eSrobert memcpy(&_registers, static_cast<const uint8_t *>(registers),
4800*202cdb0eSrobert sizeof(_registers));
4801*202cdb0eSrobert }
4802*202cdb0eSrobert
Registers_s390x()4803*202cdb0eSrobert inline Registers_s390x::Registers_s390x() {
4804*202cdb0eSrobert memset(&_registers, 0, sizeof(_registers));
4805*202cdb0eSrobert }
4806*202cdb0eSrobert
validRegister(int regNum) const4807*202cdb0eSrobert inline bool Registers_s390x::validRegister(int regNum) const {
4808*202cdb0eSrobert switch (regNum) {
4809*202cdb0eSrobert case UNW_S390X_PSWM:
4810*202cdb0eSrobert case UNW_S390X_PSWA:
4811*202cdb0eSrobert case UNW_REG_IP:
4812*202cdb0eSrobert case UNW_REG_SP:
4813*202cdb0eSrobert return true;
4814*202cdb0eSrobert }
4815*202cdb0eSrobert
4816*202cdb0eSrobert if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
4817*202cdb0eSrobert return true;
4818*202cdb0eSrobert
4819*202cdb0eSrobert return false;
4820*202cdb0eSrobert }
4821*202cdb0eSrobert
getRegister(int regNum) const4822*202cdb0eSrobert inline uint64_t Registers_s390x::getRegister(int regNum) const {
4823*202cdb0eSrobert if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
4824*202cdb0eSrobert return _registers.__gpr[regNum - UNW_S390X_R0];
4825*202cdb0eSrobert
4826*202cdb0eSrobert switch (regNum) {
4827*202cdb0eSrobert case UNW_S390X_PSWM:
4828*202cdb0eSrobert return _registers.__pswm;
4829*202cdb0eSrobert case UNW_S390X_PSWA:
4830*202cdb0eSrobert case UNW_REG_IP:
4831*202cdb0eSrobert return _registers.__pswa;
4832*202cdb0eSrobert case UNW_REG_SP:
4833*202cdb0eSrobert return _registers.__gpr[15];
4834*202cdb0eSrobert }
4835*202cdb0eSrobert _LIBUNWIND_ABORT("unsupported s390x register");
4836*202cdb0eSrobert }
4837*202cdb0eSrobert
setRegister(int regNum,uint64_t value)4838*202cdb0eSrobert inline void Registers_s390x::setRegister(int regNum, uint64_t value) {
4839*202cdb0eSrobert if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) {
4840*202cdb0eSrobert _registers.__gpr[regNum - UNW_S390X_R0] = value;
4841*202cdb0eSrobert return;
4842*202cdb0eSrobert }
4843*202cdb0eSrobert
4844*202cdb0eSrobert switch (regNum) {
4845*202cdb0eSrobert case UNW_S390X_PSWM:
4846*202cdb0eSrobert _registers.__pswm = value;
4847*202cdb0eSrobert return;
4848*202cdb0eSrobert case UNW_S390X_PSWA:
4849*202cdb0eSrobert case UNW_REG_IP:
4850*202cdb0eSrobert _registers.__pswa = value;
4851*202cdb0eSrobert return;
4852*202cdb0eSrobert case UNW_REG_SP:
4853*202cdb0eSrobert _registers.__gpr[15] = value;
4854*202cdb0eSrobert return;
4855*202cdb0eSrobert }
4856*202cdb0eSrobert _LIBUNWIND_ABORT("unsupported s390x register");
4857*202cdb0eSrobert }
4858*202cdb0eSrobert
validFloatRegister(int regNum) const4859*202cdb0eSrobert inline bool Registers_s390x::validFloatRegister(int regNum) const {
4860*202cdb0eSrobert return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15;
4861*202cdb0eSrobert }
4862*202cdb0eSrobert
getFloatRegister(int regNum) const4863*202cdb0eSrobert inline double Registers_s390x::getFloatRegister(int regNum) const {
4864*202cdb0eSrobert // NOTE: FPR DWARF register numbers are not consecutive.
4865*202cdb0eSrobert switch (regNum) {
4866*202cdb0eSrobert case UNW_S390X_F0:
4867*202cdb0eSrobert return _registers.__fpr[0];
4868*202cdb0eSrobert case UNW_S390X_F1:
4869*202cdb0eSrobert return _registers.__fpr[1];
4870*202cdb0eSrobert case UNW_S390X_F2:
4871*202cdb0eSrobert return _registers.__fpr[2];
4872*202cdb0eSrobert case UNW_S390X_F3:
4873*202cdb0eSrobert return _registers.__fpr[3];
4874*202cdb0eSrobert case UNW_S390X_F4:
4875*202cdb0eSrobert return _registers.__fpr[4];
4876*202cdb0eSrobert case UNW_S390X_F5:
4877*202cdb0eSrobert return _registers.__fpr[5];
4878*202cdb0eSrobert case UNW_S390X_F6:
4879*202cdb0eSrobert return _registers.__fpr[6];
4880*202cdb0eSrobert case UNW_S390X_F7:
4881*202cdb0eSrobert return _registers.__fpr[7];
4882*202cdb0eSrobert case UNW_S390X_F8:
4883*202cdb0eSrobert return _registers.__fpr[8];
4884*202cdb0eSrobert case UNW_S390X_F9:
4885*202cdb0eSrobert return _registers.__fpr[9];
4886*202cdb0eSrobert case UNW_S390X_F10:
4887*202cdb0eSrobert return _registers.__fpr[10];
4888*202cdb0eSrobert case UNW_S390X_F11:
4889*202cdb0eSrobert return _registers.__fpr[11];
4890*202cdb0eSrobert case UNW_S390X_F12:
4891*202cdb0eSrobert return _registers.__fpr[12];
4892*202cdb0eSrobert case UNW_S390X_F13:
4893*202cdb0eSrobert return _registers.__fpr[13];
4894*202cdb0eSrobert case UNW_S390X_F14:
4895*202cdb0eSrobert return _registers.__fpr[14];
4896*202cdb0eSrobert case UNW_S390X_F15:
4897*202cdb0eSrobert return _registers.__fpr[15];
4898*202cdb0eSrobert }
4899*202cdb0eSrobert _LIBUNWIND_ABORT("unsupported s390x register");
4900*202cdb0eSrobert }
4901*202cdb0eSrobert
setFloatRegister(int regNum,double value)4902*202cdb0eSrobert inline void Registers_s390x::setFloatRegister(int regNum, double value) {
4903*202cdb0eSrobert // NOTE: FPR DWARF register numbers are not consecutive.
4904*202cdb0eSrobert switch (regNum) {
4905*202cdb0eSrobert case UNW_S390X_F0:
4906*202cdb0eSrobert _registers.__fpr[0] = value;
4907*202cdb0eSrobert return;
4908*202cdb0eSrobert case UNW_S390X_F1:
4909*202cdb0eSrobert _registers.__fpr[1] = value;
4910*202cdb0eSrobert return;
4911*202cdb0eSrobert case UNW_S390X_F2:
4912*202cdb0eSrobert _registers.__fpr[2] = value;
4913*202cdb0eSrobert return;
4914*202cdb0eSrobert case UNW_S390X_F3:
4915*202cdb0eSrobert _registers.__fpr[3] = value;
4916*202cdb0eSrobert return;
4917*202cdb0eSrobert case UNW_S390X_F4:
4918*202cdb0eSrobert _registers.__fpr[4] = value;
4919*202cdb0eSrobert return;
4920*202cdb0eSrobert case UNW_S390X_F5:
4921*202cdb0eSrobert _registers.__fpr[5] = value;
4922*202cdb0eSrobert return;
4923*202cdb0eSrobert case UNW_S390X_F6:
4924*202cdb0eSrobert _registers.__fpr[6] = value;
4925*202cdb0eSrobert return;
4926*202cdb0eSrobert case UNW_S390X_F7:
4927*202cdb0eSrobert _registers.__fpr[7] = value;
4928*202cdb0eSrobert return;
4929*202cdb0eSrobert case UNW_S390X_F8:
4930*202cdb0eSrobert _registers.__fpr[8] = value;
4931*202cdb0eSrobert return;
4932*202cdb0eSrobert case UNW_S390X_F9:
4933*202cdb0eSrobert _registers.__fpr[9] = value;
4934*202cdb0eSrobert return;
4935*202cdb0eSrobert case UNW_S390X_F10:
4936*202cdb0eSrobert _registers.__fpr[10] = value;
4937*202cdb0eSrobert return;
4938*202cdb0eSrobert case UNW_S390X_F11:
4939*202cdb0eSrobert _registers.__fpr[11] = value;
4940*202cdb0eSrobert return;
4941*202cdb0eSrobert case UNW_S390X_F12:
4942*202cdb0eSrobert _registers.__fpr[12] = value;
4943*202cdb0eSrobert return;
4944*202cdb0eSrobert case UNW_S390X_F13:
4945*202cdb0eSrobert _registers.__fpr[13] = value;
4946*202cdb0eSrobert return;
4947*202cdb0eSrobert case UNW_S390X_F14:
4948*202cdb0eSrobert _registers.__fpr[14] = value;
4949*202cdb0eSrobert return;
4950*202cdb0eSrobert case UNW_S390X_F15:
4951*202cdb0eSrobert _registers.__fpr[15] = value;
4952*202cdb0eSrobert return;
4953*202cdb0eSrobert }
4954*202cdb0eSrobert _LIBUNWIND_ABORT("unsupported s390x register");
4955*202cdb0eSrobert }
4956*202cdb0eSrobert
validVectorRegister(int) const4957*202cdb0eSrobert inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
4958*202cdb0eSrobert return false;
4959*202cdb0eSrobert }
4960*202cdb0eSrobert
getVectorRegister(int) const4961*202cdb0eSrobert inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const {
4962*202cdb0eSrobert _LIBUNWIND_ABORT("s390x vector support not implemented");
4963*202cdb0eSrobert }
4964*202cdb0eSrobert
setVectorRegister(int,v128)4965*202cdb0eSrobert inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) {
4966*202cdb0eSrobert _LIBUNWIND_ABORT("s390x vector support not implemented");
4967*202cdb0eSrobert }
4968*202cdb0eSrobert
getRegisterName(int regNum)4969*202cdb0eSrobert inline const char *Registers_s390x::getRegisterName(int regNum) {
4970*202cdb0eSrobert switch (regNum) {
4971*202cdb0eSrobert case UNW_REG_IP:
4972*202cdb0eSrobert return "ip";
4973*202cdb0eSrobert case UNW_REG_SP:
4974*202cdb0eSrobert return "sp";
4975*202cdb0eSrobert case UNW_S390X_R0:
4976*202cdb0eSrobert return "r0";
4977*202cdb0eSrobert case UNW_S390X_R1:
4978*202cdb0eSrobert return "r1";
4979*202cdb0eSrobert case UNW_S390X_R2:
4980*202cdb0eSrobert return "r2";
4981*202cdb0eSrobert case UNW_S390X_R3:
4982*202cdb0eSrobert return "r3";
4983*202cdb0eSrobert case UNW_S390X_R4:
4984*202cdb0eSrobert return "r4";
4985*202cdb0eSrobert case UNW_S390X_R5:
4986*202cdb0eSrobert return "r5";
4987*202cdb0eSrobert case UNW_S390X_R6:
4988*202cdb0eSrobert return "r6";
4989*202cdb0eSrobert case UNW_S390X_R7:
4990*202cdb0eSrobert return "r7";
4991*202cdb0eSrobert case UNW_S390X_R8:
4992*202cdb0eSrobert return "r8";
4993*202cdb0eSrobert case UNW_S390X_R9:
4994*202cdb0eSrobert return "r9";
4995*202cdb0eSrobert case UNW_S390X_R10:
4996*202cdb0eSrobert return "r10";
4997*202cdb0eSrobert case UNW_S390X_R11:
4998*202cdb0eSrobert return "r11";
4999*202cdb0eSrobert case UNW_S390X_R12:
5000*202cdb0eSrobert return "r12";
5001*202cdb0eSrobert case UNW_S390X_R13:
5002*202cdb0eSrobert return "r13";
5003*202cdb0eSrobert case UNW_S390X_R14:
5004*202cdb0eSrobert return "r14";
5005*202cdb0eSrobert case UNW_S390X_R15:
5006*202cdb0eSrobert return "r15";
5007*202cdb0eSrobert case UNW_S390X_F0:
5008*202cdb0eSrobert return "f0";
5009*202cdb0eSrobert case UNW_S390X_F1:
5010*202cdb0eSrobert return "f1";
5011*202cdb0eSrobert case UNW_S390X_F2:
5012*202cdb0eSrobert return "f2";
5013*202cdb0eSrobert case UNW_S390X_F3:
5014*202cdb0eSrobert return "f3";
5015*202cdb0eSrobert case UNW_S390X_F4:
5016*202cdb0eSrobert return "f4";
5017*202cdb0eSrobert case UNW_S390X_F5:
5018*202cdb0eSrobert return "f5";
5019*202cdb0eSrobert case UNW_S390X_F6:
5020*202cdb0eSrobert return "f6";
5021*202cdb0eSrobert case UNW_S390X_F7:
5022*202cdb0eSrobert return "f7";
5023*202cdb0eSrobert case UNW_S390X_F8:
5024*202cdb0eSrobert return "f8";
5025*202cdb0eSrobert case UNW_S390X_F9:
5026*202cdb0eSrobert return "f9";
5027*202cdb0eSrobert case UNW_S390X_F10:
5028*202cdb0eSrobert return "f10";
5029*202cdb0eSrobert case UNW_S390X_F11:
5030*202cdb0eSrobert return "f11";
5031*202cdb0eSrobert case UNW_S390X_F12:
5032*202cdb0eSrobert return "f12";
5033*202cdb0eSrobert case UNW_S390X_F13:
5034*202cdb0eSrobert return "f13";
5035*202cdb0eSrobert case UNW_S390X_F14:
5036*202cdb0eSrobert return "f14";
5037*202cdb0eSrobert case UNW_S390X_F15:
5038*202cdb0eSrobert return "f15";
5039*202cdb0eSrobert }
5040*202cdb0eSrobert return "unknown register";
5041*202cdb0eSrobert }
5042*202cdb0eSrobert #endif // _LIBUNWIND_TARGET_S390X
5043*202cdb0eSrobert
5044*202cdb0eSrobert #if defined(_LIBUNWIND_TARGET_LOONGARCH)
5045*202cdb0eSrobert /// Registers_loongarch holds the register state of a thread in a 64-bit
5046*202cdb0eSrobert /// LoongArch process.
5047*202cdb0eSrobert class _LIBUNWIND_HIDDEN Registers_loongarch {
5048*202cdb0eSrobert public:
5049*202cdb0eSrobert Registers_loongarch();
5050*202cdb0eSrobert Registers_loongarch(const void *registers);
5051*202cdb0eSrobert
5052*202cdb0eSrobert bool validRegister(int num) const;
5053*202cdb0eSrobert uint64_t getRegister(int num) const;
5054*202cdb0eSrobert void setRegister(int num, uint64_t value);
5055*202cdb0eSrobert bool validFloatRegister(int num) const;
5056*202cdb0eSrobert double getFloatRegister(int num) const;
5057*202cdb0eSrobert void setFloatRegister(int num, double value);
5058*202cdb0eSrobert bool validVectorRegister(int num) const;
5059*202cdb0eSrobert v128 getVectorRegister(int num) const;
5060*202cdb0eSrobert void setVectorRegister(int num, v128 value);
5061*202cdb0eSrobert static const char *getRegisterName(int num);
5062*202cdb0eSrobert void jumpto();
lastDwarfRegNum()5063*202cdb0eSrobert static constexpr int lastDwarfRegNum() {
5064*202cdb0eSrobert return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH;
5065*202cdb0eSrobert }
getArch()5066*202cdb0eSrobert static int getArch() { return REGISTERS_LOONGARCH; }
5067*202cdb0eSrobert
getSP() const5068*202cdb0eSrobert uint64_t getSP() const { return _registers.__r[3]; }
setSP(uint64_t value)5069*202cdb0eSrobert void setSP(uint64_t value) { _registers.__r[3] = value; }
getIP() const5070*202cdb0eSrobert uint64_t getIP() const { return _registers.__pc; }
setIP(uint64_t value)5071*202cdb0eSrobert void setIP(uint64_t value) { _registers.__pc = value; }
5072*202cdb0eSrobert
5073*202cdb0eSrobert private:
5074*202cdb0eSrobert struct loongarch_thread_state_t {
5075*202cdb0eSrobert uint64_t __r[32];
5076*202cdb0eSrobert uint64_t __pc;
5077*202cdb0eSrobert };
5078*202cdb0eSrobert
5079*202cdb0eSrobert loongarch_thread_state_t _registers;
5080*202cdb0eSrobert #if __loongarch_frlen == 64
5081*202cdb0eSrobert double _floats[32];
5082*202cdb0eSrobert #endif
5083*202cdb0eSrobert };
5084*202cdb0eSrobert
Registers_loongarch(const void * registers)5085*202cdb0eSrobert inline Registers_loongarch::Registers_loongarch(const void *registers) {
5086*202cdb0eSrobert static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit),
5087*202cdb0eSrobert "loongarch registers do not fit into unw_context_t");
5088*202cdb0eSrobert memcpy(&_registers, registers, sizeof(_registers));
5089*202cdb0eSrobert static_assert(sizeof(_registers) == 0x108,
5090*202cdb0eSrobert "expected float registers to be at offset 264");
5091*202cdb0eSrobert #if __loongarch_frlen == 64
5092*202cdb0eSrobert memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers),
5093*202cdb0eSrobert sizeof(_floats));
5094*202cdb0eSrobert #endif
5095*202cdb0eSrobert }
5096*202cdb0eSrobert
Registers_loongarch()5097*202cdb0eSrobert inline Registers_loongarch::Registers_loongarch() {
5098*202cdb0eSrobert memset(&_registers, 0, sizeof(_registers));
5099*202cdb0eSrobert #if __loongarch_frlen == 64
5100*202cdb0eSrobert memset(&_floats, 0, sizeof(_floats));
5101*202cdb0eSrobert #endif
5102*202cdb0eSrobert }
5103*202cdb0eSrobert
validRegister(int regNum) const5104*202cdb0eSrobert inline bool Registers_loongarch::validRegister(int regNum) const {
5105*202cdb0eSrobert if (regNum == UNW_REG_IP || regNum == UNW_REG_SP)
5106*202cdb0eSrobert return true;
5107*202cdb0eSrobert if (regNum < 0 || regNum > UNW_LOONGARCH_F31)
5108*202cdb0eSrobert return false;
5109*202cdb0eSrobert return true;
5110*202cdb0eSrobert }
5111*202cdb0eSrobert
getRegister(int regNum) const5112*202cdb0eSrobert inline uint64_t Registers_loongarch::getRegister(int regNum) const {
5113*202cdb0eSrobert if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
5114*202cdb0eSrobert return _registers.__r[regNum - UNW_LOONGARCH_R0];
5115*202cdb0eSrobert
5116*202cdb0eSrobert if (regNum == UNW_REG_IP)
5117*202cdb0eSrobert return _registers.__pc;
5118*202cdb0eSrobert if (regNum == UNW_REG_SP)
5119*202cdb0eSrobert return _registers.__r[3];
5120*202cdb0eSrobert _LIBUNWIND_ABORT("unsupported loongarch register");
5121*202cdb0eSrobert }
5122*202cdb0eSrobert
setRegister(int regNum,uint64_t value)5123*202cdb0eSrobert inline void Registers_loongarch::setRegister(int regNum, uint64_t value) {
5124*202cdb0eSrobert if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
5125*202cdb0eSrobert _registers.__r[regNum - UNW_LOONGARCH_R0] = value;
5126*202cdb0eSrobert else if (regNum == UNW_REG_IP)
5127*202cdb0eSrobert _registers.__pc = value;
5128*202cdb0eSrobert else if (regNum == UNW_REG_SP)
5129*202cdb0eSrobert _registers.__r[3] = value;
5130*202cdb0eSrobert else
5131*202cdb0eSrobert _LIBUNWIND_ABORT("unsupported loongarch register");
5132*202cdb0eSrobert }
5133*202cdb0eSrobert
getRegisterName(int regNum)5134*202cdb0eSrobert inline const char *Registers_loongarch::getRegisterName(int regNum) {
5135*202cdb0eSrobert switch (regNum) {
5136*202cdb0eSrobert case UNW_REG_IP:
5137*202cdb0eSrobert return "$pc";
5138*202cdb0eSrobert case UNW_REG_SP:
5139*202cdb0eSrobert return "$sp";
5140*202cdb0eSrobert case UNW_LOONGARCH_R0:
5141*202cdb0eSrobert return "$r0";
5142*202cdb0eSrobert case UNW_LOONGARCH_R1:
5143*202cdb0eSrobert return "$r1";
5144*202cdb0eSrobert case UNW_LOONGARCH_R2:
5145*202cdb0eSrobert return "$r2";
5146*202cdb0eSrobert case UNW_LOONGARCH_R3:
5147*202cdb0eSrobert return "$r3";
5148*202cdb0eSrobert case UNW_LOONGARCH_R4:
5149*202cdb0eSrobert return "$r4";
5150*202cdb0eSrobert case UNW_LOONGARCH_R5:
5151*202cdb0eSrobert return "$r5";
5152*202cdb0eSrobert case UNW_LOONGARCH_R6:
5153*202cdb0eSrobert return "$r6";
5154*202cdb0eSrobert case UNW_LOONGARCH_R7:
5155*202cdb0eSrobert return "$r7";
5156*202cdb0eSrobert case UNW_LOONGARCH_R8:
5157*202cdb0eSrobert return "$r8";
5158*202cdb0eSrobert case UNW_LOONGARCH_R9:
5159*202cdb0eSrobert return "$r9";
5160*202cdb0eSrobert case UNW_LOONGARCH_R10:
5161*202cdb0eSrobert return "$r10";
5162*202cdb0eSrobert case UNW_LOONGARCH_R11:
5163*202cdb0eSrobert return "$r11";
5164*202cdb0eSrobert case UNW_LOONGARCH_R12:
5165*202cdb0eSrobert return "$r12";
5166*202cdb0eSrobert case UNW_LOONGARCH_R13:
5167*202cdb0eSrobert return "$r13";
5168*202cdb0eSrobert case UNW_LOONGARCH_R14:
5169*202cdb0eSrobert return "$r14";
5170*202cdb0eSrobert case UNW_LOONGARCH_R15:
5171*202cdb0eSrobert return "$r15";
5172*202cdb0eSrobert case UNW_LOONGARCH_R16:
5173*202cdb0eSrobert return "$r16";
5174*202cdb0eSrobert case UNW_LOONGARCH_R17:
5175*202cdb0eSrobert return "$r17";
5176*202cdb0eSrobert case UNW_LOONGARCH_R18:
5177*202cdb0eSrobert return "$r18";
5178*202cdb0eSrobert case UNW_LOONGARCH_R19:
5179*202cdb0eSrobert return "$r19";
5180*202cdb0eSrobert case UNW_LOONGARCH_R20:
5181*202cdb0eSrobert return "$r20";
5182*202cdb0eSrobert case UNW_LOONGARCH_R21:
5183*202cdb0eSrobert return "$r21";
5184*202cdb0eSrobert case UNW_LOONGARCH_R22:
5185*202cdb0eSrobert return "$r22";
5186*202cdb0eSrobert case UNW_LOONGARCH_R23:
5187*202cdb0eSrobert return "$r23";
5188*202cdb0eSrobert case UNW_LOONGARCH_R24:
5189*202cdb0eSrobert return "$r24";
5190*202cdb0eSrobert case UNW_LOONGARCH_R25:
5191*202cdb0eSrobert return "$r25";
5192*202cdb0eSrobert case UNW_LOONGARCH_R26:
5193*202cdb0eSrobert return "$r26";
5194*202cdb0eSrobert case UNW_LOONGARCH_R27:
5195*202cdb0eSrobert return "$r27";
5196*202cdb0eSrobert case UNW_LOONGARCH_R28:
5197*202cdb0eSrobert return "$r28";
5198*202cdb0eSrobert case UNW_LOONGARCH_R29:
5199*202cdb0eSrobert return "$r29";
5200*202cdb0eSrobert case UNW_LOONGARCH_R30:
5201*202cdb0eSrobert return "$r30";
5202*202cdb0eSrobert case UNW_LOONGARCH_R31:
5203*202cdb0eSrobert return "$r31";
5204*202cdb0eSrobert case UNW_LOONGARCH_F0:
5205*202cdb0eSrobert return "$f0";
5206*202cdb0eSrobert case UNW_LOONGARCH_F1:
5207*202cdb0eSrobert return "$f1";
5208*202cdb0eSrobert case UNW_LOONGARCH_F2:
5209*202cdb0eSrobert return "$f2";
5210*202cdb0eSrobert case UNW_LOONGARCH_F3:
5211*202cdb0eSrobert return "$f3";
5212*202cdb0eSrobert case UNW_LOONGARCH_F4:
5213*202cdb0eSrobert return "$f4";
5214*202cdb0eSrobert case UNW_LOONGARCH_F5:
5215*202cdb0eSrobert return "$f5";
5216*202cdb0eSrobert case UNW_LOONGARCH_F6:
5217*202cdb0eSrobert return "$f6";
5218*202cdb0eSrobert case UNW_LOONGARCH_F7:
5219*202cdb0eSrobert return "$f7";
5220*202cdb0eSrobert case UNW_LOONGARCH_F8:
5221*202cdb0eSrobert return "$f8";
5222*202cdb0eSrobert case UNW_LOONGARCH_F9:
5223*202cdb0eSrobert return "$f9";
5224*202cdb0eSrobert case UNW_LOONGARCH_F10:
5225*202cdb0eSrobert return "$f10";
5226*202cdb0eSrobert case UNW_LOONGARCH_F11:
5227*202cdb0eSrobert return "$f11";
5228*202cdb0eSrobert case UNW_LOONGARCH_F12:
5229*202cdb0eSrobert return "$f12";
5230*202cdb0eSrobert case UNW_LOONGARCH_F13:
5231*202cdb0eSrobert return "$f13";
5232*202cdb0eSrobert case UNW_LOONGARCH_F14:
5233*202cdb0eSrobert return "$f14";
5234*202cdb0eSrobert case UNW_LOONGARCH_F15:
5235*202cdb0eSrobert return "$f15";
5236*202cdb0eSrobert case UNW_LOONGARCH_F16:
5237*202cdb0eSrobert return "$f16";
5238*202cdb0eSrobert case UNW_LOONGARCH_F17:
5239*202cdb0eSrobert return "$f17";
5240*202cdb0eSrobert case UNW_LOONGARCH_F18:
5241*202cdb0eSrobert return "$f18";
5242*202cdb0eSrobert case UNW_LOONGARCH_F19:
5243*202cdb0eSrobert return "$f19";
5244*202cdb0eSrobert case UNW_LOONGARCH_F20:
5245*202cdb0eSrobert return "$f20";
5246*202cdb0eSrobert case UNW_LOONGARCH_F21:
5247*202cdb0eSrobert return "$f21";
5248*202cdb0eSrobert case UNW_LOONGARCH_F22:
5249*202cdb0eSrobert return "$f22";
5250*202cdb0eSrobert case UNW_LOONGARCH_F23:
5251*202cdb0eSrobert return "$f23";
5252*202cdb0eSrobert case UNW_LOONGARCH_F24:
5253*202cdb0eSrobert return "$f24";
5254*202cdb0eSrobert case UNW_LOONGARCH_F25:
5255*202cdb0eSrobert return "$f25";
5256*202cdb0eSrobert case UNW_LOONGARCH_F26:
5257*202cdb0eSrobert return "$f26";
5258*202cdb0eSrobert case UNW_LOONGARCH_F27:
5259*202cdb0eSrobert return "$f27";
5260*202cdb0eSrobert case UNW_LOONGARCH_F28:
5261*202cdb0eSrobert return "$f28";
5262*202cdb0eSrobert case UNW_LOONGARCH_F29:
5263*202cdb0eSrobert return "$f29";
5264*202cdb0eSrobert case UNW_LOONGARCH_F30:
5265*202cdb0eSrobert return "$f30";
5266*202cdb0eSrobert case UNW_LOONGARCH_F31:
5267*202cdb0eSrobert return "$f31";
5268*202cdb0eSrobert default:
5269*202cdb0eSrobert return "unknown register";
5270*202cdb0eSrobert }
5271*202cdb0eSrobert }
5272*202cdb0eSrobert
validFloatRegister(int regNum) const5273*202cdb0eSrobert inline bool Registers_loongarch::validFloatRegister(int regNum) const {
5274*202cdb0eSrobert if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31)
5275*202cdb0eSrobert return false;
5276*202cdb0eSrobert return true;
5277*202cdb0eSrobert }
5278*202cdb0eSrobert
getFloatRegister(int regNum) const5279*202cdb0eSrobert inline double Registers_loongarch::getFloatRegister(int regNum) const {
5280*202cdb0eSrobert #if __loongarch_frlen == 64
5281*202cdb0eSrobert assert(validFloatRegister(regNum));
5282*202cdb0eSrobert return _floats[regNum - UNW_LOONGARCH_F0];
5283*202cdb0eSrobert #else
5284*202cdb0eSrobert _LIBUNWIND_ABORT("libunwind not built with float support");
5285*202cdb0eSrobert #endif
5286*202cdb0eSrobert }
5287*202cdb0eSrobert
setFloatRegister(int regNum,double value)5288*202cdb0eSrobert inline void Registers_loongarch::setFloatRegister(int regNum, double value) {
5289*202cdb0eSrobert #if __loongarch_frlen == 64
5290*202cdb0eSrobert assert(validFloatRegister(regNum));
5291*202cdb0eSrobert _floats[regNum - UNW_LOONGARCH_F0] = value;
5292*202cdb0eSrobert #else
5293*202cdb0eSrobert _LIBUNWIND_ABORT("libunwind not built with float support");
5294*202cdb0eSrobert #endif
5295*202cdb0eSrobert }
5296*202cdb0eSrobert
validVectorRegister(int) const5297*202cdb0eSrobert inline bool Registers_loongarch::validVectorRegister(int) const {
5298*202cdb0eSrobert return false;
5299*202cdb0eSrobert }
5300*202cdb0eSrobert
getVectorRegister(int) const5301*202cdb0eSrobert inline v128 Registers_loongarch::getVectorRegister(int) const {
5302*202cdb0eSrobert _LIBUNWIND_ABORT("loongarch vector support not implemented");
5303*202cdb0eSrobert }
5304*202cdb0eSrobert
setVectorRegister(int,v128)5305*202cdb0eSrobert inline void Registers_loongarch::setVectorRegister(int, v128) {
5306*202cdb0eSrobert _LIBUNWIND_ABORT("loongarch vector support not implemented");
5307*202cdb0eSrobert }
5308*202cdb0eSrobert #endif //_LIBUNWIND_TARGET_LOONGARCH
5309*202cdb0eSrobert
5310f6c50668Spatrick } // namespace libunwind
5311f6c50668Spatrick
5312f6c50668Spatrick #endif // __REGISTERS_HPP__
5313